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_CHECKED_BTREE_OPCLASS   0x000001
 
#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000002
 
#define TCFLAGS_CHECKED_EQ_OPR   0x000004
 
#define TCFLAGS_CHECKED_LT_OPR   0x000008
 
#define TCFLAGS_CHECKED_GT_OPR   0x000010
 
#define TCFLAGS_CHECKED_CMP_PROC   0x000020
 
#define TCFLAGS_CHECKED_HASH_PROC   0x000040
 
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000080
 
#define TCFLAGS_CHECKED_ELEM_PROPERTIES   0x000100
 
#define TCFLAGS_HAVE_ELEM_EQUALITY   0x000200
 
#define TCFLAGS_HAVE_ELEM_COMPARE   0x000400
 
#define TCFLAGS_HAVE_ELEM_HASHING   0x000800
 
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING   0x001000
 
#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x002000
 
#define TCFLAGS_HAVE_FIELD_EQUALITY   0x004000
 
#define TCFLAGS_HAVE_FIELD_COMPARE   0x008000
 
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x010000
 
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x020000
 

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 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   0x000001

Definition at line 83 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_CMP_PROC

#define TCFLAGS_CHECKED_CMP_PROC   0x000020

Definition at line 88 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS

#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x010000

◆ TCFLAGS_CHECKED_ELEM_PROPERTIES

◆ TCFLAGS_CHECKED_EQ_OPR

#define TCFLAGS_CHECKED_EQ_OPR   0x000004

Definition at line 85 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_FIELD_PROPERTIES

#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x002000

◆ TCFLAGS_CHECKED_GT_OPR

#define TCFLAGS_CHECKED_GT_OPR   0x000010

Definition at line 87 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_EXTENDED_PROC

#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC   0x000080

Definition at line 90 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_OPCLASS

#define TCFLAGS_CHECKED_HASH_OPCLASS   0x000002

Definition at line 84 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_HASH_PROC

#define TCFLAGS_CHECKED_HASH_PROC   0x000040

Definition at line 89 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_CHECKED_LT_OPR

#define TCFLAGS_CHECKED_LT_OPR   0x000008

Definition at line 86 of file typcache.c.

Referenced by lookup_type_cache().

◆ TCFLAGS_DOMAIN_BASE_IS_COMPOSITE

#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE   0x020000

Definition at line 100 of file typcache.c.

Referenced by cache_record_field_properties(), and TypeCacheRelCallback().

◆ TCFLAGS_HAVE_ELEM_COMPARE

#define TCFLAGS_HAVE_ELEM_COMPARE   0x000400

Definition at line 93 of file typcache.c.

Referenced by array_element_has_compare(), and cache_array_element_properties().

◆ TCFLAGS_HAVE_ELEM_EQUALITY

#define TCFLAGS_HAVE_ELEM_EQUALITY   0x000200

Definition at line 92 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   0x001000

◆ TCFLAGS_HAVE_ELEM_HASHING

#define TCFLAGS_HAVE_ELEM_HASHING   0x000800

◆ TCFLAGS_HAVE_FIELD_COMPARE

#define TCFLAGS_HAVE_FIELD_COMPARE   0x008000

Definition at line 98 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_compare().

◆ TCFLAGS_HAVE_FIELD_EQUALITY

#define TCFLAGS_HAVE_FIELD_EQUALITY   0x004000

Definition at line 97 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_equality().

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

