PostgreSQL Source Code  git master
syscache.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * syscache.c
4  * System cache management routines
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/cache/syscache.c
12  *
13  * NOTES
14  * These routines allow the parser/planner/executor to perform
15  * rapid lookups on the contents of the system catalogs.
16  *
17  * see utils/syscache.h for a list of the cache IDs
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22 
23 #include "access/htup_details.h"
24 #include "catalog/pg_db_role_setting_d.h"
25 #include "catalog/pg_depend_d.h"
26 #include "catalog/pg_description_d.h"
27 #include "catalog/pg_seclabel_d.h"
28 #include "catalog/pg_shdepend_d.h"
29 #include "catalog/pg_shdescription_d.h"
30 #include "catalog/pg_shseclabel_d.h"
31 #include "common/int.h"
32 #include "lib/qunique.h"
33 #include "miscadmin.h"
34 #include "storage/lmgr.h"
35 #include "utils/catcache.h"
36 #include "utils/inval.h"
37 #include "utils/lsyscache.h"
38 #include "utils/rel.h"
39 #include "utils/syscache.h"
40 
41 /*---------------------------------------------------------------------------
42 
43  Adding system caches:
44 
45  There must be a unique index underlying each syscache (ie, an index
46  whose key is the same as that of the cache). If there is not one
47  already, add the definition for it to include/catalog/pg_*.h using
48  DECLARE_UNIQUE_INDEX.
49  (Adding an index requires a catversion.h update, while simply
50  adding/deleting caches only requires a recompile.)
51 
52  Add a MAKE_SYSCACHE call to the same pg_*.h file specifying the name of
53  your cache, the underlying index, and the initial number of hash buckets.
54 
55  The number of hash buckets must be a power of 2. It's reasonable to
56  set this to the number of entries that might be in the particular cache
57  in a medium-size database.
58 
59  Finally, any place your relation gets heap_insert() or
60  heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
61  instead, which also update indexes. The heap_* calls do not do that.
62 
63 *---------------------------------------------------------------------------
64 */
65 
66 /*
67  * struct cachedesc: information defining a single syscache
68  */
69 struct cachedesc
70 {
71  Oid reloid; /* OID of the relation being cached */
72  Oid indoid; /* OID of index relation for this cache */
73  int nkeys; /* # of keys needed for cache lookup */
74  int key[4]; /* attribute numbers of key attrs */
75  int nbuckets; /* number of hash buckets for this cache */
76 };
77 
78 /* Macro to provide nkeys and key array with convenient syntax. */
79 #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
80 
81 #include "catalog/syscache_info.h"
82 
83 StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
84  "SysCacheSize does not match syscache.c's array");
85 
86 static CatCache *SysCache[SysCacheSize];
87 
88 static bool CacheInitialized = false;
89 
90 /* Sorted array of OIDs of tables that have caches on them */
91 static Oid SysCacheRelationOid[SysCacheSize];
93 
94 /* Sorted array of OIDs of tables and indexes used by caches */
95 static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
97 
98 static int oid_compare(const void *a, const void *b);
99 
100 
101 /*
102  * InitCatalogCache - initialize the caches
103  *
104  * Note that no database access is done here; we only allocate memory
105  * and initialize the cache structure. Interrogation of the database
106  * to complete initialization of a cache happens upon first use
107  * of that cache.
108  */
109 void
111 {
112  int cacheId;
113 
115 
117 
118  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
119  {
120  /*
121  * Assert that every enumeration value defined in syscache.h has been
122  * populated in the cacheinfo array.
123  */
124  Assert(OidIsValid(cacheinfo[cacheId].reloid));
125  Assert(OidIsValid(cacheinfo[cacheId].indoid));
126  /* .nbuckets and .key[] are checked by InitCatCache() */
127 
128  SysCache[cacheId] = InitCatCache(cacheId,
129  cacheinfo[cacheId].reloid,
130  cacheinfo[cacheId].indoid,
131  cacheinfo[cacheId].nkeys,
132  cacheinfo[cacheId].key,
133  cacheinfo[cacheId].nbuckets);
134  if (!PointerIsValid(SysCache[cacheId]))
135  elog(ERROR, "could not initialize cache %u (%d)",
136  cacheinfo[cacheId].reloid, cacheId);
137  /* Accumulate data for OID lists, too */
139  cacheinfo[cacheId].reloid;
141  cacheinfo[cacheId].reloid;
143  cacheinfo[cacheId].indoid;
144  /* see comments for RelationInvalidatesSnapshotsOnly */
145  Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
146  }
147 
150 
151  /* Sort and de-dup OID arrays, so we can use binary search. */
153  sizeof(Oid), oid_compare);
156  oid_compare);
157 
159  sizeof(Oid), oid_compare);
162  sizeof(Oid), oid_compare);
163 
164  CacheInitialized = true;
165 }
166 
167 /*
168  * InitCatalogCachePhase2 - finish initializing the caches
169  *
170  * Finish initializing all the caches, including necessary database
171  * access.
172  *
173  * This is *not* essential; normally we allow syscaches to be initialized
174  * on first use. However, it is useful as a mechanism to preload the
175  * relcache with entries for the most-commonly-used system catalogs.
176  * Therefore, we invoke this routine when we need to write a new relcache
177  * init file.
178  */
179 void
181 {
182  int cacheId;
183 
185 
186  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
187  InitCatCachePhase2(SysCache[cacheId], true);
188 }
189 
190 
191 /*
192  * SearchSysCache
193  *
194  * A layer on top of SearchCatCache that does the initialization and
195  * key-setting for you.
196  *
197  * Returns the cache copy of the tuple if one is found, NULL if not.
198  * The tuple is the 'cache' copy and must NOT be modified!
199  *
200  * When the caller is done using the tuple, call ReleaseSysCache()
201  * to release the reference count grabbed by SearchSysCache(). If this
202  * is not done, the tuple will remain locked in cache until end of
203  * transaction, which is tolerable but not desirable.
204  *
205  * CAUTION: The tuple that is returned must NOT be freed by the caller!
206  */
207 HeapTuple
208 SearchSysCache(int cacheId,
209  Datum key1,
210  Datum key2,
211  Datum key3,
212  Datum key4)
213 {
214  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
215  PointerIsValid(SysCache[cacheId]));
216 
217  return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
218 }
219 
220 HeapTuple
221 SearchSysCache1(int cacheId,
222  Datum key1)
223 {
224  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
225  PointerIsValid(SysCache[cacheId]));
226  Assert(SysCache[cacheId]->cc_nkeys == 1);
227 
228  return SearchCatCache1(SysCache[cacheId], key1);
229 }
230 
231 HeapTuple
232 SearchSysCache2(int cacheId,
233  Datum key1, Datum key2)
234 {
235  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
236  PointerIsValid(SysCache[cacheId]));
237  Assert(SysCache[cacheId]->cc_nkeys == 2);
238 
239  return SearchCatCache2(SysCache[cacheId], key1, key2);
240 }
241 
242 HeapTuple
243 SearchSysCache3(int cacheId,
244  Datum key1, Datum key2, Datum key3)
245 {
246  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
247  PointerIsValid(SysCache[cacheId]));
248  Assert(SysCache[cacheId]->cc_nkeys == 3);
249 
250  return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
251 }
252 
253 HeapTuple
254 SearchSysCache4(int cacheId,
255  Datum key1, Datum key2, Datum key3, Datum key4)
256 {
257  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
258  PointerIsValid(SysCache[cacheId]));
259  Assert(SysCache[cacheId]->cc_nkeys == 4);
260 
261  return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
262 }
263 
264 /*
265  * ReleaseSysCache
266  * Release previously grabbed reference count on a tuple
267  */
268 void
270 {
271  ReleaseCatCache(tuple);
272 }
273 
274 /*
275  * SearchSysCacheLocked1
276  *
277  * Combine SearchSysCache1() with acquiring a LOCKTAG_TUPLE at mode
278  * InplaceUpdateTupleLock. This is a tool for complying with the
279  * README.tuplock section "Locking to write inplace-updated tables". After
280  * the caller's heap_update(), it should UnlockTuple(InplaceUpdateTupleLock)
281  * and ReleaseSysCache().
282  *
283  * The returned tuple may be the subject of an uncommitted update, so this
284  * doesn't prevent the "tuple concurrently updated" error.
285  */
286 HeapTuple
288  Datum key1)
289 {
290  ItemPointerData tid;
291  LOCKTAG tag;
292  Oid dboid =
294  Oid reloid = cacheinfo[cacheId].reloid;
295 
296  /*----------
297  * Since inplace updates may happen just before our LockTuple(), we must
298  * return content acquired after LockTuple() of the TID we return. If we
299  * just fetched twice instead of looping, the following sequence would
300  * defeat our locking:
301  *
302  * GRANT: SearchSysCache1() = TID (1,5)
303  * GRANT: LockTuple(pg_class, (1,5))
304  * [no more inplace update of (1,5) until we release the lock]
305  * CLUSTER: SearchSysCache1() = TID (1,5)
306  * CLUSTER: heap_update() = TID (1,8)
307  * CLUSTER: COMMIT
308  * GRANT: SearchSysCache1() = TID (1,8)
309  * GRANT: return (1,8) from SearchSysCacheLocked1()
310  * VACUUM: SearchSysCache1() = TID (1,8)
311  * VACUUM: LockTuple(pg_class, (1,8)) # two TIDs now locked for one rel
312  * VACUUM: inplace update
313  * GRANT: heap_update() = (1,9) # lose inplace update
314  *
315  * In the happy case, this takes two fetches, one to determine the TID to
316  * lock and another to get the content and confirm the TID didn't change.
317  *
318  * This is valid even if the row gets updated to a new TID, the old TID
319  * becomes LP_UNUSED, and the row gets updated back to its old TID. We'd
320  * still hold the right LOCKTAG_TUPLE and a copy of the row captured after
321  * the LOCKTAG_TUPLE.
322  */
323  ItemPointerSetInvalid(&tid);
324  for (;;)
325  {
326  HeapTuple tuple;
327  LOCKMODE lockmode = InplaceUpdateTupleLock;
328 
329  tuple = SearchSysCache1(cacheId, key1);
330  if (ItemPointerIsValid(&tid))
331  {
332  if (!HeapTupleIsValid(tuple))
333  {
334  LockRelease(&tag, lockmode, false);
335  return tuple;
336  }
337  if (ItemPointerEquals(&tid, &tuple->t_self))
338  return tuple;
339  LockRelease(&tag, lockmode, false);
340  }
341  else if (!HeapTupleIsValid(tuple))
342  return tuple;
343 
344  tid = tuple->t_self;
345  ReleaseSysCache(tuple);
346  /* like: LockTuple(rel, &tid, lockmode) */
347  SET_LOCKTAG_TUPLE(tag, dboid, reloid,
350  (void) LockAcquire(&tag, lockmode, false, false);
351 
352  /*
353  * If an inplace update just finished, ensure we process the syscache
354  * inval. XXX this is insufficient: the inplace updater may not yet
355  * have reached AtEOXact_Inval(). See test at inplace-inval.spec.
356  *
357  * If a heap_update() call just released its LOCKTAG_TUPLE, we'll
358  * probably find the old tuple and reach "tuple concurrently updated".
359  * If that heap_update() aborts, our LOCKTAG_TUPLE blocks inplace
360  * updates while our caller works.
361  */
363  }
364 }
365 
366 /*
367  * SearchSysCacheCopy
368  *
369  * A convenience routine that does SearchSysCache and (if successful)
370  * returns a modifiable copy of the syscache entry. The original
371  * syscache entry is released before returning. The caller should
372  * heap_freetuple() the result when done with it.
373  */
374 HeapTuple
375 SearchSysCacheCopy(int cacheId,
376  Datum key1,
377  Datum key2,
378  Datum key3,
379  Datum key4)
380 {
381  HeapTuple tuple,
382  newtuple;
383 
384  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
385  if (!HeapTupleIsValid(tuple))
386  return tuple;
387  newtuple = heap_copytuple(tuple);
388  ReleaseSysCache(tuple);
389  return newtuple;
390 }
391 
392 /*
393  * SearchSysCacheLockedCopy1
394  *
395  * Meld SearchSysCacheLockedCopy1 with SearchSysCacheCopy(). After the
396  * caller's heap_update(), it should UnlockTuple(InplaceUpdateTupleLock) and
397  * heap_freetuple().
398  */
399 HeapTuple
401  Datum key1)
402 {
403  HeapTuple tuple,
404  newtuple;
405 
406  tuple = SearchSysCacheLocked1(cacheId, key1);
407  if (!HeapTupleIsValid(tuple))
408  return tuple;
409  newtuple = heap_copytuple(tuple);
410  ReleaseSysCache(tuple);
411  return newtuple;
412 }
413 
414 /*
415  * SearchSysCacheExists
416  *
417  * A convenience routine that just probes to see if a tuple can be found.
418  * No lock is retained on the syscache entry.
419  */
420 bool
422  Datum key1,
423  Datum key2,
424  Datum key3,
425  Datum key4)
426 {
427  HeapTuple tuple;
428 
429  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
430  if (!HeapTupleIsValid(tuple))
431  return false;
432  ReleaseSysCache(tuple);
433  return true;
434 }
435 
436 /*
437  * GetSysCacheOid
438  *
439  * A convenience routine that does SearchSysCache and returns the OID in the
440  * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
441  * No lock is retained on the syscache entry.
442  */
443 Oid
444 GetSysCacheOid(int cacheId,
445  AttrNumber oidcol,
446  Datum key1,
447  Datum key2,
448  Datum key3,
449  Datum key4)
450 {
451  HeapTuple tuple;
452  bool isNull;
453  Oid result;
454 
455  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
456  if (!HeapTupleIsValid(tuple))
457  return InvalidOid;
458  result = heap_getattr(tuple, oidcol,
459  SysCache[cacheId]->cc_tupdesc,
460  &isNull);
461  Assert(!isNull); /* columns used as oids should never be NULL */
462  ReleaseSysCache(tuple);
463  return result;
464 }
465 
466 
467 /*
468  * SearchSysCacheAttName
469  *
470  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
471  * except that it will return NULL if the found attribute is marked
472  * attisdropped. This is convenient for callers that want to act as
473  * though dropped attributes don't exist.
474  */
475 HeapTuple
476 SearchSysCacheAttName(Oid relid, const char *attname)
477 {
478  HeapTuple tuple;
479 
480  tuple = SearchSysCache2(ATTNAME,
481  ObjectIdGetDatum(relid),
483  if (!HeapTupleIsValid(tuple))
484  return NULL;
485  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
486  {
487  ReleaseSysCache(tuple);
488  return NULL;
489  }
490  return tuple;
491 }
492 
493 /*
494  * SearchSysCacheCopyAttName
495  *
496  * As above, an attisdropped-aware version of SearchSysCacheCopy.
497  */
498 HeapTuple
500 {
501  HeapTuple tuple,
502  newtuple;
503 
504  tuple = SearchSysCacheAttName(relid, attname);
505  if (!HeapTupleIsValid(tuple))
506  return tuple;
507  newtuple = heap_copytuple(tuple);
508  ReleaseSysCache(tuple);
509  return newtuple;
510 }
511 
512 /*
513  * SearchSysCacheExistsAttName
514  *
515  * As above, an attisdropped-aware version of SearchSysCacheExists.
516  */
517 bool
519 {
520  HeapTuple tuple;
521 
522  tuple = SearchSysCacheAttName(relid, attname);
523  if (!HeapTupleIsValid(tuple))
524  return false;
525  ReleaseSysCache(tuple);
526  return true;
527 }
528 
529 
530 /*
531  * SearchSysCacheAttNum
532  *
533  * This routine is equivalent to SearchSysCache on the ATTNUM cache,
534  * except that it will return NULL if the found attribute is marked
535  * attisdropped. This is convenient for callers that want to act as
536  * though dropped attributes don't exist.
537  */
538 HeapTuple
540 {
541  HeapTuple tuple;
542 
543  tuple = SearchSysCache2(ATTNUM,
544  ObjectIdGetDatum(relid),
546  if (!HeapTupleIsValid(tuple))
547  return NULL;
548  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
549  {
550  ReleaseSysCache(tuple);
551  return NULL;
552  }
553  return tuple;
554 }
555 
556 /*
557  * SearchSysCacheCopyAttNum
558  *
559  * As above, an attisdropped-aware version of SearchSysCacheCopy.
560  */
561 HeapTuple
563 {
564  HeapTuple tuple,
565  newtuple;
566 
567  tuple = SearchSysCacheAttNum(relid, attnum);
568  if (!HeapTupleIsValid(tuple))
569  return NULL;
570  newtuple = heap_copytuple(tuple);
571  ReleaseSysCache(tuple);
572  return newtuple;
573 }
574 
575 
576 /*
577  * SysCacheGetAttr
578  *
579  * Given a tuple previously fetched by SearchSysCache(),
580  * extract a specific attribute.
581  *
582  * This is equivalent to using heap_getattr() on a tuple fetched
583  * from a non-cached relation. Usually, this is only used for attributes
584  * that could be NULL or variable length; the fixed-size attributes in
585  * a system table are accessed just by mapping the tuple onto the C struct
586  * declarations from include/catalog/.
587  *
588  * As with heap_getattr(), if the attribute is of a pass-by-reference type
589  * then a pointer into the tuple data area is returned --- the caller must
590  * not modify or pfree the datum!
591  *
592  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
593  * a different cache for the same catalog the tuple was fetched from.
594  */
595 Datum
596 SysCacheGetAttr(int cacheId, HeapTuple tup,
597  AttrNumber attributeNumber,
598  bool *isNull)
599 {
600  /*
601  * We just need to get the TupleDesc out of the cache entry, and then we
602  * can apply heap_getattr(). Normally the cache control data is already
603  * valid (because the caller recently fetched the tuple via this same
604  * cache), but there are cases where we have to initialize the cache here.
605  */
606  if (cacheId < 0 || cacheId >= SysCacheSize ||
607  !PointerIsValid(SysCache[cacheId]))
608  elog(ERROR, "invalid cache ID: %d", cacheId);
609  if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
610  {
611  InitCatCachePhase2(SysCache[cacheId], false);
612  Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
613  }
614 
615  return heap_getattr(tup, attributeNumber,
616  SysCache[cacheId]->cc_tupdesc,
617  isNull);
618 }
619 
620 /*
621  * SysCacheGetAttrNotNull
622  *
623  * As above, a version of SysCacheGetAttr which knows that the attr cannot
624  * be NULL.
625  */
626 Datum
628  AttrNumber attributeNumber)
629 {
630  bool isnull;
631  Datum attr;
632 
633  attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
634 
635  if (isnull)
636  {
637  elog(ERROR,
638  "unexpected null value in cached tuple for catalog %s column %s",
639  get_rel_name(cacheinfo[cacheId].reloid),
640  NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
641  }
642 
643  return attr;
644 }
645 
646 /*
647  * GetSysCacheHashValue
648  *
649  * Get the hash value that would be used for a tuple in the specified cache
650  * with the given search keys.
651  *
652  * The reason for exposing this as part of the API is that the hash value is
653  * exposed in cache invalidation operations, so there are places outside the
654  * catcache code that need to be able to compute the hash values.
655  */
656 uint32
658  Datum key1,
659  Datum key2,
660  Datum key3,
661  Datum key4)
662 {
663  if (cacheId < 0 || cacheId >= SysCacheSize ||
664  !PointerIsValid(SysCache[cacheId]))
665  elog(ERROR, "invalid cache ID: %d", cacheId);
666 
667  return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
668 }
669 
670 /*
671  * List-search interface
672  */
673 struct catclist *
674 SearchSysCacheList(int cacheId, int nkeys,
675  Datum key1, Datum key2, Datum key3)
676 {
677  if (cacheId < 0 || cacheId >= SysCacheSize ||
678  !PointerIsValid(SysCache[cacheId]))
679  elog(ERROR, "invalid cache ID: %d", cacheId);
680 
681  return SearchCatCacheList(SysCache[cacheId], nkeys,
682  key1, key2, key3);
683 }
684 
685 /*
686  * SysCacheInvalidate
687  *
688  * Invalidate entries in the specified cache, given a hash value.
689  * See CatCacheInvalidate() for more info.
690  *
691  * This routine is only quasi-public: it should only be used by inval.c.
692  */
693 void
694 SysCacheInvalidate(int cacheId, uint32 hashValue)
695 {
696  if (cacheId < 0 || cacheId >= SysCacheSize)
697  elog(ERROR, "invalid cache ID: %d", cacheId);
698 
699  /* if this cache isn't initialized yet, no need to do anything */
700  if (!PointerIsValid(SysCache[cacheId]))
701  return;
702 
703  CatCacheInvalidate(SysCache[cacheId], hashValue);
704 }
705 
706 /*
707  * Certain relations that do not have system caches send snapshot invalidation
708  * messages in lieu of catcache messages. This is for the benefit of
709  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
710  * for scanning one of those catalogs, rather than taking a new one, if no
711  * invalidation has been received.
712  *
713  * Relations that have syscaches need not (and must not) be listed here. The
714  * catcache invalidation messages will also flush the snapshot. If you add a
715  * syscache for one of these relations, remove it from this list.
716  */
717 bool
719 {
720  switch (relid)
721  {
722  case DbRoleSettingRelationId:
723  case DependRelationId:
724  case SharedDependRelationId:
725  case DescriptionRelationId:
726  case SharedDescriptionRelationId:
727  case SecLabelRelationId:
728  case SharedSecLabelRelationId:
729  return true;
730  default:
731  break;
732  }
733 
734  return false;
735 }
736 
737 /*
738  * Test whether a relation has a system cache.
739  */
740 bool
742 {
743  int low = 0,
744  high = SysCacheRelationOidSize - 1;
745 
746  while (low <= high)
747  {
748  int middle = low + (high - low) / 2;
749 
750  if (SysCacheRelationOid[middle] == relid)
751  return true;
752  if (SysCacheRelationOid[middle] < relid)
753  low = middle + 1;
754  else
755  high = middle - 1;
756  }
757 
758  return false;
759 }
760 
761 /*
762  * Test whether a relation supports a system cache, ie it is either a
763  * cached table or the index used for a cache.
764  */
765 bool
767 {
768  int low = 0,
769  high = SysCacheSupportingRelOidSize - 1;
770 
771  while (low <= high)
772  {
773  int middle = low + (high - low) / 2;
774 
775  if (SysCacheSupportingRelOid[middle] == relid)
776  return true;
777  if (SysCacheSupportingRelOid[middle] < relid)
778  low = middle + 1;
779  else
780  high = middle - 1;
781  }
782 
783  return false;
784 }
785 
786 
787 /*
788  * OID comparator for qsort
789  */
790 static int
791 oid_compare(const void *a, const void *b)
792 {
793  Oid oa = *((const Oid *) a);
794  Oid ob = *((const Oid *) b);
795 
796  return pg_cmp_u32(oa, ob);
797 }
int16 AttrNumber
Definition: attnum.h:21
#define NameStr(name)
Definition: c.h:737
unsigned int uint32
Definition: c.h:506
signed short int16
Definition: c.h:495
#define Assert(condition)
Definition: c.h:849
#define PointerIsValid(pointer)
Definition: c.h:754
#define lengthof(array)
Definition: c.h:779
#define OidIsValid(objectId)
Definition: c.h:766
HeapTuple SearchCatCache2(CatCache *cache, Datum v1, Datum v2)
Definition: catcache.c:1287
HeapTuple SearchCatCache3(CatCache *cache, Datum v1, Datum v2, Datum v3)
Definition: catcache.c:1295
void InitCatCachePhase2(CatCache *cache, bool touch_index)
Definition: catcache.c:1145
uint32 GetCatCacheHashValue(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1612
HeapTuple SearchCatCache4(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1303
CatCache * InitCatCache(int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
Definition: catcache.c:828
CatCList * SearchCatCacheList(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
Definition: catcache.c:1646
void CatCacheInvalidate(CatCache *cache, uint32 hashValue)
Definition: catcache.c:607
HeapTuple SearchCatCache1(CatCache *cache, Datum v1)
Definition: catcache.c:1279
void ReleaseCatCache(HeapTuple tuple)
Definition: catcache.c:1573
HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1262
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
Oid MyDatabaseId
Definition: globals.c:93
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:604
void AcceptInvalidationMessages(void)
Definition: inval.c:806
int b
Definition: isn.c:70
int a
Definition: isn.c:69
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:35
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition: itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition: itemptr.h:83
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition: lock.c:805
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:2013
#define SET_LOCKTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
Definition: lock.h:217
int LOCKMODE
Definition: lockdefs.h:26
#define InplaceUpdateTupleLock
Definition: lockdefs.h:48
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define qsort(a, b, c, d)
Definition: port.h:447
uintptr_t Datum
Definition: postgres.h:64
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21
ItemPointerData t_self
Definition: htup.h:65
Definition: lock.h:165
int key[4]
Definition: syscache.c:74
int nkeys
Definition: syscache.c:73
int nbuckets
Definition: syscache.c:75
Oid indoid
Definition: syscache.c:72
Oid reloid
Definition: syscache.c:71
bool cc_relisshared
Definition: catcache.h:62
short nkeys
Definition: catcache.h:177
HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname)
Definition: syscache.c:499
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:694
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:741
HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
Definition: syscache.c:562
void InitCatalogCache(void)
Definition: syscache.c:110
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
static bool CacheInitialized
Definition: syscache.c:88
HeapTuple SearchSysCacheLocked1(int cacheId, Datum key1)
Definition: syscache.c:287
HeapTuple SearchSysCacheLockedCopy1(int cacheId, Datum key1)
Definition: syscache.c:400
static int oid_compare(const void *a, const void *b)
Definition: syscache.c:791
HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:208
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
uint32 GetSysCacheHashValue(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:657
struct catclist * SearchSysCacheList(int cacheId, int nkeys, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:674
StaticAssertDecl(lengthof(cacheinfo)==SysCacheSize, "SysCacheSize does not match syscache.c's array")
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:243
static int SysCacheSupportingRelOidSize
Definition: syscache.c:96
HeapTuple SearchSysCacheAttNum(Oid relid, int16 attnum)
Definition: syscache.c:539
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:766
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:596
bool SearchSysCacheExistsAttName(Oid relid, const char *attname)
Definition: syscache.c:518
void InitCatalogCachePhase2(void)
Definition: syscache.c:180
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:232
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:476
bool SearchSysCacheExists(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:421
HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:375
static Oid SysCacheRelationOid[SysCacheSize]
Definition: syscache.c:91
static CatCache * SysCache[SysCacheSize]
Definition: syscache.c:86
static Oid SysCacheSupportingRelOid[SysCacheSize *2]
Definition: syscache.c:95
static int SysCacheRelationOidSize
Definition: syscache.c:92
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:718
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:254
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:627
Oid GetSysCacheOid(int cacheId, AttrNumber oidcol, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:444
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92