PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
typcache.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/hash.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/nbtree.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 "optimizer/planner.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
 

Macros

#define TCFLAGS_CHECKED_BTREE_OPCLASS   0x0001
 
#define TCFLAGS_CHECKED_HASH_OPCLASS   0x0002
 
#define TCFLAGS_CHECKED_EQ_OPR   0x0004
 
#define TCFLAGS_CHECKED_LT_OPR   0x0008
 
#define TCFLAGS_CHECKED_GT_OPR   0x0010
 
#define TCFLAGS_CHECKED_CMP_PROC   0x0020
 
#define TCFLAGS_CHECKED_HASH_PROC   0x0040
 
#define TCFLAGS_CHECKED_ELEM_PROPERTIES   0x0080
 
#define TCFLAGS_HAVE_ELEM_EQUALITY   0x0100
 
#define TCFLAGS_HAVE_ELEM_COMPARE   0x0200
 
#define TCFLAGS_HAVE_ELEM_HASHING   0x0400
 
#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x0800
 
#define TCFLAGS_HAVE_FIELD_EQUALITY   0x1000
 
#define TCFLAGS_HAVE_FIELD_COMPARE   0x2000
 
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x4000
 
#define REC_HASH_KEYS   16 /* use this many columns in hash key */
 

Typedefs

typedef struct TypeCacheEnumData TypeCacheEnumData
 
typedef struct RecordCacheEntry RecordCacheEntry
 

Functions

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 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 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)
 
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 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)
 
void assign_record_type_typmod (TupleDesc tupDesc)
 
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 HTABRecordCacheHash = NULL
 
static TupleDescRecordCacheArray = NULL
 
static int32 RecordCacheArrayLen = 0
 
static int32 NextRecordTypmod = 0
 

Macro Definition Documentation

#define REC_HASH_KEYS   16 /* use this many columns in hash key */

Definition at line 140 of file typcache.c.

Referenced by assign_record_type_typmod().

#define TCFLAGS_CHECKED_BTREE_OPCLASS   0x0001

Definition at line 78 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_CHECKED_CMP_PROC   0x0020

Definition at line 83 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS   0x4000
#define TCFLAGS_CHECKED_ELEM_PROPERTIES   0x0080
#define TCFLAGS_CHECKED_EQ_OPR   0x0004

Definition at line 80 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_CHECKED_FIELD_PROPERTIES   0x0800
#define TCFLAGS_CHECKED_GT_OPR   0x0010

Definition at line 82 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_CHECKED_HASH_OPCLASS   0x0002

Definition at line 79 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_CHECKED_HASH_PROC   0x0040

Definition at line 84 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_CHECKED_LT_OPR   0x0008

Definition at line 81 of file typcache.c.

Referenced by lookup_type_cache().

#define TCFLAGS_HAVE_ELEM_COMPARE   0x0200

Definition at line 87 of file typcache.c.

Referenced by array_element_has_compare(), and cache_array_element_properties().

#define TCFLAGS_HAVE_ELEM_EQUALITY   0x0100

Definition at line 86 of file typcache.c.

Referenced by array_element_has_equality(), and cache_array_element_properties().

#define TCFLAGS_HAVE_ELEM_HASHING   0x0400

Definition at line 88 of file typcache.c.

Referenced by array_element_has_hashing(), and cache_array_element_properties().

#define TCFLAGS_HAVE_FIELD_COMPARE   0x2000

Definition at line 91 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_compare().

#define TCFLAGS_HAVE_FIELD_EQUALITY   0x1000

Definition at line 90 of file typcache.c.

Referenced by cache_record_field_properties(), and record_fields_have_equality().

Typedef Documentation

Function Documentation

static bool array_element_has_compare ( TypeCacheEntry typentry)
static

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

1095 {
1096  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1098  return (typentry->flags & TCFLAGS_HAVE_ELEM_COMPARE) != 0;
1099 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:87
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:85
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1110
static bool array_element_has_equality ( TypeCacheEntry typentry)
static

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

1087 {
1088  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1090  return (typentry->flags & TCFLAGS_HAVE_ELEM_EQUALITY) != 0;
1091 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:85
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1110
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:86
static bool array_element_has_hashing ( TypeCacheEntry typentry)
static

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

1103 {
1104  if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES))
1106  return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0;
1107 }
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:85
static void cache_array_element_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1110
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:88
void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1309 of file typcache.c.

References Assert, CacheMemoryContext, CreateCacheMemoryContext(), CreateTupleDescCopy(), HASHCTL::entrysize, equalTupleDescs(), HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), i, HASHCTL::keysize, lcons(), lfirst, MemoryContextSwitchTo(), MemSet, tupleDesc::natts, NextRecordTypmod, NIL, NULL, palloc(), REC_HASH_KEYS, RecordCacheArrayLen, RECORDOID, repalloc(), tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, RecordCacheEntry::tupdescs, and TupleDescAttr.

Referenced by BlessTupleDesc(), internal_get_result_type(), and SPI_returntuple().

1310 {
1311  RecordCacheEntry *recentry;
1312  TupleDesc entDesc;
1313  Oid hashkey[REC_HASH_KEYS];
1314  bool found;
1315  int i;
1316  ListCell *l;
1317  int32 newtypmod;
1318  MemoryContext oldcxt;
1319 
1320  Assert(tupDesc->tdtypeid == RECORDOID);
1321 
1322  if (RecordCacheHash == NULL)
1323  {
1324  /* First time through: initialize the hash table */
1325  HASHCTL ctl;
1326 
1327  MemSet(&ctl, 0, sizeof(ctl));
1328  ctl.keysize = REC_HASH_KEYS * sizeof(Oid);
1329  ctl.entrysize = sizeof(RecordCacheEntry);
1330  RecordCacheHash = hash_create("Record information cache", 64,
1331  &ctl, HASH_ELEM | HASH_BLOBS);
1332 
1333  /* Also make sure CacheMemoryContext exists */
1334  if (!CacheMemoryContext)
1336  }
1337 
1338  /* Find or create a hashtable entry for this hash class */
1339  MemSet(hashkey, 0, sizeof(hashkey));
1340  for (i = 0; i < tupDesc->natts; i++)
1341  {
1342  if (i >= REC_HASH_KEYS)
1343  break;
1344  hashkey[i] = TupleDescAttr(tupDesc, i)->atttypid;
1345  }
1347  (void *) hashkey,
1348  HASH_ENTER, &found);
1349  if (!found)
1350  {
1351  /* New entry ... hash_search initialized only the hash key */
1352  recentry->tupdescs = NIL;
1353  }
1354 
1355  /* Look for existing record cache entry */
1356  foreach(l, recentry->tupdescs)
1357  {
1358  entDesc = (TupleDesc) lfirst(l);
1359  if (equalTupleDescs(tupDesc, entDesc))
1360  {
1361  tupDesc->tdtypmod = entDesc->tdtypmod;
1362  return;
1363  }
1364  }
1365 
1366  /* Not present, so need to manufacture an entry */
1368 
1369  if (RecordCacheArray == NULL)
1370  {
1371  RecordCacheArray = (TupleDesc *) palloc(64 * sizeof(TupleDesc));
1372  RecordCacheArrayLen = 64;
1373  }
1375  {
1376  int32 newlen = RecordCacheArrayLen * 2;
1377 
1379  newlen * sizeof(TupleDesc));
1380  RecordCacheArrayLen = newlen;
1381  }
1382 
1383  /* if fail in subrs, no damage except possibly some wasted memory... */
1384  entDesc = CreateTupleDescCopy(tupDesc);
1385  recentry->tupdescs = lcons(entDesc, recentry->tupdescs);
1386  /* mark it as a reference-counted tupdesc */
1387  entDesc->tdrefcount = 1;
1388  /* now it's safe to advance NextRecordTypmod */
1389  newtypmod = NextRecordTypmod++;
1390  entDesc->tdtypmod = newtypmod;
1391  RecordCacheArray[newtypmod] = entDesc;
1392 
1393  /* report to caller as well */
1394  tupDesc->tdtypmod = newtypmod;
1395 
1396  MemoryContextSwitchTo(oldcxt);
1397 }
#define NIL
Definition: pg_list.h:69
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:100
Oid tdtypeid
Definition: tupdesc.h:74
#define HASH_ELEM
Definition: hsearch.h:87
List * tupdescs
Definition: typcache.c:148
struct RecordCacheEntry RecordCacheEntry
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:858
static HTAB * RecordCacheHash
Definition: typcache.c:151
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
int32 tdtypmod
Definition: tupdesc.h:75
signed int int32
Definition: c.h:256
static TupleDesc * RecordCacheArray
Definition: typcache.c:153
#define REC_HASH_KEYS
Definition: typcache.c:140
#define RECORDOID
Definition: pg_type.h:680
#define HASH_BLOBS
Definition: hsearch.h:88
static int32 RecordCacheArrayLen
Definition: typcache.c:154
static int32 NextRecordTypmod
Definition: typcache.c:155
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
struct tupleDesc * TupleDesc
List * lcons(void *datum, List *list)
Definition: list.c:259
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define lfirst(lc)
Definition: pg_list.h:106
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
void * palloc(Size size)
Definition: mcxt.c:849
int tdrefcount
Definition: tupdesc.h:77
int i
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:319
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void cache_array_element_properties ( TypeCacheEntry typentry)
static