1325 {
1326  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1328  return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
1329 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:93
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1348

◆ array_element_has_equality()

static bool array_element_has_equality ( TypeCacheEntry typentry)
static

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

1317 {
1318  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1320  return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
1321 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1348
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:92

◆ array_element_has_extended_hashing()

static bool array_element_has_extended_hashing ( TypeCacheEntry typentry)
static

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

1341 {
1342  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1344  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1345 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:95
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1348

◆ array_element_has_hashing()

static bool array_element_has_hashing ( TypeCacheEntry typentry)
static

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

1333 {
1334  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1336  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1337 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1348
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:94

◆ assign_record_type_identifier()

uint64 assign_record_type_identifier ( Oid  type_id,
int32  typmod 
)

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

1848 {
1849  if (type_id != RECORDOID)
1850  {
1851  /*
1852  * It's a named composite type, so use the regular typcache.
1853  */
1854  TypeCacheEntry *typentry;
1855 
1856  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1857  if (typentry->tupDesc == NULL)
1858  ereport(ERROR,
1859  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1860  errmsg("type %s is not composite",
1861  format_type_be(type_id))));
1862  Assert(typentry->tupDesc_identifier != 0);
1863  return typentry->tupDesc_identifier;
1864  }
1865  else
1866  {
1867  /*
1868  * It's a transient record type, so look in our record-type table.
1869  */
1870  if (typmod >= 0 && typmod < RecordCacheArrayLen &&
1871  RecordCacheArray[typmod] != NULL)
1872  {
1873  Assert(RecordIdentifierArray[typmod] != 0);
1874  return RecordIdentifierArray[typmod];
1875  }
1876 
1877  /* For anonymous or unrecognized record type, generate a new ID */
1878  return ++tupledesc_id_counter;
1879  }
1880 }
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
static uint64 tupledesc_id_counter
Definition: typcache.c:277
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static int32 RecordCacheArrayLen
Definition: typcache.c:269
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define Assert(condition)
Definition: c.h:732
uint64 tupDesc_identifier
Definition: typcache.h:87
int errmsg(const char *fmt,...)
Definition: elog.c:784
TupleDesc tupDesc
Definition: typcache.h:86
#define TYPECACHE_TUPDESC
Definition: typcache.h:136
static uint64 * RecordIdentifierArray
Definition: typcache.c:268

◆ assign_record_type_typmod()

void assign_record_type_typmod ( TupleDesc  tupDesc)

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

1773 {
1774  RecordCacheEntry *recentry;
1775  TupleDesc entDesc;
1776  bool found;
1777  MemoryContext oldcxt;
1778 
1779  Assert(tupDesc->tdtypeid == RECORDOID);
1780 
1781  if (RecordCacheHash == NULL)
1782  {
1783  /* First time through: initialize the hash table */
1784  HASHCTL ctl;
1785 
1786  MemSet(&ctl, 0, sizeof(ctl));
1787  ctl.keysize = sizeof(TupleDesc); /* just the pointer */
1788  ctl.entrysize = sizeof(RecordCacheEntry);
1791  RecordCacheHash = hash_create("Record information cache", 64,
1792  &ctl,
1794 
1795  /* Also make sure CacheMemoryContext exists */
1796  if (!CacheMemoryContext)
1798  }
1799 
1800  /* Find or create a hashtable entry for this tuple descriptor */
1802  (void *) &tupDesc,
1803  HASH_ENTER, &found);
1804  if (found && recentry->tupdesc != NULL)
1805  {
1806  tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
1807  return;
1808  }
1809 
1810  /* Not present, so need to manufacture an entry */
1811  recentry->tupdesc = NULL;
1813 
1814  /* Look in the SharedRecordTypmodRegistry, if attached */
1815  entDesc = find_or_make_matching_shared_tupledesc(tupDesc);
1816  if (entDesc == NULL)
1817  {
1818  /* Reference-counted local cache only. */
1819  entDesc = CreateTupleDescCopy(tupDesc);
1820  entDesc->tdrefcount = 1;
1821  entDesc->tdtypmod = NextRecordTypmod++;
1822  }
1824  RecordCacheArray[entDesc->tdtypmod] = entDesc;
1825  recentry->tupdesc = entDesc;
1826 
1827  /* Assign a unique tupdesc identifier, too. */
1829 
1830  /* Update the caller's tuple descriptor. */
1831  tupDesc->tdtypmod = entDesc->tdtypmod;
1832 
1833  MemoryContextSwitchTo(oldcxt);
1834 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define HASH_ELEM
Definition: hsearch.h:87
static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc)
Definition: typcache.c:2531
struct RecordCacheEntry RecordCacheEntry
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:955
static uint64 tupledesc_id_counter
Definition: typcache.c:277
static HTAB * RecordCacheHash
Definition: typcache.c:264
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
int32 tdtypmod
Definition: tupdesc.h:83
static int32 NextRecordTypmod
Definition: typcache.c:270
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1524
Size keysize
Definition: hsearch.h:72
HashCompareFunc match
Definition: hsearch.h:75
static uint32 record_type_typmod_hash(const void *data, size_t size)
Definition: typcache.c:1745
#define Assert(condition)
Definition: c.h:732
#define HASH_COMPARE
Definition: hsearch.h:90
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:1756
TupleDesc tupdesc
Definition: typcache.c:149
int tdrefcount
Definition: tupdesc.h:84
static uint64 * RecordIdentifierArray
Definition: typcache.c:268
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ cache_array_element_properties()

static void cache_array_element_properties ( TypeCacheEntry typentry)
static

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

1349 {
1350  Oid elem_type = get_base_element_type(typentry->type_id);
1351 
1352  if (OidIsValid(elem_type))
1353  {
1354  TypeCacheEntry *elementry;
1355 
1356  elementry = lookup_type_cache(elem_type,
1361  if (OidIsValid(elementry->eq_opr))
1362  typentry->flags |= TCFLAGS_HAVE_ELEM_EQUALITY;
1363  if (OidIsValid(elementry->cmp_proc))
1364  typentry->flags |= TCFLAGS_HAVE_ELEM_COMPARE;
1365  if (OidIsValid(elementry->hash_proc))
1366  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1367  if (OidIsValid(elementry->hash_extended_proc))
1369  }
1371 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:93
#define TYPECACHE_EQ_OPR
Definition: typcache.h:128
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:95
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
Oid hash_extended_proc
Definition: typcache.h:63
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:142
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define TYPECACHE_CMP_PROC
Definition: typcache.h:131
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:92
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:94
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2599
#define TYPECACHE_HASH_PROC
Definition: typcache.h:132

◆ cache_range_element_properties()

static void cache_range_element_properties ( TypeCacheEntry typentry)
static

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

1497 {
1498  /* load up subtype link if we didn't already */
1499  if (typentry->rngelemtype == NULL &&
1500  typentry->typtype == TYPTYPE_RANGE)
1501  load_rangetype_info(typentry);
1502 
1503  if (typentry->rngelemtype != NULL)
1504  {
1505  TypeCacheEntry *elementry;
1506 
1507  /* might need to calculate subtype's hash function properties */
1508  elementry = lookup_type_cache(typentry->rngelemtype->type_id,
1511  if (OidIsValid(elementry->hash_proc))
1512  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1513  if (OidIsValid(elementry->hash_extended_proc))
1515  }
1517 }
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:95
#define OidIsValid(objectId)
Definition: c.h:638
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
Oid hash_extended_proc
Definition: typcache.h:63
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:95
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:142
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:820
char typtype
Definition: typcache.h:41
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:94
#define TYPECACHE_HASH_PROC
Definition: typcache.h:132

◆ cache_record_field_properties()

static void cache_record_field_properties ( TypeCacheEntry typentry)
static

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

1395 {
1396  /*
1397  * For type RECORD, we can't really tell what will work, since we don't
1398  * have access here to the specific anonymous type. Just assume that
1399  * everything will (we may get a failure at runtime ...)
1400  */
1401  if (typentry->type_id == RECORDOID)
1402  typentry->flags |= (TCFLAGS_HAVE_FIELD_EQUALITY |
1404  else if (typentry->typtype == TYPTYPE_COMPOSITE)
1405  {
1406  TupleDesc tupdesc;
1407  int newflags;
1408  int i;
1409 
1410  /* Fetch composite type's tupdesc if we don't have it already */
1411  if (typentry->tupDesc == NULL)
1412  load_typcache_tupdesc(typentry);
1413  tupdesc = typentry->tupDesc;
1414 
1415  /* Must bump the refcount while we do additional catalog lookups */
1416  IncrTupleDescRefCount(tupdesc);
1417 
1418  /* Have each property if all non-dropped fields have the property */
1419  newflags = (TCFLAGS_HAVE_FIELD_EQUALITY |
1421  for (i = 0; i < tupdesc->natts; i++)
1422  {
1423  TypeCacheEntry *fieldentry;
1424  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1425 
1426  if (attr->attisdropped)
1427  continue;
1428 
1429  fieldentry = lookup_type_cache(attr->atttypid,
1432  if (!OidIsValid(fieldentry->eq_opr))
1433  newflags &= ~TCFLAGS_HAVE_FIELD_EQUALITY;
1434  if (!OidIsValid(fieldentry->cmp_proc))
1435  newflags &= ~TCFLAGS_HAVE_FIELD_COMPARE;
1436 
1437  /* We can drop out of the loop once we disprove all bits */
1438  if (newflags == 0)
1439  break;
1440  }
1441  typentry->flags |= newflags;
1442 
1443  DecrTupleDescRefCount(tupdesc);
1444  }
1445  else if (typentry->typtype == TYPTYPE_DOMAIN)
1446  {
1447  /* If it's domain over composite, copy base type's properties */
1448  TypeCacheEntry *baseentry;
1449 
1450  /* load up basetype info if we didn't already */
1451  if (typentry->domainBaseType == InvalidOid)
1452  {
1453  typentry->domainBaseTypmod = -1;
1454  typentry->domainBaseType =
1455  getBaseTypeAndTypmod(typentry->type_id,
1456  &typentry->domainBaseTypmod);
1457  }
1458  baseentry = lookup_type_cache(typentry->domainBaseType,
1461  if (baseentry->typtype == TYPTYPE_COMPOSITE)
1462  {
1464  typentry->flags |= baseentry->flags & (TCFLAGS_HAVE_FIELD_EQUALITY |
1466  }
1467  }
1469 }
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:786
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:375
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2316
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:96
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:100
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define TYPECACHE_EQ_OPR
Definition: typcache.h:128
#define OidIsValid(objectId)
Definition: c.h:638
Oid domainBaseType
Definition: typcache.h:105
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:98
int32 domainBaseTypmod
Definition: typcache.h:106
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:97
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define InvalidOid
Definition: postgres_ext.h:36
#define TYPECACHE_CMP_PROC
Definition: typcache.h:131
char typtype
Definition: typcache.h:41
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:393
int i
TupleDesc tupDesc
Definition: typcache.h:86

◆ compare_values_of_enum()

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

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

2248 {
2249  TypeCacheEnumData *enumdata;
2250  EnumItem *item1;
2251  EnumItem *item2;
2252 
2253  /*
2254  * Equal OIDs are certainly equal --- this case was probably handled by
2255  * our caller, but we may as well check.
2256  */
2257  if (arg1 == arg2)
2258  return 0;
2259 
2260  /* Load up the cache if first time through */
2261  if (tcache->enumData == NULL)
2262  load_enum_cache_data(tcache);
2263  enumdata = tcache->enumData;
2264 
2265  /*
2266  * If both OIDs are known-sorted, we can just compare them directly.
2267  */
2268  if (enum_known_sorted(enumdata, arg1) &&
2269  enum_known_sorted(enumdata, arg2))
2270  {
2271  if (arg1 < arg2)
2272  return -1;
2273  else
2274  return 1;
2275  }
2276 
2277  /*
2278  * Slow path: we have to identify their actual sort-order positions.
2279  */
2280  item1 = find_enumitem(enumdata, arg1);
2281  item2 = find_enumitem(enumdata, arg2);
2282 
2283  if (item1 == NULL || item2 == NULL)
2284  {
2285  /*
2286  * We couldn't find one or both values. That means the enum has
2287  * changed under us, so re-initialize the cache and try again. We
2288  * don't bother retrying the known-sorted case in this path.
2289  */
2290  load_enum_cache_data(tcache);
2291  enumdata = tcache->enumData;
2292 
2293  item1 = find_enumitem(enumdata, arg1);
2294  item2 = find_enumitem(enumdata, arg2);
2295 
2296  /*
2297  * If we still can't find the values, complain: we must have corrupt
2298  * data.
2299  */
2300  if (item1 == NULL)
2301  elog(ERROR, "enum value %u not found in cache for enum %s",
2302  arg1, format_type_be(tcache->type_id));
2303  if (item2 == NULL)
2304  elog(ERROR, "enum value %u not found in cache for enum %s",
2305  arg2, format_type_be(tcache->type_id));
2306  }
2307 
2308  if (item1->sort_order < item2->sort_order)
2309  return -1;
2310  else if (item1->sort_order > item2->sort_order)
2311  return 1;
2312  else
2313  return 0;
2314 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:121
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
#define ERROR
Definition: elog.h:43
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2218
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:2475
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:2320
float4 sort_order
Definition: typcache.c:125
#define elog(elevel,...)
Definition: elog.h:226

◆ dccref_deletion_callback()

static void dccref_deletion_callback ( void *  arg)
static

Definition at line 1143 of file typcache.c.

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

Referenced by InitDomainConstraintRef().

1144 {
1146  DomainConstraintCache *dcc = ref->dcc;
1147 
1148  /* Paranoia --- be sure link is nulled before trying to release */
1149  if (dcc)
1150  {
1151  ref->constraints = NIL;
1152  ref->dcc = NULL;
1153  decr_dcc_refcount(dcc);
1154  }
1155 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:162
void * arg
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1132

◆ dcs_cmp()

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

Definition at line 1119 of file typcache.c.

Referenced by load_domaintype_info().

1120 {
1121  const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a;
1122  const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b;
1123 
1124  return strcmp((*ca)->name, (*cb)->name);
1125 }

◆ decr_dcc_refcount()

static void decr_dcc_refcount ( DomainConstraintCache dcc)
static

Definition at line 1132 of file typcache.c.

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

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

1133 {
1134  Assert(dcc->dccRefCount > 0);
1135  if (--(dcc->dccRefCount) <= 0)
1137 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
MemoryContext dccContext
Definition: typcache.c:117
#define Assert(condition)
Definition: c.h:732

◆ DomainHasConstraints()

bool DomainHasConstraints ( Oid  type_id)

Definition at line 1289 of file typcache.c.

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

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

1290 {
1291  TypeCacheEntry *typentry;
1292 
1293  /*
1294  * Note: a side effect is to cause the typcache's domain data to become
1295  * valid. This is fine since we'll likely need it soon if there is any.
1296  */
1297  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_CONSTR_INFO);
1298 
1299  return (typentry->domainData != NULL);
1300 }
DomainConstraintCache * domainData
Definition: typcache.h:112
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:141

◆ ensure_record_cache_typmod_slot_exists()

static void ensure_record_cache_typmod_slot_exists ( int32  typmod)
static

Definition at line 1524 of file typcache.c.

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

Referenced by assign_record_type_typmod(), and lookup_rowtype_tupdesc_internal().

1525 {
1526  if (RecordCacheArray == NULL)
1527  {
1530  RecordIdentifierArray = (uint64 *)
1531  MemoryContextAllocZero(CacheMemoryContext, 64 * sizeof(uint64));
1532  RecordCacheArrayLen = 64;
1533  }
1534 
1535  if (typmod >= RecordCacheArrayLen)
1536  {
1537  int32 newlen = RecordCacheArrayLen * 2;
1538 
1539  while (typmod >= newlen)
1540  newlen *= 2;
1541 
1543  newlen * sizeof(TupleDesc));
1545  (newlen - RecordCacheArrayLen) * sizeof(TupleDesc));
1547  newlen * sizeof(uint64));
1549  (newlen - RecordCacheArrayLen) * sizeof(uint64));
1550  RecordCacheArrayLen = newlen;
1551  }
1552 }
signed int int32
Definition: c.h:346
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
static int32 RecordCacheArrayLen
Definition: typcache.c:269
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:814
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
static uint64 * RecordIdentifierArray
Definition: typcache.c:268
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ enum_known_sorted()

static bool enum_known_sorted ( TypeCacheEnumData enumdata,
Oid  arg 
)
inlinestatic

Definition at line 2218 of file typcache.c.

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

Referenced by compare_values_of_enum().

2219 {
2220  Oid offset;
2221 
2222  if (arg < enumdata->bitmap_base)
2223  return false;
2224  offset = arg - enumdata->bitmap_base;
2225  if (offset > (Oid) INT_MAX)
2226  return false;
2227  return bms_is_member((int) offset, enumdata->sorted_values);
2228 }
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * sorted_values
Definition: typcache.c:131
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 2492 of file typcache.c.

References EnumItem::enum_oid.

Referenced by find_enumitem(), and load_enum_cache_data().

2493 {
2494  const EnumItem *l = (const EnumItem *) left;
2495  const EnumItem *r = (const EnumItem *) right;
2496 
2497  if (l->enum_oid < r->enum_oid)
2498  return -1;
2499  else if (l->enum_oid > r->enum_oid)
2500  return 1;
2501  else
2502  return 0;
2503 }
Oid enum_oid
Definition: typcache.c:124

◆ find_enumitem()

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

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

2476 {
2477  EnumItem srch;
2478 
2479  /* On some versions of Solaris, bsearch of zero items dumps core */
2480  if (enumdata->num_values <= 0)
2481  return NULL;
2482 
2483  srch.enum_oid = arg;
2484  return bsearch(&srch, enumdata->enum_values, enumdata->num_values,
2485  sizeof(EnumItem), enum_oid_cmp);
2486 }
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:133
Oid enum_oid
Definition: typcache.c:124
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2492
void * arg

◆ find_or_make_matching_shared_tupledesc()

static TupleDesc find_or_make_matching_shared_tupledesc ( TupleDesc  tupdesc)
static

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

2532 {
2533  TupleDesc result;
2535  SharedRecordTableEntry *record_table_entry;
2536  SharedTypmodTableEntry *typmod_table_entry;
2537  dsa_pointer shared_dp;
2538  bool found;
2539  uint32 typmod;
2540 
2541  /* If not even attached, nothing to do. */
2543  return NULL;
2544 
2545  /* Try to find a matching tuple descriptor in the record table. */
2546  key.shared = false;
2547  key.u.local_tupdesc = tupdesc;
2548  record_table_entry = (SharedRecordTableEntry *)
2550  if (record_table_entry)
2551  {
2552  Assert(record_table_entry->key.shared);
2554  record_table_entry);
2555  result = (TupleDesc)
2557  record_table_entry->key.u.shared_tupdesc);
2558  Assert(result->tdrefcount == -1);
2559 
2560  return result;
2561  }
2562 
2563  /* Allocate a new typmod number. This will be wasted if we error out. */
2564  typmod = (int)
2566  1);
2567 
2568  /* Copy the TupleDesc into shared memory. */
2569  shared_dp = share_tupledesc(CurrentSession->area, tupdesc, typmod);
2570 
2571  /*
2572  * Create an entry in the typmod table so that others will understand this
2573  * typmod number.
2574  */
2575  PG_TRY();
2576  {
2577  typmod_table_entry = (SharedTypmodTableEntry *)
2579  &typmod, &found);
2580  if (found)
2581  elog(ERROR, "cannot create duplicate shared record typmod");
2582  }
2583  PG_CATCH();
2584  {
2585  dsa_free(CurrentSession->area, shared_dp);
2586  PG_RE_THROW();
2587  }
2588  PG_END_TRY();
2589  typmod_table_entry->typmod = typmod;
2590  typmod_table_entry->shared_tupdesc = shared_dp;
2592  typmod_table_entry);
2593 
2594  /*
2595  * Finally create an entry in the record table so others with matching
2596  * tuple descriptors can reuse the typmod.
2597  */
2598  record_table_entry = (SharedRecordTableEntry *)
2600  &found);
2601  if (found)
2602  {
2603  /*
2604  * Someone concurrently inserted a matching tuple descriptor since the
2605  * first time we checked. Use that one instead.
2606  */
2608  record_table_entry);
2609 
2610  /* Might as well free up the space used by the one we created. */
2612  &typmod);
2613  Assert(found);
2614  dsa_free(CurrentSession->area, shared_dp);
2615 
2616  /* Return the one we found. */
2617  Assert(record_table_entry->key.shared);
2618  result = (TupleDesc)
2620  record_table_entry->key.shared);
2621  Assert(result->tdrefcount == -1);
2622 
2623  return result;
2624  }
2625 
2626  /* Store it and return it. */
2627  record_table_entry->key.shared = true;
2628  record_table_entry->key.u.shared_tupdesc = shared_dp;
2630  record_table_entry);
2631  result = (TupleDesc)
2632  dsa_get_address(CurrentSession->area, shared_dp);
2633  Assert(result->tdrefcount == -1);
2634 
2635  return result;
2636 }
Session * CurrentSession
Definition: session.c:48
dshash_table * shared_record_table
Definition: session.h:32
SharedRecordTableKey key
Definition: typcache.c:188
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:198
pg_atomic_uint32 next_typmod
Definition: typcache.c:163
#define ERROR
Definition: elog.h:43
dsa_area * area
Definition: session.h:28
unsigned int uint32
Definition: c.h:358
dsa_pointer shared_tupdesc
Definition: typcache.c:177
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
union SharedRecordTableKey::@36 u
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:331
#define PG_CATCH()
Definition: elog.h:310
bool dshash_delete_key(dshash_table *hash_table, const void *key)
Definition: dshash.c:502
#define Assert(condition)
Definition: c.h:732
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2510
#define PG_RE_THROW()
Definition: elog.h:331
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:226
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:176
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:301
#define PG_END_TRY()
Definition: elog.h:317

