PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
typcache.h File Reference
#include "access/tupdesc.h"
#include "fmgr.h"
Include dependency graph for typcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TypeCacheEntry
 
struct  DomainConstraintRef
 

Macros

#define TYPECACHE_EQ_OPR   0x0001
 
#define TYPECACHE_LT_OPR   0x0002
 
#define TYPECACHE_GT_OPR   0x0004
 
#define TYPECACHE_CMP_PROC   0x0008
 
#define TYPECACHE_HASH_PROC   0x0010
 
#define TYPECACHE_EQ_OPR_FINFO   0x0020
 
#define TYPECACHE_CMP_PROC_FINFO   0x0040
 
#define TYPECACHE_HASH_PROC_FINFO   0x0080
 
#define TYPECACHE_TUPDESC   0x0100
 
#define TYPECACHE_BTREE_OPFAMILY   0x0200
 
#define TYPECACHE_HASH_OPFAMILY   0x0400
 
#define TYPECACHE_RANGE_INFO   0x0800
 
#define TYPECACHE_DOMAIN_INFO   0x1000
 

Typedefs

typedef struct
DomainConstraintCache 
DomainConstraintCache
 
typedef struct TypeCacheEntry TypeCacheEntry
 
typedef struct DomainConstraintRef DomainConstraintRef
 

Functions

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)
 
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)
 
int compare_values_of_enum (TypeCacheEntry *tcache, Oid arg1, Oid arg2)
 

Macro Definition Documentation

#define TYPECACHE_BTREE_OPFAMILY   0x0200

Definition at line 119 of file typcache.h.

Referenced by lookup_type_cache().

#define TYPECACHE_CMP_PROC   0x0008
#define TYPECACHE_CMP_PROC_FINFO   0x0040
#define TYPECACHE_DOMAIN_INFO   0x1000

Definition at line 122 of file typcache.h.

Referenced by DomainHasConstraints(), InitDomainConstraintRef(), and lookup_type_cache().

#define TYPECACHE_EQ_OPR_FINFO   0x0020
#define TYPECACHE_GT_OPR   0x0004
#define TYPECACHE_HASH_OPFAMILY   0x0400

Definition at line 120 of file typcache.h.

Referenced by lookup_type_cache().

#define TYPECACHE_HASH_PROC   0x0010
#define TYPECACHE_HASH_PROC_FINFO   0x0080

Definition at line 117 of file typcache.h.

Referenced by array_typanalyze(), hash_array(), hash_range(), and lookup_type_cache().

#define TYPECACHE_RANGE_INFO   0x0800
#define TYPECACHE_TUPDESC   0x0100

Definition at line 118 of file typcache.h.

Referenced by lookup_rowtype_tupdesc_internal(), and lookup_type_cache().

Typedef Documentation

Definition at line 24 of file typcache.h.

Function Documentation

void assign_record_type_typmod ( TupleDesc  tupDesc)

Definition at line 1308 of file typcache.c.

References Assert, tupleDesc::attrs, 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, and RecordCacheEntry::tupdescs.

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

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

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

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

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

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

Definition at line 1274 of file typcache.c.

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

Referenced by plperl_sv_to_datum().

1275 {
1276  TupleDesc tupDesc;
1277 
1278  tupDesc = lookup_rowtype_tupdesc_internal(type_id, typmod, noError);
1279  if (tupDesc != NULL)
1280  IncrTupleDescRefCount(tupDesc);
1281  return tupDesc;
1282 }
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:318
#define NULL
Definition: c.h:229
static TupleDesc lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1210
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(), 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:1378
#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:289
#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:857
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
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:152
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1406
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:1421
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:1382
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
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:675
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:525
#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:297
#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:1502
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:1473
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1069
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