Definition at line 1110 of file typcache.c.

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

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

1111 {
1112  Oid elem_type = get_base_element_type(typentry->type_id);
1113 
1114  if (OidIsValid(elem_type))
1115  {
1116  TypeCacheEntry *elementry;
1117 
1118  elementry = lookup_type_cache(elem_type,
1122  if (OidIsValid(elementry->eq_opr))
1123  typentry->flags |= TCFLAGS_HAVE_ELEM_EQUALITY;
1124  if (OidIsValid(elementry->cmp_proc))
1125  typentry->flags |= TCFLAGS_HAVE_ELEM_COMPARE;
1126  if (OidIsValid(elementry->hash_proc))
1127  typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING;
1128  }
1130 }
#define TCFLAGS_HAVE_ELEM_COMPARE
Definition: typcache.c:87
#define TYPECACHE_EQ_OPR
Definition: typcache.h:110
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define TCFLAGS_CHECKED_ELEM_PROPERTIES
Definition: typcache.c:85
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define TYPECACHE_CMP_PROC
Definition: typcache.h:113
#define TCFLAGS_HAVE_ELEM_EQUALITY
Definition: typcache.c:86
#define TCFLAGS_HAVE_ELEM_HASHING
Definition: typcache.c:88
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
#define TYPECACHE_HASH_PROC
Definition: typcache.h:114
static void cache_record_field_properties ( TypeCacheEntry typentry)
static

Definition at line 1149 of file typcache.c.

References TypeCacheEntry::cmp_proc, DecrTupleDescRefCount(), TypeCacheEntry::eq_opr, TypeCacheEntry::flags, i, IncrTupleDescRefCount(), load_typcache_tupdesc(), lookup_type_cache(), tupleDesc::natts, NULL, OidIsValid, RECORDOID, TCFLAGS_CHECKED_FIELD_PROPERTIES, TCFLAGS_HAVE_FIELD_COMPARE, TCFLAGS_HAVE_FIELD_EQUALITY, TypeCacheEntry::tupDesc, TupleDescAttr, TypeCacheEntry::type_id, TYPECACHE_CMP_PROC, TYPECACHE_EQ_OPR, TypeCacheEntry::typtype, and TYPTYPE_COMPOSITE.

Referenced by record_fields_have_compare(), and record_fields_have_equality().

1150 {
1151  /*
1152  * For type RECORD, we can't really tell what will work, since we don't
1153  * have access here to the specific anonymous type. Just assume that
1154  * everything will (we may get a failure at runtime ...)
1155  */
1156  if (typentry->type_id == RECORDOID)
1157  typentry->flags |= (TCFLAGS_HAVE_FIELD_EQUALITY |
1159  else if (typentry->typtype == TYPTYPE_COMPOSITE)
1160  {
1161  TupleDesc tupdesc;
1162  int newflags;
1163  int i;
1164 
1165  /* Fetch composite type's tupdesc if we don't have it already */
1166  if (typentry->tupDesc == NULL)
1167  load_typcache_tupdesc(typentry);
1168  tupdesc = typentry->tupDesc;
1169 
1170  /* Must bump the refcount while we do additional catalog lookups */
1171  IncrTupleDescRefCount(tupdesc);
1172 
1173  /* Have each property if all non-dropped fields have the property */
1174  newflags = (TCFLAGS_HAVE_FIELD_EQUALITY |
1176  for (i = 0; i < tupdesc->natts; i++)
1177  {
1178  TypeCacheEntry *fieldentry;
1179  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1180 
1181  if (attr->attisdropped)
1182  continue;
1183 
1184  fieldentry = lookup_type_cache(attr->atttypid,
1187  if (!OidIsValid(fieldentry->eq_opr))
1188  newflags &= ~TCFLAGS_HAVE_FIELD_EQUALITY;
1189  if (!OidIsValid(fieldentry->cmp_proc))
1190  newflags &= ~TCFLAGS_HAVE_FIELD_COMPARE;
1191 
1192  /* We can drop out of the loop once we disprove all bits */
1193  if (newflags == 0)
1194  break;
1195  }
1196  typentry->flags |= newflags;
1197 
1198  DecrTupleDescRefCount(tupdesc);
1199  }
1201 }
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:571
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:283
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:89
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define TYPECACHE_EQ_OPR
Definition: typcache.h:110
#define OidIsValid(objectId)
Definition: c.h:538
int natts
Definition: tupdesc.h:73
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:91
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RECORDOID
Definition: pg_type.h:680
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:90
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define TYPECACHE_CMP_PROC
Definition: typcache.h:113
char typtype
Definition: typcache.h:39
#define NULL
Definition: c.h:229
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:301
int i
TupleDesc tupDesc
Definition: typcache.h:76
int compare_values_of_enum ( TypeCacheEntry tcache,
Oid  arg1,
Oid  arg2 
)

Definition at line 1556 of file typcache.c.

References elog, enum_known_sorted(), TypeCacheEntry::enumData, ERROR, find_enumitem(), format_type_be(), load_enum_cache_data(), NULL, EnumItem::sort_order, and TypeCacheEntry::type_id.

Referenced by enum_cmp_internal().

1557 {
1558  TypeCacheEnumData *enumdata;
1559  EnumItem *item1;
1560  EnumItem *item2;
1561 
1562  /*
1563  * Equal OIDs are certainly equal --- this case was probably handled by
1564  * our caller, but we may as well check.
1565  */
1566  if (arg1 == arg2)
1567  return 0;
1568 
1569  /* Load up the cache if first time through */
1570  if (tcache->enumData == NULL)
1571  load_enum_cache_data(tcache);
1572  enumdata = tcache->enumData;
1573 
1574  /*
1575  * If both OIDs are known-sorted, we can just compare them directly.
1576  */
1577  if (enum_known_sorted(enumdata, arg1) &&
1578  enum_known_sorted(enumdata, arg2))
1579  {
1580  if (arg1 < arg2)
1581  return -1;
1582  else
1583  return 1;
1584  }
1585 
1586  /*
1587  * Slow path: we have to identify their actual sort-order positions.
1588  */
1589  item1 = find_enumitem(enumdata, arg1);
1590  item2 = find_enumitem(enumdata, arg2);
1591 
1592  if (item1 == NULL || item2 == NULL)
1593  {
1594  /*
1595  * We couldn't find one or both values. That means the enum has
1596  * changed under us, so re-initialize the cache and try again. We
1597  * don't bother retrying the known-sorted case in this path.
1598  */
1599  load_enum_cache_data(tcache);
1600  enumdata = tcache->enumData;
1601 
1602  item1 = find_enumitem(enumdata, arg1);
1603  item2 = find_enumitem(enumdata, arg2);
1604 
1605  /*
1606  * If we still can't find the values, complain: we must have corrupt
1607  * data.
1608  */
1609  if (item1 == NULL)
1610  elog(ERROR, "enum value %u not found in cache for enum %s",
1611  arg1, format_type_be(tcache->type_id));
1612  if (item2 == NULL)
1613  elog(ERROR, "enum value %u not found in cache for enum %s",
1614  arg2, format_type_be(tcache->type_id));
1615  }
1616 
1617  if (item1->sort_order < item2->sort_order)
1618  return -1;
1619  else if (item1->sort_order > item2->sort_order)
1620  return 1;
1621  else
1622  return 0;
1623 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:103
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define ERROR
Definition: elog.h:43
static bool enum_known_sorted(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:1527
static EnumItem * find_enumitem(TypeCacheEnumData *enumdata, Oid arg)
Definition: typcache.c:1784
#define NULL
Definition: c.h:229
static void load_enum_cache_data(TypeCacheEntry *tcache)
Definition: typcache.c:1629
float4 sort_order
Definition: typcache.c:117
#define elog
Definition: elog.h:219
static void dccref_deletion_callback ( void *  arg)
static

Definition at line 913 of file typcache.c.

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

Referenced by InitDomainConstraintRef().

914 {
916  DomainConstraintCache *dcc = ref->dcc;
917 
918  /* Paranoia --- be sure link is nulled before trying to release */
919  if (dcc)
920  {
921  ref->constraints = NIL;
922  ref->dcc = NULL;
923  decr_dcc_refcount(dcc);
924  }
925 }
#define NIL
Definition: pg_list.h:69
DomainConstraintCache * dcc
Definition: typcache.h:138
#define NULL
Definition: c.h:229
void * arg
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:902
static int dcs_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 889 of file typcache.c.

Referenced by load_domaintype_info().

890 {
891  const DomainConstraintState *const *ca = (const DomainConstraintState *const *) a;
892  const DomainConstraintState *const *cb = (const DomainConstraintState *const *) b;
893 
894  return strcmp((*ca)->name, (*cb)->name);
895 }
static void decr_dcc_refcount ( DomainConstraintCache dcc)
static

Definition at line 902 of file typcache.c.

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

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

903 {
904  Assert(dcc->dccRefCount > 0);
905  if (--(dcc->dccRefCount) <= 0)
907 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
MemoryContext dccContext
Definition: typcache.c:109
#define Assert(condition)
Definition: c.h:676
bool DomainHasConstraints ( Oid  type_id)

Definition at line 1059 of file typcache.c.

References TypeCacheEntry::domainData, lookup_type_cache(), NULL, and TYPECACHE_DOMAIN_INFO.

Referenced by ATColumnChangeRequiresRewrite(), and ATExecAddColumn().

1060 {
1061  TypeCacheEntry *typentry;
1062 
1063  /*
1064  * Note: a side effect is to cause the typcache's domain data to become
1065  * valid. This is fine since we'll likely need it soon if there is any.
1066  */
1067  typentry = lookup_type_cache(type_id, TYPECACHE_DOMAIN_INFO);
1068 
1069  return (typentry->domainData != NULL);
1070 }
DomainConstraintCache * domainData
Definition: typcache.h:94
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define NULL
Definition: c.h:229
#define TYPECACHE_DOMAIN_INFO
Definition: typcache.h:122
static bool enum_known_sorted ( TypeCacheEnumData enumdata,
Oid  arg 
)
inlinestatic

Definition at line 1527 of file typcache.c.

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

Referenced by compare_values_of_enum().

1528 {
1529  Oid offset;
1530 
1531  if (arg < enumdata->bitmap_base)
1532  return false;
1533  offset = arg - enumdata->bitmap_base;
1534  if (offset > (Oid) INT_MAX)
1535  return false;
1536  return bms_is_member((int) offset, enumdata->sorted_values);
1537 }
unsigned int Oid
Definition: postgres_ext.h:31
Bitmapset * sorted_values
Definition: typcache.c:123
void * arg
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
static int enum_oid_cmp ( const void *  left,
const void *  right 
)
static

Definition at line 1801 of file typcache.c.

References EnumItem::enum_oid.

Referenced by find_enumitem(), and load_enum_cache_data().

1802 {
1803  const EnumItem *l = (const EnumItem *) left;
1804  const EnumItem *r = (const EnumItem *) right;
1805 
1806  if (l->enum_oid < r->enum_oid)
1807  return -1;
1808  else if (l->enum_oid > r->enum_oid)
1809  return 1;
1810  else
1811  return 0;
1812 }
Oid enum_oid
Definition: typcache.c:116
static EnumItem * find_enumitem ( TypeCacheEnumData enumdata,
Oid  arg 
)
static

Definition at line 1784 of file typcache.c.

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

Referenced by compare_values_of_enum().

1785 {
1786  EnumItem srch;
1787 
1788  /* On some versions of Solaris, bsearch of zero items dumps core */
1789  if (enumdata->num_values <= 0)
1790  return NULL;
1791 
1792  srch.enum_oid = arg;
1793  return bsearch(&srch, enumdata->enum_values, enumdata->num_values,
1794  sizeof(EnumItem), enum_oid_cmp);
1795 }
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:125
Oid enum_oid
Definition: typcache.c:116
#define NULL
Definition: c.h:229
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:1801
void * arg
void InitDomainConstraintRef ( Oid  type_id,
DomainConstraintRef ref,
MemoryContext  refctx,
bool  need_exprstate 
)

Definition at line 972 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, NULL, prep_domain_constraints(), DomainConstraintRef::refctx, DomainConstraintRef::tcache, and TYPECACHE_DOMAIN_INFO.

Referenced by domain_state_setup(), and ExecInitCoerceToDomain().

974 {
975  /* Look up the typcache entry --- we assume it survives indefinitely */
977  ref->need_exprstate = need_exprstate;
978  /* For safety, establish the callback before acquiring a refcount */
979  ref->refctx = refctx;
980  ref->dcc = NULL;
982  ref->callback.arg = (void *) ref;
984  /* Acquire refcount if there are constraints, and set up exported list */
985  if (ref->tcache->domainData)
986  {
987  ref->dcc = ref->tcache->domainData;
988  ref->dcc->dccRefCount++;
989  if (ref->need_exprstate)
991  ref->refctx);
992  else
993  ref->constraints = ref->dcc->constraints;
994  }
995  else
996  ref->constraints = NIL;
997 }
MemoryContextCallback callback
Definition: typcache.h:139
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define NIL
Definition: pg_list.h:69
DomainConstraintCache * dcc
Definition: typcache.h:138
static void dccref_deletion_callback(void *arg)
Definition: typcache.c:913
DomainConstraintCache * domainData
Definition: typcache.h:94
MemoryContext refctx
Definition: typcache.h:133
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define NULL
Definition: c.h:229
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:934
TypeCacheEntry * tcache
Definition: typcache.h:134
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:265
#define TYPECACHE_DOMAIN_INFO
Definition: typcache.h:122
static void load_domaintype_info ( TypeCacheEntry typentry)
static

Definition at line 662 of file typcache.c.

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), Anum_pg_constraint_conbin, Anum_pg_constraint_contypid, BTEqualStrategyNumber, CacheMemoryContext, DomainConstraintState::check_expr, DomainConstraintState::check_exprstate, CONSTRAINT_CHECK, ConstraintRelationId, 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, heap_close, heap_open(), HeapTupleIsValid, lcons(), makeNode, MemoryContextAlloc(), MemoryContextSetParent(), MemoryContextSwitchTo(), DomainConstraintState::name, NameStr, NIL, NULL, ObjectIdGetDatum, palloc(), pstrdup(), qsort, RelationData::rd_att, ReleaseSysCache(), repalloc(), ScanKeyInit(), SearchSysCache1, stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TextDatumGetCString, TypeCacheEntry::type_id, TYPEOID, TYPTYPE_DOMAIN, and val.

Referenced by lookup_type_cache(), and UpdateDomainConstraintRef().

663 {
664  Oid typeOid = typentry->type_id;
666  bool notNull = false;
667  DomainConstraintState **ccons;
668  int cconslen;
669  Relation conRel;
670  MemoryContext oldcxt;
671 
672  /*
673  * If we're here, any existing constraint info is stale, so release it.
674  * For safety, be sure to null the link before trying to delete the data.
675  */
676  if (typentry->domainData)
677  {
678  dcc = typentry->domainData;
679  typentry->domainData = NULL;
680  decr_dcc_refcount(dcc);
681  }
682 
683  /*
684  * We try to optimize the common case of no domain constraints, so don't
685  * create the dcc object and context until we find a constraint. Likewise
686  * for the temp sorting array.
687  */
688  dcc = NULL;
689  ccons = NULL;
690  cconslen = 0;
691 
692  /*
693  * Scan pg_constraint for relevant constraints. We want to find
694  * constraints for not just this domain, but any ancestor domains, so the
695  * outer loop crawls up the domain stack.
696  */
698 
699  for (;;)
700  {
701  HeapTuple tup;
702  HeapTuple conTup;
703  Form_pg_type typTup;
704  int nccons = 0;
705  ScanKeyData key[1];
706  SysScanDesc scan;
707 
708  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
709  if (!HeapTupleIsValid(tup))
710  elog(ERROR, "cache lookup failed for type %u", typeOid);
711  typTup = (Form_pg_type) GETSTRUCT(tup);
712 
713  if (typTup->typtype != TYPTYPE_DOMAIN)
714  {
715  /* Not a domain, so done */
716  ReleaseSysCache(tup);
717  break;
718  }
719 
720  /* Test for NOT NULL Constraint */
721  if (typTup->typnotnull)
722  notNull = true;
723 
724  /* Look for CHECK Constraints on this domain */
725  ScanKeyInit(&key[0],
727  BTEqualStrategyNumber, F_OIDEQ,
728  ObjectIdGetDatum(typeOid));
729 
730  scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
731  NULL, 1, key);
732 
733  while (HeapTupleIsValid(conTup = systable_getnext(scan)))
734  {
736  Datum val;
737  bool isNull;
738  char *constring;
739  Expr *check_expr;
741 
742  /* Ignore non-CHECK constraints (presently, shouldn't be any) */
743  if (c->contype != CONSTRAINT_CHECK)
744  continue;
745 
746  /* Not expecting conbin to be NULL, but we'll test for it anyway */
748  conRel->rd_att, &isNull);
749  if (isNull)
750  elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
751  NameStr(typTup->typname), NameStr(c->conname));
752 
753  /* Convert conbin to C string in caller context */
754  constring = TextDatumGetCString(val);
755 
756  /* Create the DomainConstraintCache object and context if needed */
757  if (dcc == NULL)
758  {
759  MemoryContext cxt;
760 
762  "Domain constraints",
764  dcc = (DomainConstraintCache *)
766  dcc->constraints = NIL;
767  dcc->dccContext = cxt;
768  dcc->dccRefCount = 0;
769  }
770 
771  /* Create node trees in DomainConstraintCache's context */
772  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
773 
774  check_expr = (Expr *) stringToNode(constring);
775 
776  /* ExecInitExpr will assume we've planned the expression */
777  check_expr = expression_planner(check_expr);
778 
781  r->name = pstrdup(NameStr(c->conname));
782  r->check_expr = check_expr;
783  r->check_exprstate = NULL;
784 
785  MemoryContextSwitchTo(oldcxt);
786 
787  /* Accumulate constraints in an array, for sorting below */
788  if (ccons == NULL)
789  {
790  cconslen = 8;
791  ccons = (DomainConstraintState **)
792  palloc(cconslen * sizeof(DomainConstraintState *));
793  }
794  else if (nccons >= cconslen)
795  {
796  cconslen *= 2;
797  ccons = (DomainConstraintState **)
798  repalloc(ccons, cconslen * sizeof(DomainConstraintState *));
799  }
800  ccons[nccons++] = r;
801  }
802 
803  systable_endscan(scan);
804 
805  if (nccons > 0)
806  {
807  /*
808  * Sort the items for this domain, so that CHECKs are applied in a
809  * deterministic order.
810  */
811  if (nccons > 1)
812  qsort(ccons, nccons, sizeof(DomainConstraintState *), dcs_cmp);
813 
814  /*
815  * Now attach them to the overall list. Use lcons() here because
816  * constraints of parent domains should be applied earlier.
817  */
818  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
819  while (nccons > 0)
820  dcc->constraints = lcons(ccons[--nccons], dcc->constraints);
821  MemoryContextSwitchTo(oldcxt);
822  }
823 
824  /* loop to next domain in stack */
825  typeOid = typTup->typbasetype;
826  ReleaseSysCache(tup);
827  }
828 
829  heap_close(conRel, AccessShareLock);
830 
831  /*
832  * Only need to add one NOT NULL check regardless of how many domains in
833  * the stack request it.
834  */
835  if (notNull)
836  {
838 
839  /* Create the DomainConstraintCache object and context if needed */
840  if (dcc == NULL)
841  {
842  MemoryContext cxt;
843 
845  "Domain constraints",
847  dcc = (DomainConstraintCache *)
849  dcc->constraints = NIL;
850  dcc->dccContext = cxt;
851  dcc->dccRefCount = 0;
852  }
853 
854  /* Create node trees in DomainConstraintCache's context */
855  oldcxt = MemoryContextSwitchTo(dcc->dccContext);
856 
858 
860  r->name = pstrdup("NOT NULL");
861  r->check_expr = NULL;
862  r->check_exprstate = NULL;
863 
864  /* lcons to apply the nullness check FIRST */
865  dcc->constraints = lcons(r, dcc->constraints);
866 
867  MemoryContextSwitchTo(oldcxt);
868  }
869 
870  /*
871  * If we made a constraint object, move it into CacheMemoryContext and
872  * attach it to the typcache entry.
873  */
874  if (dcc)
875  {
877  typentry->domainData = dcc;
878  dcc->dccRefCount++; /* count the typcache's reference */
879  }
880 
881  /* Either way, the typcache entry's domain data is now valid. */
883 }
#define NIL
Definition: pg_list.h:69
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
void * stringToNode(char *str)
Definition: read.c:38
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
MemoryContext dccContext
Definition: typcache.c:109
DomainConstraintType constrainttype
Definition: execnodes.h:809
DomainConstraintCache * domainData
Definition: typcache.h:94
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
char * pstrdup(const char *in)
Definition: mcxt.c:1077
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:175
Expr * expression_planner(Expr *expr)
Definition: planner.c:5939
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
static int dcs_cmp(const void *a, const void *b)
Definition: typcache.c:889
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define Anum_pg_constraint_conbin
#define ConstraintTypidIndexId
Definition: indexing.h:128
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define CONSTRAINT_CHECK
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * c
ExprState * check_exprstate
Definition: execnodes.h:812
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define Anum_pg_constraint_contypid
#define TextDatumGetCString(d)
Definition: builtins.h:92
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
List * lcons(void *datum, List *list)
Definition: list.c:259
#define makeNode(_type_)
Definition: nodes.h:557
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:92
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
void * palloc(Size size)
Definition: mcxt.c:849
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
#define NameStr(name)
Definition: c.h:499
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define qsort(a, b, c, d)
Definition: port.h:443
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:902
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void load_enum_cache_data ( TypeCacheEntry tcache)
static

Definition at line 1629 of file typcache.c.

References AccessShareLock, Anum_pg_enum_enumtypid, 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, EnumRelationId, EnumTypIdLabelIndexId, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, i, InvalidOid, MemoryContextSwitchTo(), NULL, TypeCacheEnumData::num_values, ObjectIdGetDatum, offsetof, palloc(), pfree(), qsort, repalloc(), ScanKeyInit(), EnumItem::sort_order, TypeCacheEnumData::sorted_values, systable_beginscan(), systable_endscan(), systable_getnext(), TypeCacheEntry::type_id, TypeCacheEntry::typtype, and TYPTYPE_ENUM.

Referenced by compare_values_of_enum().

1630 {
1631  TypeCacheEnumData *enumdata;
1632  Relation enum_rel;
1633  SysScanDesc enum_scan;
1634  HeapTuple enum_tuple;
1635  ScanKeyData skey;
1636  EnumItem *items;
1637  int numitems;
1638  int maxitems;
1639  Oid bitmap_base;
1640  Bitmapset *bitmap;
1641  MemoryContext oldcxt;
1642  int bm_size,
1643  start_pos;
1644 
1645  /* Check that this is actually an enum */
1646  if (tcache->typtype != TYPTYPE_ENUM)
1647  ereport(ERROR,
1648  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1649  errmsg("%s is not an enum",
1650  format_type_be(tcache->type_id))));
1651 
1652  /*
1653  * Read all the information for members of the enum type. We collect the
1654  * info in working memory in the caller's context, and then transfer it to
1655  * permanent memory in CacheMemoryContext. This minimizes the risk of
1656  * leaking memory from CacheMemoryContext in the event of an error partway
1657  * through.
1658  */
1659  maxitems = 64;
1660  items = (EnumItem *) palloc(sizeof(EnumItem) * maxitems);
1661  numitems = 0;
1662 
1663  /* Scan pg_enum for the members of the target enum type. */
1664  ScanKeyInit(&skey,
1666  BTEqualStrategyNumber, F_OIDEQ,
1667  ObjectIdGetDatum(tcache->type_id));
1668 
1670  enum_scan = systable_beginscan(enum_rel,
1672  true, NULL,
1673  1, &skey);
1674 
1675  while (HeapTupleIsValid(enum_tuple = systable_getnext(enum_scan)))
1676  {
1677  Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enum_tuple);
1678 
1679  if (numitems >= maxitems)
1680  {
1681  maxitems *= 2;
1682  items = (EnumItem *) repalloc(items, sizeof(EnumItem) * maxitems);
1683  }
1684  items[numitems].enum_oid = HeapTupleGetOid(enum_tuple);
1685  items[numitems].sort_order = en->enumsortorder;
1686  numitems++;
1687  }
1688 
1689  systable_endscan(enum_scan);
1690  heap_close(enum_rel, AccessShareLock);
1691 
1692  /* Sort the items into OID order */
1693  qsort(items, numitems, sizeof(EnumItem), enum_oid_cmp);
1694 
1695  /*
1696  * Here, we create a bitmap listing a subset of the enum's OIDs that are
1697  * known to be in order and can thus be compared with just OID comparison.
1698  *
1699  * The point of this is that the enum's initial OIDs were certainly in
1700  * order, so there is some subset that can be compared via OID comparison;
1701  * and we'd rather not do binary searches unnecessarily.
1702  *
1703  * This is somewhat heuristic, and might identify a subset of OIDs that
1704  * isn't exactly what the type started with. That's okay as long as the
1705  * subset is correctly sorted.
1706  */
1707  bitmap_base = InvalidOid;
1708  bitmap = NULL;
1709  bm_size = 1; /* only save sets of at least 2 OIDs */
1710 
1711  for (start_pos = 0; start_pos < numitems - 1; start_pos++)
1712  {
1713  /*
1714  * Identify longest sorted subsequence starting at start_pos
1715  */
1716  Bitmapset *this_bitmap = bms_make_singleton(0);
1717  int this_bm_size = 1;
1718  Oid start_oid = items[start_pos].enum_oid;
1719  float4 prev_order = items[start_pos].sort_order;
1720  int i;
1721 
1722  for (i = start_pos + 1; i < numitems; i++)
1723  {
1724  Oid offset;
1725 
1726  offset = items[i].enum_oid - start_oid;
1727  /* quit if bitmap would be too large; cutoff is arbitrary */
1728  if (offset >= 8192)
1729  break;
1730  /* include the item if it's in-order */
1731  if (items[i].sort_order > prev_order)
1732  {
1733  prev_order = items[i].sort_order;
1734  this_bitmap = bms_add_member(this_bitmap, (int) offset);
1735  this_bm_size++;
1736  }
1737  }
1738 
1739  /* Remember it if larger than previous best */
1740  if (this_bm_size > bm_size)
1741  {
1742  bms_free(bitmap);
1743  bitmap_base = start_oid;
1744  bitmap = this_bitmap;
1745  bm_size = this_bm_size;
1746  }
1747  else
1748  bms_free(this_bitmap);
1749 
1750  /*
1751  * Done if it's not possible to find a longer sequence in the rest of
1752  * the list. In typical cases this will happen on the first
1753  * iteration, which is why we create the bitmaps on the fly instead of
1754  * doing a second pass over the list.
1755  */
1756  if (bm_size >= (numitems - start_pos - 1))
1757  break;
1758  }
1759 
1760  /* OK, copy the data into CacheMemoryContext */
1762  enumdata = (TypeCacheEnumData *)
1763  palloc(offsetof(TypeCacheEnumData, enum_values) +
1764  numitems * sizeof(EnumItem));
1765  enumdata->bitmap_base = bitmap_base;
1766  enumdata->sorted_values = bms_copy(bitmap);
1767  enumdata->num_values = numitems;
1768  memcpy(enumdata->enum_values, items, numitems * sizeof(EnumItem));
1769  MemoryContextSwitchTo(oldcxt);
1770 
1771  pfree(items);
1772  bms_free(bitmap);
1773 
1774  /* And link the finished cache struct into the typcache */
1775  if (tcache->enumData != NULL)
1776  pfree(tcache->enumData);
1777  tcache->enumData = enumdata;
1778 }
struct TypeCacheEnumData * enumData
Definition: typcache.h:103
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define EnumTypIdLabelIndexId
Definition: indexing.h:157
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
Bitmapset * sorted_values
Definition: typcache.c:123
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define EnumRelationId
Definition: pg_enum.h:32
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:179
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:46
#define ereport(elevel, rest)
Definition: elog.h:122
EnumItem enum_values[FLEXIBLE_ARRAY_MEMBER]
Definition: typcache.c:125
float float4
Definition: c.h:380
Oid enum_oid
Definition: typcache.c:116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
char typtype
Definition: typcache.h:39
void bms_free(Bitmapset *a)
Definition: bitmapset.c:201
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
#define Anum_pg_enum_enumtypid
Definition: pg_enum.h:53
float4 sort_order
Definition: typcache.c:117
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
static int enum_oid_cmp(const void *left, const void *right)
Definition: typcache.c:1801
int i
#define TYPTYPE_ENUM
Definition: pg_type.h:723
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define qsort(a, b, c, d)
Definition: port.h:443
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define offsetof(type, field)
Definition: c.h:555
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void load_rangetype_info ( TypeCacheEntry typentry)
static

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