◆ InitDomainConstraintRef()

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

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

1204 {
1205  /* Look up the typcache entry --- we assume it survives indefinitely */
1207  ref->need_exprstate = need_exprstate;
1208  /* For safety, establish the callback before acquiring a refcount */
1209  ref->refctx = refctx;
1210  ref->dcc = NULL;
1212  ref->callback.arg = (void *) ref;
1214  /* Acquire refcount if there are constraints, and set up exported list */
1215  if (ref->tcache->domainData)
1216  {
1217  ref->dcc = ref->tcache->domainData;
1218  ref->dcc->dccRefCount++;
1219  if (ref->need_exprstate)
1221  ref->refctx);
1222  else
1223  ref->constraints = ref->dcc->constraints;
1224  }
1225  else
1226  ref->constraints = NIL;
1227 }
MemoryContextCallback callback
Definition: typcache.h:163
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:162
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:1143
DomainConstraintCache * domainData
Definition: typcache.h:112
MemoryContext refctx
Definition: typcache.h:157
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1164
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:141
TypeCacheEntry * tcache
Definition: typcache.h:158
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:285

◆ load_domaintype_info()

static void load_domaintype_info ( TypeCacheEntry typentry)
static

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

884 {
885  Oid typeOid = typentry->type_id;
887  bool notNull = false;
888  DomainConstraintState **ccons;
889  int cconslen;
890  Relation conRel;
891  MemoryContext oldcxt;
892 
893  /*
894  * If we're here, any existing constraint info is stale, so release it.
895  * For safety, be sure to null the link before trying to delete the data.
896  */
897  if (typentry->domainData)
898  {
899  dcc = typentry->domainData;
900  typentry->domainData = NULL;
901  decr_dcc_refcount(dcc);
902  }
903 
904  /*
905  * We try to optimize the common case of no domain constraints, so don't
906  * create the dcc object and context until we find a constraint. Likewise
907  * for the temp sorting array.
908  */
909  dcc = NULL;
910  ccons = NULL;
911  cconslen = 0;
912 
913  /*
914  * Scan pg_constraint for relevant constraints. We want to find
915  * constraints for not just this domain, but any ancestor domains, so the
916  * outer loop crawls up the domain stack.
917  */
918  conRel = table_open(ConstraintRelationId, AccessShareLock);
919 
920  for (;;)
921  {
922  HeapTuple tup;
923  HeapTuple conTup;
924  Form_pg_type typTup;
925  int nccons = 0;
926  ScanKeyData key[1];
927  SysScanDesc scan;
928 
929  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
930  if (!HeapTupleIsValid(tup))
931  elog(ERROR, "cache lookup failed for type %u", typeOid);
932  typTup = (Form_pg_type) GETSTRUCT(tup);
933 
934  if (typTup->typtype != TYPTYPE_DOMAIN)
935  {
936  /* Not a domain, so done */
937  ReleaseSysCache(tup);
938  break;
939  }
940 
941  /* Test for NOT NULL Constraint */
942  if (typTup->typnotnull)
943  notNull = true;
944 
945  /* Look for CHECK Constraints on this domain */
946  ScanKeyInit(&key[0],
947  Anum_pg_constraint_contypid,
948  BTEqualStrategyNumber, F_OIDEQ,
949  ObjectIdGetDatum(typeOid));
950 
951  scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
952  NULL, 1, key);
953 
954  while (HeapTupleIsValid(conTup = systable_getnext(scan)))
955  {
957  Datum val;
958  bool isNull;
959  char *constring;
960  Expr *check_expr;
962 
963  /* Ignore non-CHECK constraints (presently, shouldn't be any) */
964  if (c->contype != CONSTRAINT_CHECK)
965  continue;
966 
967  /* Not expecting conbin to be NULL, but we'll test for it anyway */
968  val = fastgetattr(conTup, Anum_pg_constraint_conbin,
969  conRel->rd_att, &isNull);
970  if (isNull)
971  elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
972  NameStr(typTup->typname), NameStr(c->conname));
973 
974  /* Convert conbin to C string in caller context */
975  constring = TextDatumGetCString(val);
976 
977  /* Create the DomainConstraintCache object and context if needed */
978  if (dcc == NULL)
979  {
980  MemoryContext cxt;
981 
983  "Domain constraints",
985  dcc = (DomainConstraintCache *)
987  dcc->constraints = NIL;
988  dcc->dccContext = cxt;
989  dcc->dccRefCount = 0;
990  }
991 
992  /* Create node trees in DomainConstraintCache's context */
993  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
994 
995  check_expr = (Expr *) stringToNode(constring);
996 
997  /*
998  * Plan the expression, since ExecInitExpr will expect that.
999  *
1000  * Note: caching the result of expression_planner() is not very
1001  * good practice. Ideally we'd use a CachedExpression here so
1002  * that we would react promptly to, eg, changes in inlined
1003  * functions. However, because we don't support mutable domain
1004  * CHECK constraints, it's not really clear that it's worth the
1005  * extra overhead to do that.
1006  */
1007  check_expr = expression_planner(check_expr);
1008 
1011  r->name = pstrdup(NameStr(c->conname));
1012  r->check_expr = check_expr;
1013  r->check_exprstate = NULL;
1014 
1015  MemoryContextSwitchTo(oldcxt);
1016 
1017  /* Accumulate constraints in an array, for sorting below */
1018  if (ccons == NULL)
1019  {
1020  cconslen = 8;
1021  ccons = (DomainConstraintState **)
1022  palloc(cconslen * sizeof(DomainConstraintState *));
1023  }
1024  else if (nccons >= cconslen)
1025  {
1026  cconslen *= 2;
1027  ccons = (DomainConstraintState **)
1028  repalloc(ccons, cconslen * sizeof(DomainConstraintState *));
1029  }
1030  ccons[nccons++] = r;
1031  }
1032 
1033  systable_endscan(scan);
1034 
1035  if (nccons > 0)
1036  {
1037  /*
1038  * Sort the items for this domain, so that CHECKs are applied in a
1039  * deterministic order.
1040  */
1041  if (nccons > 1)
1042  qsort(ccons, nccons, sizeof(DomainConstraintState *), dcs_cmp);
1043 
1044  /*
1045  * Now attach them to the overall list. Use lcons() here because
1046  * constraints of parent domains should be applied earlier.
1047  */
1048  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1049  while (nccons > 0)
1050  dcc->constraints = lcons(ccons[--nccons], dcc->constraints);
1051  MemoryContextSwitchTo(oldcxt);
1052  }
1053 
1054  /* loop to next domain in stack */
1055  typeOid = typTup->typbasetype;
1056  ReleaseSysCache(tup);
1057  }
1058 
1059  table_close(conRel, AccessShareLock);
1060 
1061  /*
1062  * Only need to add one NOT NULL check regardless of how many domains in
1063  * the stack request it.
1064  */
1065  if (notNull)
1066  {
1068 
1069  /* Create the DomainConstraintCache object and context if needed */
1070  if (dcc == NULL)
1071  {
1072  MemoryContext cxt;
1073 
1075  "Domain constraints",
1077  dcc = (DomainConstraintCache *)
1079  dcc->constraints = NIL;
1080  dcc->dccContext = cxt;
1081  dcc->dccRefCount = 0;
1082  }
1083 
1084  /* Create node trees in DomainConstraintCache's context */
1085  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
1086 
1088 
1090  r->name = pstrdup("NOT NULL");
1091  r->check_expr = NULL;
1092  r->check_exprstate = NULL;
1093 
1094  /* lcons to apply the nullness check FIRST */
1095  dcc->constraints = lcons(r, dcc->constraints);
1096 
1097  MemoryContextSwitchTo(oldcxt);
1098  }
1099 
1100  /*
1101  * If we made a constraint object, move it into CacheMemoryContext and
1102  * attach it to the typcache entry.
1103  */
1104  if (dcc)
1105  {
1107  typentry->domainData = dcc;
1108  dcc->dccRefCount++; /* count the typcache's reference */
1109  }
1110 
1111  /* Either way, the typcache entry's domain data is now valid. */
1113 }
#define NIL
Definition: pg_list.h:65
#define AllocSetContextCreate
Definition: memutils.h:169
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
MemoryContext dccContext
Definition: typcache.c:117
DomainConstraintType constrainttype
Definition: execnodes.h:904
DomainConstraintCache * domainData
Definition: typcache.h:112
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:354
char * pstrdup(const char *in)
Definition: mcxt.c:1161
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:201
Expr * expression_planner(Expr *expr)
Definition: planner.c:6046
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:1119
unsigned int Oid
Definition: postgres_ext.h:31
#define ConstraintTypidIndexId
Definition: indexing.h:130
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * c
ExprState * check_exprstate
Definition: execnodes.h:907
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
TupleDesc rd_att
Definition: rel.h:84
List * lcons(void *datum, List *list)
Definition: list.c:453
#define makeNode(_type_)
Definition: nodes.h:573
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:251
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:99
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
void * palloc(Size size)
Definition: mcxt.c:924
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
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:492
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1132
long val
Definition: informix.c:684
#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 2320 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().

2321 {
2322  TypeCacheEnumData *enumdata;
2323  Relation enum_rel;
2324  SysScanDesc enum_scan;
2325  HeapTuple enum_tuple;
2326  ScanKeyData skey;
2327  EnumItem *items;
2328  int numitems;
2329  int maxitems;
2330  Oid bitmap_base;
2331  Bitmapset *bitmap;
2332  MemoryContext oldcxt;
2333  int bm_size,
2334  start_pos;
2335 
2336  /* Check that this is actually an enum */
2337  if (tcache->typtype != TYPTYPE_ENUM)
2338  ereport(ERROR,
2339  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2340  errmsg("%s is not an enum",
2341  format_type_be(tcache->type_id))));
2342 
2343  /*
2344  * Read all the information for members of the enum type. We collect the
2345  * info in working memory in the caller's context, and then transfer it to
2346  * permanent memory in CacheMemoryContext. This minimizes the risk of
2347  * leaking memory from CacheMemoryContext in the event of an error partway
2348  * through.
2349  */
2350  maxitems = 64;
2351  items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
2352  numitems = 0;
2353 
2354  /* Scan pg_enum for the members of the target enum type. */
2355  ScanKeyInit(&skey,
2356  Anum_pg_enum_enumtypid,
2357  BTEqualStrategyNumber, F_OIDEQ,
2358  ObjectIdGetDatum(tcache->type_id));
2359 
2360  enum_rel = table_open(EnumRelationId, AccessShareLock);
2361  enum_scan = systable_beginscan(enum_rel,
2363  true, NULL,
2364  1, &skey);
2365 
2366  while (HeapTupleIsValid(enum_tuple = systable_getnext(enum_scan)))
2367  {
2368  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enum_tuple);
2369 
2370  if (numitems >= maxitems)
2371  {
2372  maxitems *= 2;
2373  items = (EnumItem *) repalloc(items, sizeof(EnumItem) * maxitems);
2374  }
2375  items[numitems].enum_oid = en->oid;
2376  items[numitems].sort_order = en->enumsortorder;
2377  numitems++;
2378  }
2379 
2380  systable_endscan(enum_scan);
2381  table_close(enum_rel, AccessShareLock);
2382 
2383  /* Sort the items into OID order */
2384  qsort(items, numitems, sizeof(EnumItem), enum_oid_cmp);
2385 
2386  /*
2387  * Here, we create a bitmap listing a subset of the enum's OIDs that are
2388  * known to be in order and can thus be compared with just OID comparison.
2389  *
2390  * The point of this is that the enum's initial OIDs were certainly in
2391  * order, so there is some subset that can be compared via OID comparison;
2392  * and we'd rather not do binary searches unnecessarily.
2393  *
2394  * This is somewhat heuristic, and might identify a subset of OIDs that
2395  * isn't exactly what the type started with. That's okay as long as the
2396  * subset is correctly sorted.
2397  */
2398  bitmap_base = InvalidOid;
2399  bitmap = NULL;
2400  bm_size = 1; /* only save sets of at least 2 OIDs */
2401 
2402  for (start_pos = 0; start_pos < numitems - 1; start_pos++)
2403  {
2404  /*
2405  * Identify longest sorted subsequence starting at start_pos
2406  */
2407  Bitmapset *this_bitmap = bms_make_singleton(0);
2408  int this_bm_size = 1;
2409  Oid start_oid = items[start_pos].enum_oid;
2410  float4 prev_order = items[start_pos].sort_order;
2411  int i;
2412 
2413  for (i = start_pos + 1; i < numitems; i++)
2414  {
2415  Oid offset;
2416 
2417  offset = items[i].enum_oid - start_oid;
2418  /* quit if bitmap would be too large; cutoff is arbitrary */
2419  if (offset >= 8192)
2420  break;
2421  /* include the item if it's in-order */
2422  if (items[i].sort_order > prev_order)
2423  {
2424  prev_order = items[i].sort_order;
2425  this_bitmap = bms_add_member(this_bitmap, (int) offset);
2426  this_bm_size++;
2427  }
2428  }
2429 
2430  /* Remember it if larger than previous best */
2431  if (this_bm_size > bm_size)
2432  {
2433  bms_free(bitmap);
2434  bitmap_base = start_oid;
2435  bitmap = this_bitmap;
2436  bm_size = this_bm_size;
2437  }
2438  else
2439  bms_free(this_bitmap);
2440 
2441  /*
2442  * Done if it's not possible to find a longer sequence in the rest of
2443  * the list. In typical cases this will happen on the first
2444  * iteration, which is why we create the bitmaps on the fly instead of
2445  * doing a second pass over the list.
2446  */
2447  if (bm_size >= (numitems - start_pos - 1))
2448  break;
2449  }
2450 
2451  /* OK, copy the data into CacheMemoryContext */
2453  enumdata = (TypeCacheEnumData *)
2454  palloc(offsetof(TypeCacheEnumData, enum_values) +
2455  numitems * sizeof(EnumItem));
2456  enumdata->bitmap_base = bitmap_base;
2457  enumdata->sorted_values = bms_copy(bitmap);
2458  enumdata->num_values = numitems;
2459  memcpy(enumdata->enum_values, items, numitems * sizeof(EnumItem));
2460  MemoryContextSwitchTo(oldcxt);
2461 
2462  pfree(items);
2463  bms_free(bitmap);
2464 
2465  /* And link the finished cache struct into the typcache */
2466  if (tcache->enumData != NULL)
2467  pfree(tcache->enumData);
2468  tcache->enumData = enumdata;
2469 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:121
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#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:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
#define EnumTypIdLabelIndexId
Definition: indexing.h:161
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
Bitmapset * sorted_values
Definition: typcache.c:131
void pfree(void *pointer)
Definition: mcxt.c:1031
#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
#define ereport(elevel, rest)
Definition: elog.h:141
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:133
float float4
Definition: c.h:490
Oid enum_oid
Definition: typcache.c:124
#define InvalidOid
Definition: postgres_ext.h:36
char typtype
Definition: typcache.h:41
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:1044
float4 sort_order
Definition: typcache.c:125
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:2492
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:492
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define offsetof(type, field)
Definition: c.h:655
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ load_rangetype_info()

static void load_rangetype_info ( TypeCacheEntry typentry)
static

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