600 {
601  Form_pg_range pg_range;
602  HeapTuple tup;
603  Oid subtypeOid;
604  Oid opclassOid;
605  Oid canonicalOid;
606  Oid subdiffOid;
607  Oid opfamilyOid;
608  Oid opcintype;
609  Oid cmpFnOid;
610 
611  /* get information from pg_range */
613  /* should not fail, since we already checked typtype ... */
614  if (!HeapTupleIsValid(tup))
615  elog(ERROR, "cache lookup failed for range type %u",
616  typentry->type_id);
617  pg_range = (Form_pg_range) GETSTRUCT(tup);
618 
619  subtypeOid = pg_range->rngsubtype;
620  typentry->rng_collation = pg_range->rngcollation;
621  opclassOid = pg_range->rngsubopc;
622  canonicalOid = pg_range->rngcanonical;
623  subdiffOid = pg_range->rngsubdiff;
624 
625  ReleaseSysCache(tup);
626 
627  /* get opclass properties and look up the comparison function */
628  opfamilyOid = get_opclass_family(opclassOid);
629  opcintype = get_opclass_input_type(opclassOid);
630 
631  cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
632  BTORDER_PROC);
633  if (!RegProcedureIsValid(cmpFnOid))
634  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
635  BTORDER_PROC, opcintype, opcintype, opfamilyOid);
636 
637  /* set up cached fmgrinfo structs */
638  fmgr_info_cxt(cmpFnOid, &typentry->rng_cmp_proc_finfo,
640  if (OidIsValid(canonicalOid))
641  fmgr_info_cxt(canonicalOid, &typentry->rng_canonical_finfo,
643  if (OidIsValid(subdiffOid))
644  fmgr_info_cxt(subdiffOid, &typentry->rng_subdiff_finfo,
646 
647  /* Lastly, set up link to the element type --- this marks data valid */
648  typentry->rngelemtype = lookup_type_cache(subtypeOid, 0);
649 }
FormData_pg_range * Form_pg_range
Definition: pg_range.h:49
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:86
#define BTORDER_PROC
Definition: nbtree.h:229
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
FmgrInfo rng_subdiff_finfo
Definition: typcache.h:88
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RegProcedureIsValid(p)
Definition: c.h:540
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
FmgrInfo rng_canonical_finfo
Definition: typcache.h:87
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:84
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
Oid rng_collation
Definition: typcache.h:85
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1047
#define elog
Definition: elog.h:219
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1069
static void load_typcache_tupdesc ( TypeCacheEntry typentry)
static

Definition at line 571 of file typcache.c.

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

Referenced by cache_record_field_properties(), and lookup_type_cache().

572 {
573  Relation rel;
574 
575  if (!OidIsValid(typentry->typrelid)) /* should not happen */
576  elog(ERROR, "invalid typrelid for composite type %u",
577  typentry->type_id);
578  rel = relation_open(typentry->typrelid, AccessShareLock);
579  Assert(rel->rd_rel->reltype == typentry->type_id);
580 
581  /*
582  * Link to the tupdesc and increment its refcount (we assert it's a
583  * refcounted descriptor). We don't use IncrTupleDescRefCount() for this,
584  * because the reference mustn't be entered in the current resource owner;
585  * it can outlive the current query.
586  */
587  typentry->tupDesc = RelationGetDescr(rel);
588 
589  Assert(typentry->tupDesc->tdrefcount > 0);
590  typentry->tupDesc->tdrefcount++;
591 
593 }
#define RelationGetDescr(relation)
Definition: rel.h:428
#define AccessShareLock
Definition: lockdefs.h:36
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
Form_pg_class rd_rel
Definition: rel.h:114
#define OidIsValid(objectId)
Definition: c.h:538
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:676
int tdrefcount
Definition: tupdesc.h:77
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define elog
Definition: elog.h:219
TupleDesc tupDesc
Definition: typcache.h:76
TupleDesc lookup_rowtype_tupdesc_copy ( Oid  type_id,
int32  typmod 
)

Definition at line 1292 of file typcache.c.

References CreateTupleDescCopyConstr(), and lookup_rowtype_tupdesc_internal().

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

1293 {
1294  TupleDesc tmp;
1295 
1296  tmp = lookup_rowtype_tupdesc_internal(type_id, typmod, false);
1297  return CreateTupleDescCopyConstr(tmp);
1298 }
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:129
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1211
static TupleDesc lookup_rowtype_tupdesc_internal ( Oid  type_id,
int32  typmod,
bool  noError 
)
static

Definition at line 1211 of file typcache.c.

References ereport, errcode(), errmsg(), ERROR, format_type_be(), lookup_type_cache(), NextRecordTypmod, NULL, RECORDOID, TypeCacheEntry::tupDesc, and TYPECACHE_TUPDESC.

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

1212 {
1213  if (type_id != RECORDOID)
1214  {
1215  /*
1216  * It's a named composite type, so use the regular typcache.
1217  */
1218  TypeCacheEntry *typentry;
1219 
1220  typentry = lookup_type_cache(type_id, TYPECACHE_TUPDESC);
1221  if (typentry->tupDesc == NULL && !noError)
1222  ereport(ERROR,
1223  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1224  errmsg("type %s is not composite",
1225  format_type_be(type_id))));
1226  return typentry->tupDesc;
1227  }
1228  else
1229  {
1230  /*
1231  * It's a transient record type, so look in our record-type table.
1232  */
1233  if (typmod < 0 || typmod >= NextRecordTypmod)
1234  {
1235  if (!noError)
1236  ereport(ERROR,
1237  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1238  errmsg("record type has not been registered")));
1239  return NULL;
1240  }
1241  return RecordCacheArray[typmod];
1242  }
1243 }
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
static TupleDesc * RecordCacheArray
Definition: typcache.c:153
#define ERROR
Definition: elog.h:43
#define RECORDOID
Definition: pg_type.h:680
#define ereport(elevel, rest)
Definition: elog.h:122
static int32 NextRecordTypmod
Definition: typcache.c:155
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define NULL
Definition: c.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:797
TupleDesc tupDesc
Definition: typcache.h:76
#define TYPECACHE_TUPDESC
Definition: typcache.h:118
TupleDesc lookup_rowtype_tupdesc_noerror ( Oid  type_id,
int32  typmod,
bool  noError 
)