821 {
822  Form_pg_range pg_range;
823  HeapTuple tup;
824  Oid subtypeOid;
825  Oid opclassOid;
826  Oid canonicalOid;
827  Oid subdiffOid;
828  Oid opfamilyOid;
829  Oid opcintype;
830  Oid cmpFnOid;
831 
832  /* get information from pg_range */
834  /* should not fail, since we already checked typtype ... */
835  if (!HeapTupleIsValid(tup))
836  elog(ERROR, "cache lookup failed for range type %u",
837  typentry->type_id);
838  pg_range = (Form_pg_range) GETSTRUCT(tup);
839 
840  subtypeOid = pg_range->rngsubtype;
841  typentry->rng_collation = pg_range->rngcollation;
842  opclassOid = pg_range->rngsubopc;
843  canonicalOid = pg_range->rngcanonical;
844  subdiffOid = pg_range->rngsubdiff;
845 
846  ReleaseSysCache(tup);
847 
848  /* get opclass properties and look up the comparison function */
849  opfamilyOid = get_opclass_family(opclassOid);
850  opcintype = get_opclass_input_type(opclassOid);
851 
852  cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
853  BTORDER_PROC);
854  if (!RegProcedureIsValid(cmpFnOid))
855  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
856  BTORDER_PROC, opcintype, opcintype, opfamilyOid);
857 
858  /* set up cached fmgrinfo structs */
859  fmgr_info_cxt(cmpFnOid, &typentry->rng_cmp_proc_finfo,
861  if (OidIsValid(canonicalOid))
862  fmgr_info_cxt(canonicalOid, &typentry->rng_canonical_finfo,
864  if (OidIsValid(subdiffOid))
865  fmgr_info_cxt(subdiffOid, &typentry->rng_subdiff_finfo,
867 
868  /* Lastly, set up link to the element type --- this marks data valid */
869  typentry->rngelemtype = lookup_type_cache(subtypeOid, 0);
870 }
FormData_pg_range * Form_pg_range
Definition: pg_range.h:55
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:97
#define BTORDER_PROC
Definition: nbtree.h:392
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
FmgrInfo rng_subdiff_finfo
Definition: typcache.h:99
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RegProcedureIsValid(p)
Definition: c.h:640
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
FmgrInfo rng_canonical_finfo
Definition: typcache.h:98
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:95
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
Oid rng_collation
Definition: typcache.h:96
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1019
#define elog(elevel,...)
Definition: elog.h:226
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1041

◆ load_typcache_tupdesc()

static void load_typcache_tupdesc ( TypeCacheEntry typentry)
static

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

787 {
788  Relation rel;
789 
790  if (!OidIsValid(typentry->typrelid)) /* should not happen */
791  elog(ERROR, "invalid typrelid for composite type %u",
792  typentry->type_id);
793  rel = relation_open(typentry->typrelid, AccessShareLock);
794  Assert(rel->rd_rel->reltype == typentry->type_id);
795 
796  /*
797  * Link to the tupdesc and increment its refcount (we assert it's a
798  * refcounted descriptor). We don't use IncrTupleDescRefCount() for this,
799  * because the reference mustn't be entered in the current resource owner;
800  * it can outlive the current query.
801  */
802  typentry->tupDesc = RelationGetDescr(rel);
803 
804  Assert(typentry->tupDesc->tdrefcount > 0);
805  typentry->tupDesc->tdrefcount++;
806 
807  /*
808  * In future, we could take some pains to not change tupDesc_identifier if
809  * the tupdesc didn't really change; but for now it's not worth it.
810  */
812 
814 }
#define RelationGetDescr(relation)
Definition: rel.h:442
#define AccessShareLock
Definition: lockdefs.h:36
static uint64 tupledesc_id_counter
Definition: typcache.c:277
Form_pg_class rd_rel
Definition: rel.h:83
#define OidIsValid(objectId)
Definition: c.h:638
#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:732
uint64 tupDesc_identifier
Definition: typcache.h:87
#define elog(elevel,...)
Definition: elog.h:226
int tdrefcount
Definition: tupdesc.h:84
TupleDesc tupDesc
Definition: typcache.h:86

◆ lookup_rowtype_tupdesc()

◆ lookup_rowtype_tupdesc_copy()

TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

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

1687 {
1688  TupleDesc tmp;
1689 
1690  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1691  return CreateTupleDescCopyConstr(tmp);
1692 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:150
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1561

◆ lookup_rowtype_tupdesc_domain()

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

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

1709 {
1710  TupleDesc tupDesc;
1711 
1712  if (type_id != RECORDOID)
1713  {
1714  /*
1715  * Check for domain or named composite type. We might as well load
1716  * whichever data is needed.
1717  */
1718  TypeCacheEntry *typentry;
1719 
1720  typentry = lookup_type_cache(type_id,
1723  if (typentry->typtype == TYPTYPE_DOMAIN)
1725  typentry->domainBaseTypmod,
1726  noError);
1727  if (typentry->tupDesc == NULL && !noError)
1728  ereport(ERROR,
1729  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1730  errmsg("type %s is not composite",
1731  format_type_be(type_id))));
1732  tupDesc = typentry->tupDesc;
1733  }
1734  else
1735  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1736  if (tupDesc != NULL)
1737  PinTupleDesc(tupDesc);
1738  return tupDesc;
1739 }
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
Oid domainBaseType
Definition: typcache.h:105
#define ERROR
Definition: elog.h:43
int32 domainBaseTypmod
Definition: typcache.h:106
TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1669
#define ereport(elevel, rest)
Definition: elog.h:141
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
char typtype
Definition: typcache.h:41
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
int errmsg(const char *fmt,...)
Definition: elog.c:784
TupleDesc tupDesc
Definition: typcache.h:86
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1561
#define TYPECACHE_TUPDESC
Definition: typcache.h:136

◆ lookup_rowtype_tupdesc_internal()

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

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

1562 {
1563  if (type_id != RECORDOID)
1564  {
1565  /*
1566  * It's a named composite type, so use the regular typcache.
1567  */
1568  TypeCacheEntry *typentry;
1569 
1570  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1571  if (typentry->tupDesc == NULL && !noError)
1572  ereport(ERROR,
1573  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1574  errmsg("type %s is not composite",
1575  format_type_be(type_id))));
1576  return typentry->tupDesc;
1577  }
1578  else
1579  {
1580  /*
1581  * It's a transient record type, so look in our record-type table.
1582  */
1583  if (typmod >= 0)
1584  {
1585  /* It is already in our local cache? */
1586  if (typmod < RecordCacheArrayLen &&
1587  RecordCacheArray[typmod] != NULL)
1588  return RecordCacheArray[typmod];
1589 
1590  /* Are we attached to a shared record typmod registry? */
1592  {
1593  SharedTypmodTableEntry *entry;
1594 
1595  /* Try to find it in the shared typmod index. */
1597  &typmod, false);
1598  if (entry != NULL)
1599  {
1600  TupleDesc tupdesc;
1601 
1602  tupdesc = (TupleDesc)
1604  entry->shared_tupdesc);
1605  Assert(typmod == tupdesc->tdtypmod);
1606 
1607  /* We may need to extend the local RecordCacheArray. */
1609 
1610  /*
1611  * Our local array can now point directly to the TupleDesc
1612  * in shared memory, which is non-reference-counted.
1613  */
1614  RecordCacheArray[typmod] = tupdesc;
1615  Assert(tupdesc->tdrefcount == -1);
1616 
1617  /*
1618  * We don't share tupdesc identifiers across processes, so
1619  * assign one locally.
1620  */
1622 
1624  entry);
1625 
1626  return RecordCacheArray[typmod];
1627  }
1628  }
1629  }
1630 
1631  if (!noError)
1632  ereport(ERROR,
1633  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1634  errmsg("record type has not been registered")));
1635  return NULL;
1636  }
1637 }
Session * CurrentSession
Definition: session.c:48
int errcode(int sqlerrcode)
Definition: elog.c:570
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
static uint64 tupledesc_id_counter
Definition: typcache.c:277
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:561
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
dsa_pointer shared_tupdesc
Definition: typcache.c:198
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
dsa_area * area
Definition: session.h:28
#define ereport(elevel, rest)
Definition: elog.h:141
static int32 RecordCacheArrayLen
Definition: typcache.c:269
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
static void ensure_record_cache_typmod_slot_exists(int32 typmod)
Definition: typcache.c:1524
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:732
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:784
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:86
#define TYPECACHE_TUPDESC
Definition: typcache.h:136
static uint64 * RecordIdentifierArray
Definition: typcache.c:268

◆ lookup_rowtype_tupdesc_noerror()

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

Definition at line 1669 of file typcache.c.

References lookup_rowtype_tupdesc_internal(), and PinTupleDesc.

Referenced by lookup_rowtype_tupdesc_domain().

1670 {
1671  TupleDesc tupDesc;
1672 
1673  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1674  if (tupDesc != NULL)
1675  PinTupleDesc(tupDesc);
1676  return tupDesc;
1677 }
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1561

◆ lookup_type_cache()

TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 322 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, 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(), 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, TypeCacheEntry::tupDesc, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::typcollation, TypeCacheEntry::type_id, 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(), 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(), 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().