Definition at line 1275 of file typcache.c.

References IncrTupleDescRefCount(), lookup_rowtype_tupdesc_internal(), and NULL.

Referenced by plperl_sv_to_datum().

1276 {
1277  TupleDesc tupDesc;
1278 
1279  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1280  if (tupDesc != NULL)
1281  IncrTupleDescRefCount(tupDesc);
1282  return tupDesc;
1283 }
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:283
#define NULL
Definition: c.h:229
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1211
TypeCacheEntry* lookup_type_cache ( Oid  type_id,
int  flags 
)

Definition at line 191 of file typcache.c.

References array_element_has_compare(), array_element_has_equality(), array_element_has_hashing(), ARRAY_EQ_OP, ARRAY_GT_OP, ARRAY_LT_OP, Assert, BTEqualStrategyNumber, BTGreaterStrategyNumber, BTLessStrategyNumber, BTORDER_PROC, BTREE_AM_OID, TypeCacheEntry::btree_opf, TypeCacheEntry::btree_opintype, CacheMemoryContext, CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), CLAOID, TypeCacheEntry::cmp_proc, TypeCacheEntry::cmp_proc_finfo, CONSTROID, CreateCacheMemoryContext(), 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(), GetDefaultOpClass(), GETSTRUCT, TypeCacheEntry::gt_opr, HASH_AM_OID, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FIND, TypeCacheEntry::hash_opf, TypeCacheEntry::hash_opintype, TypeCacheEntry::hash_proc, TypeCacheEntry::hash_proc_finfo, hash_search(), HASHPROC, HeapTupleIsValid, HTEqualStrategyNumber, InvalidOid, HASHCTL::keysize, load_domaintype_info(), load_rangetype_info(), load_typcache_tupdesc(), TypeCacheEntry::lt_opr, MemSet, NameStr, TypeCacheEntry::nextDomain, NULL, ObjectIdGetDatum, OidIsValid, RECORD_EQ_OP, record_fields_have_compare(), record_fields_have_equality(), RECORD_GT_OP, RECORD_LT_OP, 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_OPCLASS, TCFLAGS_CHECKED_HASH_PROC, TCFLAGS_CHECKED_LT_OPR, TypeCacheEntry::tupDesc, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TYPECACHE_BTREE_OPFAMILY, TYPECACHE_CMP_PROC, TYPECACHE_CMP_PROC_FINFO, TYPECACHE_DOMAIN_INFO, TYPECACHE_EQ_OPR, TYPECACHE_EQ_OPR_FINFO, TYPECACHE_GT_OPR, TYPECACHE_HASH_OPFAMILY, TYPECACHE_HASH_PROC, TYPECACHE_HASH_PROC_FINFO, TYPECACHE_LT_OPR, TYPECACHE_RANGE_INFO, TYPECACHE_TUPDESC, TypeCacheConstrCallback(), TypeCacheOpcCallback(), TypeCacheRelCallback(), TYPEOID, TypeCacheEntry::typlen, TypeCacheEntry::typrelid, TypeCacheEntry::typstorage, TypeCacheEntry::typtype, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, and TYPTYPE_RANGE.