323 {
324  TypeCacheEntry *typentry;
325  bool found;
326 
327  if (TypeCacheHash == NULL)
328  {
329  /* First time through: initialize the hash table */
330  HASHCTL ctl;
331 
332  MemSet(&ctl, 0, sizeof(ctl));
333  ctl.keysize = sizeof(Oid);
334  ctl.entrysize = sizeof(TypeCacheEntry);
335  TypeCacheHash = hash_create("Type information cache", 64,
336  &ctl, HASH_ELEM | HASH_BLOBS);
337 
338  /* Also set up callbacks for SI invalidations */
343 
344  /* Also make sure CacheMemoryContext exists */
345  if (!CacheMemoryContext)
347  }
348 
349  /* Try to look up an existing entry */
351  (void *) &type_id,
352  HASH_FIND, NULL);
353  if (typentry == NULL)
354  {
355  /*
356  * If we didn't find one, we want to make one. But first look up the
357  * pg_type row, just to make sure we don't make a cache entry for an
358  * invalid type OID. If the type OID is not valid, present a
359  * user-facing error, since some code paths such as domain_in() allow
360  * this function to be reached with a user-supplied OID.
361  */
362  HeapTuple tp;
363  Form_pg_type typtup;
364 
365  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
366  if (!HeapTupleIsValid(tp))
367  ereport(ERROR,
368  (errcode(ERRCODE_UNDEFINED_OBJECT),
369  errmsg("type with OID %u does not exist", type_id)));
370  typtup = (Form_pg_type) GETSTRUCT(tp);
371  if (!typtup->typisdefined)
372  ereport(ERROR,
373  (errcode(ERRCODE_UNDEFINED_OBJECT),
374  errmsg("type \"%s\" is only a shell",
375  NameStr(typtup->typname))));
376 
377  /* Now make the typcache entry */
379  (void *) &type_id,
380  HASH_ENTER, &found);
381  Assert(!found); /* it wasn't there a moment ago */
382 
383  MemSet(typentry, 0, sizeof(TypeCacheEntry));
384  typentry->type_id = type_id;
385  typentry->typlen = typtup->typlen;
386  typentry->typbyval = typtup->typbyval;
387  typentry->typalign = typtup->typalign;
388  typentry->typstorage = typtup->typstorage;
389  typentry->typtype = typtup->typtype;
390  typentry->typrelid = typtup->typrelid;
391  typentry->typelem = typtup->typelem;
392  typentry->typcollation = typtup->typcollation;
393 
394  /* If it's a domain, immediately thread it into the domain cache list */
395  if (typentry->typtype == TYPTYPE_DOMAIN)
396  {
397  typentry->nextDomain = firstDomainTypeEntry;
398  firstDomainTypeEntry = typentry;
399  }
400 
401  ReleaseSysCache(tp);
402  }
403 
404  /*
405  * Look up opclasses if we haven't already and any dependent info is
406  * requested.
407  */
412  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
413  {
414  Oid opclass;
415 
416  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
417  if (OidIsValid(opclass))
418  {
419  typentry->btree_opf = get_opclass_family(opclass);
420  typentry->btree_opintype = get_opclass_input_type(opclass);
421  }
422  else
423  {
424  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
425  }
426 
427  /*
428  * Reset information derived from btree opclass. Note in particular
429  * that we'll redetermine the eq_opr even if we previously found one;
430  * this matters in case a btree opclass has been added to a type that
431  * previously had only a hash opclass.
432  */
433  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
438  }
439 
440  /*
441  * If we need to look up equality operator, and there's no btree opclass,
442  * force lookup of hash opclass.
443  */
444  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
445  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
446  typentry->btree_opf == InvalidOid)
447  flags |= TYPECACHE_HASH_OPFAMILY;
448 
453  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
454  {
455  Oid opclass;
456 
457  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
458  if (OidIsValid(opclass))
459  {
460  typentry->hash_opf = get_opclass_family(opclass);
461  typentry->hash_opintype = get_opclass_input_type(opclass);
462  }
463  else
464  {
465  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
466  }
467 
468  /*
469  * Reset information derived from hash opclass. We do *not* reset the
470  * eq_opr; if we already found one from the btree opclass, that
471  * decision is still good.
472  */
473  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
475  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
476  }
477 
478  /*
479  * Look for requested operators and functions, if we haven't already.
480  */
481  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
482  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
483  {
484  Oid eq_opr = InvalidOid;
485 
486  if (typentry->btree_opf != InvalidOid)
487  eq_opr = get_opfamily_member(typentry->btree_opf,
488  typentry->btree_opintype,
489  typentry->btree_opintype,
491  if (eq_opr == InvalidOid &&
492  typentry->hash_opf != InvalidOid)
493  eq_opr = get_opfamily_member(typentry->hash_opf,
494  typentry->hash_opintype,
495  typentry->hash_opintype,
497 
498  /*
499  * If the proposed equality operator is array_eq or record_eq, check
500  * to see if the element type or column types support equality. If
501  * not, array_eq or record_eq would fail at runtime, so we don't want
502  * to report that the type has equality. (We can omit similar
503  * checking for ranges because ranges can't be created in the first
504  * place unless their subtypes support equality.)
505  */
506  if (eq_opr == ARRAY_EQ_OP &&
507  !array_element_has_equality(typentry))
508  eq_opr = InvalidOid;
509  else if (eq_opr == RECORD_EQ_OP &&
510  !record_fields_have_equality(typentry))
511  eq_opr = InvalidOid;
512 
513  /* Force update of eq_opr_finfo only if we're changing state */
514  if (typentry->eq_opr != eq_opr)
515  typentry->eq_opr_finfo.fn_oid = InvalidOid;
516 
517  typentry->eq_opr = eq_opr;
518 
519  /*
520  * Reset info about hash functions whenever we pick up new info about
521  * equality operator. This is so we can ensure that the hash
522  * functions match the operator.
523  */
524  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC |
526  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
527  }
528  if ((flags & TYPECACHE_LT_OPR) &&
529  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
530  {
531  Oid lt_opr = InvalidOid;
532 
533  if (typentry->btree_opf != InvalidOid)
534  lt_opr = get_opfamily_member(typentry->btree_opf,
535  typentry->btree_opintype,
536  typentry->btree_opintype,
538 
539  /*
540  * As above, make sure array_cmp or record_cmp will succeed; but again
541  * we need no special check for ranges.
542  */
543  if (lt_opr == ARRAY_LT_OP &&
544  !array_element_has_compare(typentry))
545  lt_opr = InvalidOid;
546  else if (lt_opr == RECORD_LT_OP &&
547  !record_fields_have_compare(typentry))
548  lt_opr = InvalidOid;
549 
550  typentry->lt_opr = lt_opr;
551  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
552  }
553  if ((flags & TYPECACHE_GT_OPR) &&
554  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
555  {
556  Oid gt_opr = InvalidOid;
557 
558  if (typentry->btree_opf != InvalidOid)
559  gt_opr = get_opfamily_member(typentry->btree_opf,
560  typentry->btree_opintype,
561  typentry->btree_opintype,
563 
564  /*
565  * As above, make sure array_cmp or record_cmp will succeed; but again
566  * we need no special check for ranges.
567  */
568  if (gt_opr == ARRAY_GT_OP &&
569  !array_element_has_compare(typentry))
570  gt_opr = InvalidOid;
571  else if (gt_opr == RECORD_GT_OP &&
572  !record_fields_have_compare(typentry))
573  gt_opr = InvalidOid;
574 
575  typentry->gt_opr = gt_opr;
576  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
577  }
578  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
579  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
580  {
581  Oid cmp_proc = InvalidOid;
582 
583  if (typentry->btree_opf != InvalidOid)
584  cmp_proc = get_opfamily_proc(typentry->btree_opf,
585  typentry->btree_opintype,
586  typentry->btree_opintype,
587  BTORDER_PROC);
588 
589  /*
590  * As above, make sure array_cmp or record_cmp will succeed; but again
591  * we need no special check for ranges.
592  */
593  if (cmp_proc == F_BTARRAYCMP &&
594  !array_element_has_compare(typentry))
595  cmp_proc = InvalidOid;
596  else if (cmp_proc == F_BTRECORDCMP &&
597  !record_fields_have_compare(typentry))
598  cmp_proc = InvalidOid;
599 
600  /* Force update of cmp_proc_finfo only if we're changing state */
601  if (typentry->cmp_proc != cmp_proc)
602  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
603 
604  typentry->cmp_proc = cmp_proc;
605  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
606  }
608  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
609  {
610  Oid hash_proc = InvalidOid;
611 
612  /*
613  * We insist that the eq_opr, if one has been determined, match the
614  * hash opclass; else report there is no hash function.
615  */
616  if (typentry->hash_opf != InvalidOid &&
617  (!OidIsValid(typentry->eq_opr) ||
618  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
619  typentry->hash_opintype,
620  typentry->hash_opintype,
622  hash_proc = get_opfamily_proc(typentry->hash_opf,
623  typentry->hash_opintype,
624  typentry->hash_opintype,
626 
627  /*
628  * As above, make sure hash_array will succeed. We don't currently
629  * support hashing for composite types, but when we do, we'll need
630  * more logic here to check that case too.
631  */
632  if (hash_proc == F_HASH_ARRAY &&
633  !array_element_has_hashing(typentry))
634  hash_proc = InvalidOid;
635 
636  /*
637  * Likewise for hash_range.
638  */
639  if (hash_proc == F_HASH_RANGE &&
640  !range_element_has_hashing(typentry))
641  hash_proc = InvalidOid;
642 
643  /* Force update of hash_proc_finfo only if we're changing state */
644  if (typentry->hash_proc != hash_proc)
645  typentry->hash_proc_finfo.fn_oid = InvalidOid;
646 
647  typentry->hash_proc = hash_proc;
648  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
649  }
650  if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
653  {
654  Oid hash_extended_proc = InvalidOid;
655 
656  /*
657  * We insist that the eq_opr, if one has been determined, match the
658  * hash opclass; else report there is no hash function.
659  */
660  if (typentry->hash_opf != InvalidOid &&
661  (!OidIsValid(typentry->eq_opr) ||
662  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
663  typentry->hash_opintype,
664  typentry->hash_opintype,
666  hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
667  typentry->hash_opintype,
668  typentry->hash_opintype,
670 
671  /*
672  * As above, make sure hash_array_extended will succeed. We don't
673  * currently support hashing for composite types, but when we do,
674  * we'll need more logic here to check that case too.
675  */
676  if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
678  hash_extended_proc = InvalidOid;
679 
680  /*
681  * Likewise for hash_range_extended.
682  */
683  if (hash_extended_proc == F_HASH_RANGE_EXTENDED &&
685  hash_extended_proc = InvalidOid;
686 
687  /* Force update of proc finfo only if we're changing state */
688  if (typentry->hash_extended_proc != hash_extended_proc)
690 
691  typentry->hash_extended_proc = hash_extended_proc;
693  }
694 
695  /*
696  * Set up fmgr lookup info as requested
697  *
698  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
699  * which is not quite right (they're really in the hash table's private
700  * memory context) but this will do for our purposes.
701  *
702  * Note: the code above avoids invalidating the finfo structs unless the
703  * referenced operator/function OID actually changes. This is to prevent
704  * unnecessary leakage of any subsidiary data attached to an finfo, since
705  * that would cause session-lifespan memory leaks.
706  */
707  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
708  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
709  typentry->eq_opr != InvalidOid)
710  {
711  Oid eq_opr_func;
712 
713  eq_opr_func = get_opcode(typentry->eq_opr);
714  if (eq_opr_func != InvalidOid)
715  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
717  }
718  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
719  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
720  typentry->cmp_proc != InvalidOid)
721  {
722  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
724  }
725  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
726  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
727  typentry->hash_proc != InvalidOid)
728  {
729  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
731  }
732  if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
734  typentry->hash_extended_proc != InvalidOid)
735  {
737  &typentry->hash_extended_proc_finfo,
739  }
740 
741  /*
742  * If it's a composite type (row type), get tupdesc if requested
743  */
744  if ((flags & TYPECACHE_TUPDESC) &&
745  typentry->tupDesc == NULL &&
746  typentry->typtype == TYPTYPE_COMPOSITE)
747  {
748  load_typcache_tupdesc(typentry);
749  }
750 
751  /*
752  * If requested, get information about a range type
753  */
754  if ((flags & TYPECACHE_RANGE_INFO) &&
755  typentry->rngelemtype == NULL &&
756  typentry->typtype == TYPTYPE_RANGE)
757  {
758  load_rangetype_info(typentry);
759  }
760 
761  /*
762  * If requested, get information about a domain type
763  */
764  if ((flags & TYPECACHE_DOMAIN_BASE_INFO) &&
765  typentry->domainBaseType == InvalidOid &&
766  typentry->typtype == TYPTYPE_DOMAIN)
767  {
768  typentry->domainBaseTypmod = -1;
769  typentry->domainBaseType =
770  getBaseTypeAndTypmod(type_id, &typentry->domainBaseTypmod);
771  }
772  if ((flags & TYPECACHE_DOMAIN_CONSTR_INFO) &&
773  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
774  typentry->typtype == TYPTYPE_DOMAIN)
775  {
776  load_domaintype_info(typentry);
777  }
778 
779  return typentry;
780 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1332
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:786
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2316
#define BTORDER_PROC
Definition: nbtree.h:392
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:139
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1937
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid hash_opintype
Definition: typcache.h:57
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:85
#define HASH_ELEM
Definition: hsearch.h:87
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:80
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:143
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC
Definition: typcache.c:90
struct TypeCacheEntry TypeCacheEntry
Oid typcollation
Definition: typcache.h:44
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:133
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:135
Size entrysize
Definition: hsearch.h:73
#define TYPECACHE_EQ_OPR
Definition: typcache.h:128
int errcode(int sqlerrcode)
Definition: elog.c:570
#define HASHEXTENDED_PROC
Definition: hash.h:338
#define MemSet(start, val, len)
Definition: c.h:955
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:638
bool typbyval
Definition: typcache.h:38
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1468
Oid domainBaseType
Definition: typcache.h:105
FmgrInfo cmp_proc_finfo
Definition: typcache.h:73
struct TypeCacheEntry * nextDomain
Definition: typcache.h:124
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:87
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define HTEqualStrategyNumber
Definition: stratnum.h:41
char typstorage
Definition: typcache.h:40
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:2092
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1324
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
int32 domainBaseTypmod
Definition: typcache.h:106
Oid hash_extended_proc
Definition: typcache.h:63
FmgrInfo hash_proc_finfo
Definition: typcache.h:74
#define TYPECACHE_GT_OPR
Definition: typcache.h:130
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define HASHSTANDARD_PROC
Definition: hash.h:337
#define ereport(elevel, rest)
Definition: elog.h:141
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:137
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:95
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
static bool range_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1480
#define HASH_BLOBS
Definition: hsearch.h:88
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:75
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1426
#define TYPECACHE_HASH_EXTENDED_PROC
Definition: typcache.h:142
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Oid btree_opintype
Definition: typcache.h:55
Size keysize
Definition: hsearch.h:72
FmgrInfo eq_opr_finfo
Definition: typcache.h:72
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:820
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
Oid fn_oid
Definition: fmgr.h:59
#define TYPECACHE_CMP_PROC
Definition: typcache.h:131
char typtype
Definition: typcache.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
#define TYPECACHE_DOMAIN_CONSTR_INFO
Definition: typcache.h:141
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
FormData_pg_type * Form_pg_type
Definition: pg_type.h:251
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:83
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:99
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1386
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1019
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1316
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:883
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:89
char typalign
Definition: typcache.h:39
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define TYPECACHE_LT_OPR
Definition: typcache.h:129
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:86
#define NameStr(name)
Definition: c.h:609
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:134
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:84
static bool range_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1488
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:138
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1378
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:88
#define BTLessStrategyNumber
Definition: stratnum.h:29
static bool array_element_has_extended_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1340
TupleDesc tupDesc
Definition: typcache.h:86
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2194
static HTAB * TypeCacheHash
Definition: typcache.c:77
#define TYPECACHE_HASH_PROC
Definition: typcache.h:132
#define TYPECACHE_TUPDESC
Definition: typcache.h:136
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:2165
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1041

◆ prep_domain_constraints()

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

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

1165 {
1166  List *result = NIL;
1167  MemoryContext oldcxt;
1168  ListCell *lc;
1169 
1170  oldcxt = MemoryContextSwitchTo(execctx);
1171 
1172  foreach(lc, constraints)
1173  {
1175  DomainConstraintState *newr;
1176 
1178  newr->constrainttype = r->constrainttype;
1179  newr->name = r->name;
1180  newr->check_expr = r->check_expr;
1181  newr->check_exprstate = ExecInitExpr(r->check_expr, NULL);
1182 
1183  result = lappend(result, newr);
1184  }
1185 
1186  MemoryContextSwitchTo(oldcxt);
1187 
1188  return result;
1189 }
#define NIL
Definition: pg_list.h:65
DomainConstraintType constrainttype
Definition: execnodes.h:904
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * check_exprstate
Definition: execnodes.h:907
List * lappend(List *list, void *datum)
Definition: list.c:321
#define makeNode(_type_)
Definition: nodes.h:573
#define lfirst(lc)
Definition: pg_list.h:190
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:121
Definition: pg_list.h:50

◆ range_element_has_extended_hashing()

static bool range_element_has_extended_hashing ( TypeCacheEntry typentry)
static

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

1489 {
1490  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1492  return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0;
1493 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1496
#define TCFLAGS_HAVE_ELEM_EXTENDED_HASHING
Definition: typcache.c:95
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91

◆ range_element_has_hashing()

static bool range_element_has_hashing ( TypeCacheEntry typentry)
static

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

1481 {
1482  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1484  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1485 }
static void cache_range_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1496
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:91
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:94

◆ record_fields_have_compare()

static bool record_fields_have_compare ( TypeCacheEntry typentry)
static

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

1387 {
1388  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1390  return (typentry->flags & TCFLAGS_HAVE_FIELD_COMPARE) != 0;
1391 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:96
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1394
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:98

◆ record_fields_have_equality()

static bool record_fields_have_equality ( TypeCacheEntry typentry)
static

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

1379 {
1380  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1382  return (typentry->flags & TCFLAGS_HAVE_FIELD_EQUALITY) != 0;
1383 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:96
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1394
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:97

◆ record_type_typmod_compare()

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

Definition at line 1756 of file typcache.c.

References equalTupleDescs(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

1757 {
1758  RecordCacheEntry *left = (RecordCacheEntry *) a;
1759  RecordCacheEntry *right = (RecordCacheEntry *) b;
1760 
1761  return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
1762 }
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:411
TupleDesc tupdesc
Definition: typcache.c:149

◆ record_type_typmod_hash()

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

Definition at line 1745 of file typcache.c.

References hashTupleDesc(), and RecordCacheEntry::tupdesc.

Referenced by assign_record_type_typmod().

1746 {
1747  RecordCacheEntry *entry = (RecordCacheEntry *) data;
1748 
1749  return hashTupleDesc(entry->tupdesc);
1750 }
uint32 hashTupleDesc(TupleDesc desc)
Definition: tupdesc.c:574
TupleDesc tupdesc
Definition: typcache.c:149

◆ share_tupledesc()

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

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

2511 {
2512  dsa_pointer shared_dp;
2513  TupleDesc shared;
2514 
2515  shared_dp = dsa_allocate(area, TupleDescSize(tupdesc));
2516  shared = (TupleDesc) dsa_get_address(area, shared_dp);
2517  TupleDescCopy(shared, tupdesc);
2518  shared->tdtypmod = typmod;
2519 
2520  return shared_dp;
2521 }
#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 205 of file typcache.c.

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

207 {
208  dsa_area *area = (dsa_area *) arg;
211  TupleDesc t1;
212  TupleDesc t2;
213 
214  if (k1->shared)
215  t1 = (TupleDesc) dsa_get_address(area, k1->u.shared_tupdesc);
216  else
217  t1 = k1->u.local_tupdesc;
218 
219  if (k2->shared)
220  t2 = (TupleDesc) dsa_get_address(area, k2->u.shared_tupdesc);
221  else
222  t2 = k2->u.local_tupdesc;
223 
224  return equalTupleDescs(t1, t2) ? 0 : 1;
225 }
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:932
dsa_pointer shared_tupdesc
Definition: typcache.c:177
union SharedRecordTableKey::@36 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:176
void * arg

◆ shared_record_table_hash()

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

Definition at line 231 of file typcache.c.

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

232 {
233  dsa_area *area = (dsa_area *) arg;
235  TupleDesc t;
236 
237  if (k->shared)
238  t = (TupleDesc) dsa_get_address(area, k->u.shared_tupdesc);
239  else
240  t = k->u.local_tupdesc;
241 
242  return hashTupleDesc(t);
243 }
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:177
union SharedRecordTableKey::@36 u
Definition: dsa.c:354
struct TupleDescData * TupleDesc
Definition: tupdesc.h:89
TupleDesc local_tupdesc
Definition: typcache.c:176
void * arg

◆ shared_record_typmod_registry_detach()

static void shared_record_typmod_registry_detach ( dsm_segment segment,
Datum  datum 
)
static

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

2644 {
2645  /* Be cautious here: maybe we didn't finish initializing. */
2646  if (CurrentSession->shared_record_table != NULL)
2647  {
2650  }
2651  if (CurrentSession->shared_typmod_table != NULL)
2652  {
2655  }
2657 }
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 2009 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().

2010 {
2011  MemoryContext old_context;
2012  dshash_table *record_table;
2013  dshash_table *typmod_table;
2014 
2016 
2017  /* We can't already be attached to a shared registry. */
2018  Assert(CurrentSession != NULL);
2019  Assert(CurrentSession->segment != NULL);
2020  Assert(CurrentSession->area != NULL);
2024 
2025  /*
2026  * We can't already have typmods in our local cache, because they'd clash
2027  * with those imported by SharedRecordTypmodRegistryInit. This should be
2028  * a freshly started parallel worker. If we ever support worker
2029  * recycling, a worker would need to zap its local cache in between
2030  * servicing different queries, in order to be able to call this and
2031  * synchronize typmods with a new leader; but that's problematic because
2032  * we can't be very sure that record-typmod-related state hasn't escaped
2033  * to anywhere else in the process.
2034  */
2035  Assert(NextRecordTypmod == 0);
2036 
2037  old_context = MemoryContextSwitchTo(TopMemoryContext);
2038 
2039  /* Attach to the two hash tables. */
2040  record_table = dshash_attach(CurrentSession->area,
2042  registry->record_table_handle,
2043  CurrentSession->area);
2044  typmod_table = dshash_attach(CurrentSession->area,
2046  registry->typmod_table_handle,
2047  NULL);
2048 
2049  MemoryContextSwitchTo(old_context);
2050 
2051  /*
2052  * Set up detach hook to run at worker exit. Currently this is the same
2053  * as the leader's detach hook, but in future they might need to be
2054  * different.
2055  */
2058  PointerGetDatum(registry));
2059 
2060  /*
2061  * Set up the session state that will tell assign_record_type_typmod and
2062  * lookup_rowtype_tupdesc_internal about the shared registry.
2063  */
2065  CurrentSession->shared_record_table = record_table;
2066  CurrentSession->shared_typmod_table = typmod_table;
2067 }
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:246
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:975
dsa_area * area
Definition: session.h:28
#define IsParallelWorker()
Definition: parallel.h:60
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:255
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2643
static int32 NextRecordTypmod
Definition: typcache.c:270
struct SharedRecordTypmodRegistry * shared_typmod_registry
Definition: session.h:31
dshash_table * shared_typmod_table
Definition: session.h:33
#define Assert(condition)
Definition: c.h:732
dshash_table_handle record_table_handle
Definition: typcache.c:159
dshash_table_handle typmod_table_handle
Definition: typcache.c:161
dsm_segment * segment
Definition: session.h:27

◆ SharedRecordTypmodRegistryEstimate()

size_t SharedRecordTypmodRegistryEstimate ( void  )

Definition at line 1888 of file typcache.c.

Referenced by GetSessionDsmHandle().

1889 {
1890  return sizeof(SharedRecordTypmodRegistry);
1891 }
struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry
Definition: typcache.h:166

◆ SharedRecordTypmodRegistryInit()

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

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

1913 {
1914  MemoryContext old_context;
1915  dshash_table *record_table;
1916  dshash_table *typmod_table;
1917  int32 typmod;
1918 
1920 
1921  /* We can't already be attached to a shared registry. */
1925 
1926  old_context = MemoryContextSwitchTo(TopMemoryContext);
1927 
1928  /* Create the hash table of tuple descriptors indexed by themselves. */
1929  record_table = dshash_create(area, &srtr_record_table_params, area);
1930 
1931  /* Create the hash table of tuple descriptors indexed by typmod. */
1932  typmod_table = dshash_create(area, &srtr_typmod_table_params, NULL);
1933 
1934  MemoryContextSwitchTo(old_context);
1935 
1936  /* Initialize the SharedRecordTypmodRegistry. */
1937  registry->record_table_handle = dshash_get_hash_table_handle(record_table);
1938  registry->typmod_table_handle = dshash_get_hash_table_handle(typmod_table);
1940 
1941  /*
1942  * Copy all entries from this backend's private registry into the shared
1943  * registry.
1944  */
1945  for (typmod = 0; typmod < NextRecordTypmod; ++typmod)
1946  {
1947  SharedTypmodTableEntry *typmod_table_entry;
1948  SharedRecordTableEntry *record_table_entry;
1949  SharedRecordTableKey record_table_key;
1950  dsa_pointer shared_dp;
1951  TupleDesc tupdesc;
1952  bool found;
1953 
1954  tupdesc = RecordCacheArray[typmod];
1955  if (tupdesc == NULL)
1956  continue;
1957 
1958  /* Copy the TupleDesc into shared memory. */
1959  shared_dp = share_tupledesc(area, tupdesc, typmod);
1960 
1961  /* Insert into the typmod table. */
1962  typmod_table_entry = dshash_find_or_insert(typmod_table,
1963  &tupdesc->tdtypmod,
1964  &found);
1965  if (found)
1966  elog(ERROR, "cannot create duplicate shared record typmod");
1967  typmod_table_entry->typmod = tupdesc->tdtypmod;
1968  typmod_table_entry->shared_tupdesc = shared_dp;
1969  dshash_release_lock(typmod_table, typmod_table_entry);
1970 
1971  /* Insert into the record table. */
1972  record_table_key.shared = false;
1973  record_table_key.u.local_tupdesc = tupdesc;
1974  record_table_entry = dshash_find_or_insert(record_table,
1975  &record_table_key,
1976  &found);
1977  if (!found)
1978  {
1979  record_table_entry->key.shared = true;
1980  record_table_entry->key.u.shared_tupdesc = shared_dp;
1981  }
1982  dshash_release_lock(record_table, record_table_entry);
1983  }
1984 
1985  /*
1986  * Set up the global state that will tell assign_record_type_typmod and
1987  * lookup_rowtype_tupdesc_internal about the shared registry.
1988  */
1989  CurrentSession->shared_record_table = record_table;
1990  CurrentSession->shared_typmod_table = typmod_table;
1992 
1993  /*
1994  * We install a detach hook in the leader, but only to handle cleanup on
1995  * failure during GetSessionDsmHandle(). Once GetSessionDsmHandle() pins
1996  * the memory, the leader process will use a shared registry until it
1997  * exits.
1998  */
2000 }
Session * CurrentSession
Definition: session.c:48
static const dshash_parameters srtr_record_table_params
Definition: typcache.c:246
dshash_table * shared_record_table
Definition: session.h:32
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SharedRecordTableKey key
Definition: typcache.c:188
void on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
Definition: dsm.c:975
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:346
static TupleDesc * RecordCacheArray
Definition: typcache.c:267
dsa_pointer shared_tupdesc
Definition: typcache.c:198
pg_atomic_uint32 next_typmod
Definition: typcache.c:163
#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:177
#define IsParallelWorker()
Definition: parallel.h:60
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static const dshash_parameters srtr_typmod_table_params
Definition: typcache.c:255
static void shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
Definition: typcache.c:2643
static int32 NextRecordTypmod
Definition: typcache.c:270
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
union SharedRecordTableKey::@36 u
#define Assert(condition)
Definition: c.h:732
static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod)
Definition: typcache.c:2510
dshash_table_handle record_table_handle
Definition: typcache.c:159
#define elog(elevel,...)
Definition: elog.h:226
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:430
TupleDesc local_tupdesc
Definition: typcache.c:176
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:226
dshash_table_handle typmod_table_handle
Definition: typcache.c:161

◆ TypeCacheConstrCallback()

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

Definition at line 2194 of file typcache.c.

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

Referenced by lookup_type_cache().

2195 {
2196  TypeCacheEntry *typentry;
2197 
2198  /*
2199  * Because this is called very frequently, and typically very few of the
2200  * typcache entries are for domains, we don't use hash_seq_search here.
2201  * Instead we thread all the domain-type entries together so that we can
2202  * visit them cheaply.
2203  */
2204  for (typentry = firstDomainTypeEntry;
2205  typentry != NULL;
2206  typentry = typentry->nextDomain)
2207  {
2208  /* Reset domain constraint validity information */
2210  }
2211 }
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:80
struct TypeCacheEntry * nextDomain
Definition: typcache.h:124
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:99

◆ TypeCacheOpcCallback()

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

Definition at line 2165 of file typcache.c.

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

Referenced by lookup_type_cache().

2166 {
2168  TypeCacheEntry *typentry;
2169 
2170  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2171  hash_seq_init(&status, TypeCacheHash);
2172  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2173  {
2174  /* Reset equality/comparison/hashing validity information */
2175  typentry->flags = 0;
2176  }
2177 }
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static HTAB * TypeCacheHash
Definition: typcache.c:77

◆ TypeCacheRelCallback()

static void TypeCacheRelCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 2092 of file typcache.c.

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

Referenced by lookup_type_cache().

2093 {
2095  TypeCacheEntry *typentry;
2096 
2097  /* TypeCacheHash must exist, else this callback wouldn't be registered */
2098  hash_seq_init(&status, TypeCacheHash);
2099  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
2100  {
2101  if (typentry->typtype == TYPTYPE_COMPOSITE)
2102  {
2103  /* Skip if no match, unless we're zapping all composite types */
2104  if (relid != typentry->typrelid && relid != InvalidOid)
2105  continue;
2106 
2107  /* Delete tupdesc if we have it */
2108  if (typentry->tupDesc != NULL)
2109  {
2110  /*
2111  * Release our refcount, and free the tupdesc if none remain.
2112  * (Can't use DecrTupleDescRefCount because this reference is
2113  * not logged in current resource owner.)
2114  */
2115  Assert(typentry->tupDesc->tdrefcount > 0);
2116  if (--typentry->tupDesc->tdrefcount == 0)
2117  FreeTupleDesc(typentry->tupDesc);
2118  typentry->tupDesc = NULL;
2119 
2120  /*
2121  * Also clear tupDesc_identifier, so that anything watching
2122  * that will realize that the tupdesc has possibly changed.
2123  * (Alternatively, we could specify that to detect possible
2124  * tupdesc change, one must check for tupDesc != NULL as well
2125  * as tupDesc_identifier being the same as what was previously
2126  * seen. That seems error-prone.)
2127  */
2128  typentry->tupDesc_identifier = 0;
2129  }
2130 
2131  /* Reset equality/comparison/hashing validity information */
2132  typentry->flags = 0;
2133  }
2134  else if (typentry->typtype == TYPTYPE_DOMAIN)
2135  {
2136  /*
2137  * If it's domain over composite, reset flags. (We don't bother
2138  * trying to determine whether the specific base type needs a
2139  * reset.) Note that if we haven't determined whether the base
2140  * type is composite, we don't need to reset anything.
2141  */
2142  if (typentry->flags & TCFLAGS_DOMAIN_BASE_IS_COMPOSITE)
2143  typentry->flags = 0;
2144  }
2145  }
2146 }
#define TCFLAGS_DOMAIN_BASE_IS_COMPOSITE
Definition: typcache.c:100
#define InvalidOid
Definition: postgres_ext.h:36
char typtype
Definition: typcache.h:41
#define Assert(condition)
Definition: c.h:732
uint64 tupDesc_identifier
Definition: typcache.h:87
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
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:86
static HTAB * TypeCacheHash
Definition: typcache.c:77

◆ UpdateDomainConstraintRef()

void UpdateDomainConstraintRef ( DomainConstraintRef ref)

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

1241 {
1242  TypeCacheEntry *typentry = ref->tcache;
1243 
1244  /* Make sure typcache entry's data is up to date */
1245  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1246  typentry->typtype == TYPTYPE_DOMAIN)
1247  load_domaintype_info(typentry);
1248 
1249  /* Transfer to ref object if there's new info, adjusting refcounts */
1250  if (ref->dcc != typentry->domainData)
1251  {
1252  /* Paranoia --- be sure link is nulled before trying to release */
1253  DomainConstraintCache *dcc = ref->dcc;
1254 
1255  if (dcc)
1256  {
1257  /*
1258  * Note: we just leak the previous list of executable domain
1259  * constraints. Alternatively, we could keep those in a child
1260  * context of ref->refctx and free that context at this point.
1261  * However, in practice this code path will be taken so seldom
1262  * that the extra bookkeeping for a child context doesn't seem
1263  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1264  */
1265  ref->constraints = NIL;
1266  ref->dcc = NULL;
1267  decr_dcc_refcount(dcc);
1268  }
1269  dcc = typentry->domainData;
1270  if (dcc)
1271  {
1272  ref->dcc = dcc;
1273  dcc->dccRefCount++;
1274  if (ref->need_exprstate)
1276  ref->refctx);
1277  else
1278  ref->constraints = dcc->constraints;
1279  }
1280  }
1281 }
#define NIL
Definition: pg_list.h:65
DomainConstraintCache * dcc
Definition: typcache.h:162
DomainConstraintCache * domainData
Definition: typcache.h:112
MemoryContext refctx
Definition: typcache.h:157
char typtype
Definition: typcache.h:41
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:1164
TypeCacheEntry * tcache
Definition: typcache.h:158
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:99
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:883
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:1132

Variable Documentation

◆ firstDomainTypeEntry

TypeCacheEntry* firstDomainTypeEntry = NULL
static

Definition at line 80 of file typcache.c.

Referenced by lookup_type_cache().

◆ NextRecordTypmod

int32 NextRecordTypmod = 0
static

◆ RecordCacheArray

TupleDesc* RecordCacheArray = NULL
static

Definition at line 267 of file typcache.c.

◆ RecordCacheArrayLen

int32 RecordCacheArrayLen = 0
static

◆ RecordCacheHash

HTAB* RecordCacheHash = NULL
static

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

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

Definition at line 255 of file typcache.c.

◆ tupledesc_id_counter

◆ TypeCacheHash

HTAB* TypeCacheHash = NULL
static

Definition at line 77 of file typcache.c.