Referenced by appendAggOrderBy(), array_cmp(), array_contain_compare(), array_eq(), array_position_common(), array_positions(), array_replace_internal(), array_typanalyze(), brin_inclusion_opcinfo(), brin_minmax_opcinfo(), BuildRangeRemapInfo(), cache_array_element_properties(), cache_record_field_properties(), calc_arraycontsel(), 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_range(), InitDomainConstraintRef(), initGinState(), load_rangetype_info(), lookup_rowtype_tupdesc_internal(), ndistinct_for_combination(), op_hashjoinable(), op_mergejoinable(), range_get_typcache(), record_cmp(), record_eq(), refresh_by_match_merge(), scalararraysel(), scalararraysel_containment(), show_sortorder_options(), tuple_equals_slot(), and width_bucket_array().

192 {
193  TypeCacheEntry *typentry;
194  bool found;
195 
196  if (TypeCacheHash == NULL)
197  {
198  /* First time through: initialize the hash table */
199  HASHCTL ctl;
200 
201  MemSet(&ctl, 0, sizeof(ctl));
202  ctl.keysize = sizeof(Oid);
203  ctl.entrysize = sizeof(TypeCacheEntry);
204  TypeCacheHash = hash_create("Type information cache", 64,
205  &ctl, HASH_ELEM | HASH_BLOBS);
206 
207  /* Also set up callbacks for SI invalidations */
212 
213  /* Also make sure CacheMemoryContext exists */
214  if (!CacheMemoryContext)
216  }
217 
218  /* Try to look up an existing entry */
220  (void *) &type_id,
221  HASH_FIND, NULL);
222  if (typentry == NULL)
223  {
224  /*
225  * If we didn't find one, we want to make one. But first look up the
226  * pg_type row, just to make sure we don't make a cache entry for an
227  * invalid type OID. If the type OID is not valid, present a
228  * user-facing error, since some code paths such as domain_in() allow
229  * this function to be reached with a user-supplied OID.
230  */
231  HeapTuple tp;
232  Form_pg_type typtup;
233 
234  tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
235  if (!HeapTupleIsValid(tp))
236  ereport(ERROR,
237  (errcode(ERRCODE_UNDEFINED_OBJECT),
238  errmsg("type with OID %u does not exist", type_id)));
239  typtup = (Form_pg_type) GETSTRUCT(tp);
240  if (!typtup->typisdefined)
241  ereport(ERROR,
242  (errcode(ERRCODE_UNDEFINED_OBJECT),
243  errmsg("type \"%s\" is only a shell",
244  NameStr(typtup->typname))));
245 
246  /* Now make the typcache entry */
248  (void *) &type_id,
249  HASH_ENTER, &found);
250  Assert(!found); /* it wasn't there a moment ago */
251 
252  MemSet(typentry, 0, sizeof(TypeCacheEntry));
253  typentry->type_id = type_id;
254  typentry->typlen = typtup->typlen;
255  typentry->typbyval = typtup->typbyval;
256  typentry->typalign = typtup->typalign;
257  typentry->typstorage = typtup->typstorage;
258  typentry->typtype = typtup->typtype;
259  typentry->typrelid = typtup->typrelid;
260 
261  /* If it's a domain, immediately thread it into the domain cache list */
262  if (typentry->typtype == TYPTYPE_DOMAIN)
263  {
264  typentry->nextDomain = firstDomainTypeEntry;
265  firstDomainTypeEntry = typentry;
266  }
267 
268  ReleaseSysCache(tp);
269  }
270 
271  /*
272  * Look up opclasses if we haven't already and any dependent info is
273  * requested.
274  */
279  !(typentry->flags & TCFLAGS_CHECKED_BTREE_OPCLASS))
280  {
281  Oid opclass;
282 
283  opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
284  if (OidIsValid(opclass))
285  {
286  typentry->btree_opf = get_opclass_family(opclass);
287  typentry->btree_opintype = get_opclass_input_type(opclass);
288  }
289  else
290  {
291  typentry->btree_opf = typentry->btree_opintype = InvalidOid;
292  }
293 
294  /*
295  * Reset information derived from btree opclass. Note in particular
296  * that we'll redetermine the eq_opr even if we previously found one;
297  * this matters in case a btree opclass has been added to a type that
298  * previously had only a hash opclass.
299  */
300  typentry->flags &= ~(TCFLAGS_CHECKED_EQ_OPR |
305  }
306 
307  /*
308  * If we need to look up equality operator, and there's no btree opclass,
309  * force lookup of hash opclass.
310  */
311  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
312  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR) &&
313  typentry->btree_opf == InvalidOid)
314  flags |= TYPECACHE_HASH_OPFAMILY;
315 
318  !(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
319  {
320  Oid opclass;
321 
322  opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
323  if (OidIsValid(opclass))
324  {
325  typentry->hash_opf = get_opclass_family(opclass);
326  typentry->hash_opintype = get_opclass_input_type(opclass);
327  }
328  else
329  {
330  typentry->hash_opf = typentry->hash_opintype = InvalidOid;
331  }
332 
333  /*
334  * Reset information derived from hash opclass. We do *not* reset the
335  * eq_opr; if we already found one from the btree opclass, that
336  * decision is still good.
337  */
338  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC);
339  typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
340  }
341 
342  /*
343  * Look for requested operators and functions, if we haven't already.
344  */
345  if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
346  !(typentry->flags & TCFLAGS_CHECKED_EQ_OPR))
347  {
348  Oid eq_opr = InvalidOid;
349 
350  if (typentry->btree_opf != InvalidOid)
351  eq_opr = get_opfamily_member(typentry->btree_opf,
352  typentry->btree_opintype,
353  typentry->btree_opintype,
355  if (eq_opr == InvalidOid &&
356  typentry->hash_opf != InvalidOid)
357  eq_opr = get_opfamily_member(typentry->hash_opf,
358  typentry->hash_opintype,
359  typentry->hash_opintype,
361 
362  /*
363  * If the proposed equality operator is array_eq or record_eq, check
364  * to see if the element type or column types support equality. If
365  * not, array_eq or record_eq would fail at runtime, so we don't want
366  * to report that the type has equality.
367  */
368  if (eq_opr == ARRAY_EQ_OP &&
369  !array_element_has_equality(typentry))
370  eq_opr = InvalidOid;
371  else if (eq_opr == RECORD_EQ_OP &&
372  !record_fields_have_equality(typentry))
373  eq_opr = InvalidOid;
374 
375  /* Force update of eq_opr_finfo only if we're changing state */
376  if (typentry->eq_opr != eq_opr)
377  typentry->eq_opr_finfo.fn_oid = InvalidOid;
378 
379  typentry->eq_opr = eq_opr;
380 
381  /*
382  * Reset info about hash function whenever we pick up new info about
383  * equality operator. This is so we can ensure that the hash function
384  * matches the operator.
385  */
386  typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC);
387  typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
388  }
389  if ((flags & TYPECACHE_LT_OPR) &&
390  !(typentry->flags & TCFLAGS_CHECKED_LT_OPR))
391  {
392  Oid lt_opr = InvalidOid;
393 
394  if (typentry->btree_opf != InvalidOid)
395  lt_opr = get_opfamily_member(typentry->btree_opf,
396  typentry->btree_opintype,
397  typentry->btree_opintype,
399 
400  /* As above, make sure array_cmp or record_cmp will succeed */
401  if (lt_opr == ARRAY_LT_OP &&
402  !array_element_has_compare(typentry))
403  lt_opr = InvalidOid;
404  else if (lt_opr == RECORD_LT_OP &&
405  !record_fields_have_compare(typentry))
406  lt_opr = InvalidOid;
407 
408  typentry->lt_opr = lt_opr;
409  typentry->flags |= TCFLAGS_CHECKED_LT_OPR;
410  }
411  if ((flags & TYPECACHE_GT_OPR) &&
412  !(typentry->flags & TCFLAGS_CHECKED_GT_OPR))
413  {
414  Oid gt_opr = InvalidOid;
415 
416  if (typentry->btree_opf != InvalidOid)
417  gt_opr = get_opfamily_member(typentry->btree_opf,
418  typentry->btree_opintype,
419  typentry->btree_opintype,
421 
422  /* As above, make sure array_cmp or record_cmp will succeed */
423  if (gt_opr == ARRAY_GT_OP &&
424  !array_element_has_compare(typentry))
425  gt_opr = InvalidOid;
426  else if (gt_opr == RECORD_GT_OP &&
427  !record_fields_have_compare(typentry))
428  gt_opr = InvalidOid;
429 
430  typentry->gt_opr = gt_opr;
431  typentry->flags |= TCFLAGS_CHECKED_GT_OPR;
432  }
433  if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
434  !(typentry->flags & TCFLAGS_CHECKED_CMP_PROC))
435  {
436  Oid cmp_proc = InvalidOid;
437 
438  if (typentry->btree_opf != InvalidOid)
439  cmp_proc = get_opfamily_proc(typentry->btree_opf,
440  typentry->btree_opintype,
441  typentry->btree_opintype,
442  BTORDER_PROC);
443 
444  /* As above, make sure array_cmp or record_cmp will succeed */
445  if (cmp_proc == F_BTARRAYCMP &&
446  !array_element_has_compare(typentry))
447  cmp_proc = InvalidOid;
448  else if (cmp_proc == F_BTRECORDCMP &&
449  !record_fields_have_compare(typentry))
450  cmp_proc = InvalidOid;
451 
452  /* Force update of cmp_proc_finfo only if we're changing state */
453  if (typentry->cmp_proc != cmp_proc)
454  typentry->cmp_proc_finfo.fn_oid = InvalidOid;
455 
456  typentry->cmp_proc = cmp_proc;
457  typentry->flags |= TCFLAGS_CHECKED_CMP_PROC;
458  }
460  !(typentry->flags & TCFLAGS_CHECKED_HASH_PROC))
461  {
462  Oid hash_proc = InvalidOid;
463 
464  /*
465  * We insist that the eq_opr, if one has been determined, match the
466  * hash opclass; else report there is no hash function.
467  */
468  if (typentry->hash_opf != InvalidOid &&
469  (!OidIsValid(typentry->eq_opr) ||
470  typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
471  typentry->hash_opintype,
472  typentry->hash_opintype,
474  hash_proc = get_opfamily_proc(typentry->hash_opf,
475  typentry->hash_opintype,
476  typentry->hash_opintype,
477  HASHPROC);
478 
479  /*
480  * As above, make sure hash_array will succeed. We don't currently
481  * support hashing for composite types, but when we do, we'll need
482  * more logic here to check that case too.
483  */
484  if (hash_proc == F_HASH_ARRAY &&
485  !array_element_has_hashing(typentry))
486  hash_proc = InvalidOid;
487 
488  /* Force update of hash_proc_finfo only if we're changing state */
489  if (typentry->hash_proc != hash_proc)
490  typentry->hash_proc_finfo.fn_oid = InvalidOid;
491 
492  typentry->hash_proc = hash_proc;
493  typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
494  }
495 
496  /*
497  * Set up fmgr lookup info as requested
498  *
499  * Note: we tell fmgr the finfo structures live in CacheMemoryContext,
500  * which is not quite right (they're really in the hash table's private
501  * memory context) but this will do for our purposes.
502  *
503  * Note: the code above avoids invalidating the finfo structs unless the
504  * referenced operator/function OID actually changes. This is to prevent
505  * unnecessary leakage of any subsidiary data attached to an finfo, since
506  * that would cause session-lifespan memory leaks.
507  */
508  if ((flags & TYPECACHE_EQ_OPR_FINFO) &&
509  typentry->eq_opr_finfo.fn_oid == InvalidOid &&
510  typentry->eq_opr != InvalidOid)
511  {
512  Oid eq_opr_func;
513 
514  eq_opr_func = get_opcode(typentry->eq_opr);
515  if (eq_opr_func != InvalidOid)
516  fmgr_info_cxt(eq_opr_func, &typentry->eq_opr_finfo,
518  }
519  if ((flags & TYPECACHE_CMP_PROC_FINFO) &&
520  typentry->cmp_proc_finfo.fn_oid == InvalidOid &&
521  typentry->cmp_proc != InvalidOid)
522  {
523  fmgr_info_cxt(typentry->cmp_proc, &typentry->cmp_proc_finfo,
525  }
526  if ((flags & TYPECACHE_HASH_PROC_FINFO) &&
527  typentry->hash_proc_finfo.fn_oid == InvalidOid &&
528  typentry->hash_proc != InvalidOid)
529  {
530  fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
532  }
533 
534  /*
535  * If it's a composite type (row type), get tupdesc if requested
536  */
537  if ((flags & TYPECACHE_TUPDESC) &&
538  typentry->tupDesc == NULL &&
539  typentry->typtype == TYPTYPE_COMPOSITE)
540  {
541  load_typcache_tupdesc(typentry);
542  }
543 
544  /*
545  * If requested, get information about a range type
546  */
547  if ((flags & TYPECACHE_RANGE_INFO) &&
548  typentry->rngelemtype == NULL &&
549  typentry->typtype == TYPTYPE_RANGE)
550  {
551  load_rangetype_info(typentry);
552  }
553 
554  /*
555  * If requested, get information about a domain type
556  */
557  if ((flags & TYPECACHE_DOMAIN_INFO) &&
558  (typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
559  typentry->typtype == TYPTYPE_DOMAIN)
560  {
561  load_domaintype_info(typentry);
562  }
563 
564  return typentry;
565 }
static bool array_element_has_hashing(TypeCacheEntry *typentry)
Definition: typcache.c:1102
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
static void load_typcache_tupdesc(TypeCacheEntry *typentry)
Definition: typcache.c:571
#define BTORDER_PROC
Definition: nbtree.h:229
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:121
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1391
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid hash_opintype
Definition: typcache.h:53
#define TCFLAGS_CHECKED_EQ_OPR
Definition: typcache.c:80
#define HASH_ELEM
Definition: hsearch.h:87
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:75
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
struct TypeCacheEntry TypeCacheEntry
#define HTEqualStrategyNumber
Definition: hash.h:288
#define TYPECACHE_EQ_OPR_FINFO
Definition: typcache.h:115
#define BTREE_AM_OID
Definition: pg_am.h:70
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:117
Size entrysize
Definition: hsearch.h:73
#define TYPECACHE_EQ_OPR
Definition: typcache.h:110
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:858
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define RECORD_EQ_OP
Definition: pg_operator.h:1720
int16 typlen
Definition: typcache.h:35
#define OidIsValid(objectId)
Definition: c.h:538
bool typbyval
Definition: typcache.h:36
#define HASH_AM_OID
Definition: pg_am.h:73
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1431
FmgrInfo cmp_proc_finfo
Definition: typcache.h:68
struct TypeCacheEntry * nextDomain
Definition: typcache.h:106
#define TCFLAGS_CHECKED_GT_OPR
Definition: typcache.c:82
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ARRAY_LT_OP
Definition: pg_operator.h:781
char typstorage
Definition: typcache.h:38
static void TypeCacheRelCallback(Datum arg, Oid relid)
Definition: typcache.c:1422
static bool array_element_has_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1094
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
FmgrInfo hash_proc_finfo
Definition: typcache.h:69
#define RECORD_LT_OP
Definition: pg_operator.h:1725
#define TYPECACHE_GT_OPR
Definition: typcache.h:112
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define ereport(elevel, rest)
Definition: elog.h:122
#define TYPECACHE_BTREE_OPFAMILY
Definition: typcache.h:119
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:84
#define RECORD_GT_OP
Definition: pg_operator.h:1728
#define TYPTYPE_RANGE
Definition: pg_type.h:725
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Oid btree_opintype
Definition: typcache.h:51
Size keysize
Definition: hsearch.h:72
FmgrInfo eq_opr_finfo
Definition: typcache.h:67
#define InvalidOid
Definition: postgres_ext.h:36
static void load_rangetype_info(TypeCacheEntry *typentry)
Definition: typcache.c:599
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
Oid fn_oid
Definition: fmgr.h:59
#define TYPECACHE_CMP_PROC
Definition: typcache.h:113
char typtype
Definition: typcache.h:39
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
#define ARRAY_GT_OP
Definition: pg_operator.h:784
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
#define TCFLAGS_CHECKED_BTREE_OPCLASS
Definition: typcache.c:78
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:92
static bool record_fields_have_compare(TypeCacheEntry *typentry)
Definition: typcache.c:1141
#define ARRAY_EQ_OP
Definition: pg_operator.h:776
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1047
static bool array_element_has_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1086
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:662
#define TCFLAGS_CHECKED_HASH_PROC
Definition: typcache.c:84
char typalign
Definition: typcache.h:37
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HASHPROC
Definition: hash.h:296
#define TYPECACHE_LT_OPR
Definition: typcache.h:111
#define TCFLAGS_CHECKED_LT_OPR
Definition: typcache.c:81
#define NameStr(name)
Definition: c.h:499
#define TYPECACHE_CMP_PROC_FINFO
Definition: typcache.h:116
#define TCFLAGS_CHECKED_HASH_OPCLASS
Definition: typcache.c:79
#define TYPECACHE_HASH_OPFAMILY
Definition: typcache.h:120
#define TYPECACHE_DOMAIN_INFO
Definition: typcache.h:122
static bool record_fields_have_equality(TypeCacheEntry *typentry)
Definition: typcache.c:1133
#define TCFLAGS_CHECKED_CMP_PROC
Definition: typcache.c:83
#define BTLessStrategyNumber
Definition: stratnum.h:29
TupleDesc tupDesc
Definition: typcache.h:76
static void TypeCacheConstrCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:1503
static HTAB * TypeCacheHash
Definition: typcache.c:72
#define TYPECACHE_HASH_PROC
Definition: typcache.h:114
#define TYPECACHE_TUPDESC
Definition: typcache.h:118
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: typcache.c:1474
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1069
static List * prep_domain_constraints ( List constraints,
MemoryContext  execctx 
)
static

Definition at line 934 of file typcache.c.

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

Referenced by InitDomainConstraintRef(), and UpdateDomainConstraintRef().

935 {
936  List *result = NIL;
937  MemoryContext oldcxt;
938  ListCell *lc;
939 
940  oldcxt = MemoryContextSwitchTo(execctx);
941 
942  foreach(lc, constraints)
943  {
945  DomainConstraintState *newr;
946 
948  newr->constrainttype = r->constrainttype;
949  newr->name = r->name;
950  newr->check_expr = r->check_expr;
952 
953  result = lappend(result, newr);
954  }
955 
956  MemoryContextSwitchTo(oldcxt);
957 
958  return result;
959 }
#define NIL
Definition: pg_list.h:69
DomainConstraintType constrainttype
Definition: execnodes.h:809
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1633
ExprState * check_exprstate
Definition: execnodes.h:812
List * lappend(List *list, void *datum)
Definition: list.c:128
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:113
Definition: pg_list.h:45
static bool record_fields_have_compare ( TypeCacheEntry typentry)
static

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

1142 {
1143  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1145  return (typentry->flags & TCFLAGS_HAVE_FIELD_COMPARE) != 0;
1146 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:89
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1149
#define TCFLAGS_HAVE_FIELD_COMPARE
Definition: typcache.c:91
static bool record_fields_have_equality ( TypeCacheEntry typentry)
static

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

1134 {
1135  if (!(typentry->flags & TCFLAGS_CHECKED_FIELD_PROPERTIES))
1137  return (typentry->flags & TCFLAGS_HAVE_FIELD_EQUALITY) != 0;
1138 }
#define TCFLAGS_CHECKED_FIELD_PROPERTIES
Definition: typcache.c:89
static void cache_record_field_properties(TypeCacheEntry *typentry)
Definition: typcache.c:1149
#define TCFLAGS_HAVE_FIELD_EQUALITY
Definition: typcache.c:90
static void TypeCacheConstrCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 1503 of file typcache.c.

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

Referenced by lookup_type_cache().

1504 {
1505  TypeCacheEntry *typentry;
1506 
1507  /*
1508  * Because this is called very frequently, and typically very few of the
1509  * typcache entries are for domains, we don't use hash_seq_search here.
1510  * Instead we thread all the domain-type entries together so that we can
1511  * visit them cheaply.
1512  */
1513  for (typentry = firstDomainTypeEntry;
1514  typentry != NULL;
1515  typentry = typentry->nextDomain)
1516  {
1517  /* Reset domain constraint validity information */
1519  }
1520 }
static TypeCacheEntry * firstDomainTypeEntry
Definition: typcache.c:75
struct TypeCacheEntry * nextDomain
Definition: typcache.h:106
#define NULL
Definition: c.h:229
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:92
static void TypeCacheOpcCallback ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 1474 of file typcache.c.

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

Referenced by lookup_type_cache().

1475 {
1477  TypeCacheEntry *typentry;
1478 
1479  /* TypeCacheHash must exist, else this callback wouldn't be registered */
1480  hash_seq_init(&status, TypeCacheHash);
1481  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
1482  {
1483  /* Reset equality/comparison/hashing validity information */
1484  typentry->flags = 0;
1485  }
1486 }
#define NULL
Definition: c.h:229
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static HTAB * TypeCacheHash
Definition: typcache.c:72
static void TypeCacheRelCallback ( Datum  arg,
Oid  relid 
)
static

Definition at line 1422 of file typcache.c.

References Assert, TypeCacheEntry::flags, FreeTupleDesc(), hash_seq_init(), hash_seq_search(), InvalidOid, NULL, status(), tupleDesc::tdrefcount, TypeCacheEntry::tupDesc, TypeCacheEntry::typrelid, TypeCacheEntry::typtype, and TYPTYPE_COMPOSITE.

Referenced by lookup_type_cache().

1423 {
1425  TypeCacheEntry *typentry;
1426 
1427  /* TypeCacheHash must exist, else this callback wouldn't be registered */
1428  hash_seq_init(&status, TypeCacheHash);
1429  while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL)
1430  {
1431  if (typentry->typtype != TYPTYPE_COMPOSITE)
1432  continue; /* skip non-composites */
1433 
1434  /* Skip if no match, unless we're zapping all composite types */
1435  if (relid != typentry->typrelid && relid != InvalidOid)
1436  continue;
1437 
1438  /* Delete tupdesc if we have it */
1439  if (typentry->tupDesc != NULL)
1440  {
1441  /*
1442  * Release our refcount, and free the tupdesc if none remain.
1443  * (Can't use DecrTupleDescRefCount because this reference is not
1444  * logged in current resource owner.)
1445  */
1446  Assert(typentry->tupDesc->tdrefcount > 0);
1447  if (--typentry->tupDesc->tdrefcount == 0)
1448  FreeTupleDesc(typentry->tupDesc);
1449  typentry->tupDesc = NULL;
1450  }
1451 
1452  /* Reset equality/comparison/hashing validity information */
1453  typentry->flags = 0;
1454  }
1455 }
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define InvalidOid
Definition: postgres_ext.h:36
char typtype
Definition: typcache.h:39
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:233
int tdrefcount
Definition: tupdesc.h:77
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
TupleDesc tupDesc
Definition: typcache.h:76
static HTAB * TypeCacheHash
Definition: typcache.c:72
void UpdateDomainConstraintRef ( DomainConstraintRef ref)

Definition at line 1010 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, NULL, prep_domain_constraints(), DomainConstraintRef::refctx, DomainConstraintRef::tcache, TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS, TypeCacheEntry::typtype, and TYPTYPE_DOMAIN.

Referenced by domain_check_input().

1011 {
1012  TypeCacheEntry *typentry = ref->tcache;
1013 
1014  /* Make sure typcache entry's data is up to date */
1015  if ((typentry->flags & TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS) == 0 &&
1016  typentry->typtype == TYPTYPE_DOMAIN)
1017  load_domaintype_info(typentry);
1018 
1019  /* Transfer to ref object if there's new info, adjusting refcounts */
1020  if (ref->dcc != typentry->domainData)
1021  {
1022  /* Paranoia --- be sure link is nulled before trying to release */
1023  DomainConstraintCache *dcc = ref->dcc;
1024 
1025  if (dcc)
1026  {
1027  /*
1028  * Note: we just leak the previous list of executable domain
1029  * constraints. Alternatively, we could keep those in a child
1030  * context of ref->refctx and free that context at this point.
1031  * However, in practice this code path will be taken so seldom
1032  * that the extra bookkeeping for a child context doesn't seem
1033  * worthwhile; we'll just allow a leak for the lifespan of refctx.
1034  */
1035  ref->constraints = NIL;
1036  ref->dcc = NULL;
1037  decr_dcc_refcount(dcc);
1038  }
1039  dcc = typentry->domainData;
1040  if (dcc)
1041  {
1042  ref->dcc = dcc;
1043  dcc->dccRefCount++;
1044  if (ref->need_exprstate)
1046  ref->refctx);
1047  else
1048  ref->constraints = dcc->constraints;
1049  }
1050  }
1051 }
#define NIL
Definition: pg_list.h:69
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
DomainConstraintCache * dcc
Definition: typcache.h:138
DomainConstraintCache * domainData
Definition: typcache.h:94
MemoryContext refctx
Definition: typcache.h:133
char typtype
Definition: typcache.h:39
#define NULL
Definition: c.h:229
static List * prep_domain_constraints(List *constraints, MemoryContext execctx)
Definition: typcache.c:934
TypeCacheEntry * tcache
Definition: typcache.h:134
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS
Definition: typcache.c:92
static void load_domaintype_info(TypeCacheEntry *typentry)
Definition: typcache.c:662
static void decr_dcc_refcount(DomainConstraintCache *dcc)
Definition: typcache.c:902

Variable Documentation

TypeCacheEntry* firstDomainTypeEntry = NULL
static

Definition at line 75 of file typcache.c.

Referenced by lookup_type_cache().

int32 NextRecordTypmod = 0
static

Definition at line 155 of file typcache.c.

Referenced by assign_record_type_typmod(), and lookup_rowtype_tupdesc_internal().

TupleDesc* RecordCacheArray = NULL
static

Definition at line 153 of file typcache.c.

int32 RecordCacheArrayLen = 0
static

Definition at line 154 of file typcache.c.

Referenced by assign_record_type_typmod().

HTAB* RecordCacheHash = NULL
static

Definition at line 151 of file typcache.c.

HTAB* TypeCacheHash = NULL
static

Definition at line 72 of file typcache.c.