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-2025, 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 */
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
83StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
84 "SysCacheSize does not match syscache.c's array");
85
86static CatCache *SysCache[SysCacheSize];
87
88static bool CacheInitialized = false;
89
90/* Sorted array of OIDs of tables that have caches on them */
91static Oid SysCacheRelationOid[SysCacheSize];
93
94/* Sorted array of OIDs of tables and indexes used by caches */
95static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
97
98static 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 */
109void
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);
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 */
179void
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 */
208SearchSysCache(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
221SearchSysCache1(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
232SearchSysCache2(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
243SearchSysCache3(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
254SearchSysCache4(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 */
268void
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 */
288 Datum key1)
289{
290 CatCache *cache = SysCache[cacheId];
291 ItemPointerData tid;
292 LOCKTAG tag;
293
294 /*----------
295 * Since inplace updates may happen just before our LockTuple(), we must
296 * return content acquired after LockTuple() of the TID we return. If we
297 * just fetched twice instead of looping, the following sequence would
298 * defeat our locking:
299 *
300 * GRANT: SearchSysCache1() = TID (1,5)
301 * GRANT: LockTuple(pg_class, (1,5))
302 * [no more inplace update of (1,5) until we release the lock]
303 * CLUSTER: SearchSysCache1() = TID (1,5)
304 * CLUSTER: heap_update() = TID (1,8)
305 * CLUSTER: COMMIT
306 * GRANT: SearchSysCache1() = TID (1,8)
307 * GRANT: return (1,8) from SearchSysCacheLocked1()
308 * VACUUM: SearchSysCache1() = TID (1,8)
309 * VACUUM: LockTuple(pg_class, (1,8)) # two TIDs now locked for one rel
310 * VACUUM: inplace update
311 * GRANT: heap_update() = (1,9) # lose inplace update
312 *
313 * In the happy case, this takes two fetches, one to determine the TID to
314 * lock and another to get the content and confirm the TID didn't change.
315 *
316 * This is valid even if the row gets updated to a new TID, the old TID
317 * becomes LP_UNUSED, and the row gets updated back to its old TID. We'd
318 * still hold the right LOCKTAG_TUPLE and a copy of the row captured after
319 * the LOCKTAG_TUPLE.
320 */
322 for (;;)
323 {
324 HeapTuple tuple;
326
327 tuple = SearchSysCache1(cacheId, key1);
328 if (ItemPointerIsValid(&tid))
329 {
330 if (!HeapTupleIsValid(tuple))
331 {
332 LockRelease(&tag, lockmode, false);
333 return tuple;
334 }
335 if (ItemPointerEquals(&tid, &tuple->t_self))
336 return tuple;
337 LockRelease(&tag, lockmode, false);
338 }
339 else if (!HeapTupleIsValid(tuple))
340 return tuple;
341
342 tid = tuple->t_self;
343 ReleaseSysCache(tuple);
344
345 /*
346 * Do like LockTuple(rel, &tid, lockmode). While cc_relisshared won't
347 * change from one iteration to another, it may have been a temporary
348 * "false" until our first SearchSysCache1().
349 */
352 cache->cc_reloid,
355 (void) LockAcquire(&tag, lockmode, false, false);
356
357 /*
358 * If an inplace update just finished, ensure we process the syscache
359 * inval.
360 *
361 * If a heap_update() call just released its LOCKTAG_TUPLE, we'll
362 * probably find the old tuple and reach "tuple concurrently updated".
363 * If that heap_update() aborts, our LOCKTAG_TUPLE blocks inplace
364 * updates while our caller works.
365 */
367 }
368}
369
370/*
371 * SearchSysCacheCopy
372 *
373 * A convenience routine that does SearchSysCache and (if successful)
374 * returns a modifiable copy of the syscache entry. The original
375 * syscache entry is released before returning. The caller should
376 * heap_freetuple() the result when done with it.
377 */
380 Datum key1,
381 Datum key2,
382 Datum key3,
383 Datum key4)
384{
385 HeapTuple tuple,
386 newtuple;
387
388 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
389 if (!HeapTupleIsValid(tuple))
390 return tuple;
391 newtuple = heap_copytuple(tuple);
392 ReleaseSysCache(tuple);
393 return newtuple;
394}
395
396/*
397 * SearchSysCacheLockedCopy1
398 *
399 * Meld SearchSysCacheLockedCopy1 with SearchSysCacheCopy(). After the
400 * caller's heap_update(), it should UnlockTuple(InplaceUpdateTupleLock) and
401 * heap_freetuple().
402 */
405 Datum key1)
406{
407 HeapTuple tuple,
408 newtuple;
409
410 tuple = SearchSysCacheLocked1(cacheId, key1);
411 if (!HeapTupleIsValid(tuple))
412 return tuple;
413 newtuple = heap_copytuple(tuple);
414 ReleaseSysCache(tuple);
415 return newtuple;
416}
417
418/*
419 * SearchSysCacheExists
420 *
421 * A convenience routine that just probes to see if a tuple can be found.
422 * No lock is retained on the syscache entry.
423 */
424bool
426 Datum key1,
427 Datum key2,
428 Datum key3,
429 Datum key4)
430{
431 HeapTuple tuple;
432
433 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
434 if (!HeapTupleIsValid(tuple))
435 return false;
436 ReleaseSysCache(tuple);
437 return true;
438}
439
440/*
441 * GetSysCacheOid
442 *
443 * A convenience routine that does SearchSysCache and returns the OID in the
444 * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
445 * No lock is retained on the syscache entry.
446 */
447Oid
448GetSysCacheOid(int cacheId,
449 AttrNumber oidcol,
450 Datum key1,
451 Datum key2,
452 Datum key3,
453 Datum key4)
454{
455 HeapTuple tuple;
456 bool isNull;
457 Oid result;
458
459 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
460 if (!HeapTupleIsValid(tuple))
461 return InvalidOid;
462 result = heap_getattr(tuple, oidcol,
463 SysCache[cacheId]->cc_tupdesc,
464 &isNull);
465 Assert(!isNull); /* columns used as oids should never be NULL */
466 ReleaseSysCache(tuple);
467 return result;
468}
469
470
471/*
472 * SearchSysCacheAttName
473 *
474 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
475 * except that it will return NULL if the found attribute is marked
476 * attisdropped. This is convenient for callers that want to act as
477 * though dropped attributes don't exist.
478 */
481{
482 HeapTuple tuple;
483
484 tuple = SearchSysCache2(ATTNAME,
485 ObjectIdGetDatum(relid),
487 if (!HeapTupleIsValid(tuple))
488 return NULL;
489 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
490 {
491 ReleaseSysCache(tuple);
492 return NULL;
493 }
494 return tuple;
495}
496
497/*
498 * SearchSysCacheCopyAttName
499 *
500 * As above, an attisdropped-aware version of SearchSysCacheCopy.
501 */
504{
505 HeapTuple tuple,
506 newtuple;
507
508 tuple = SearchSysCacheAttName(relid, attname);
509 if (!HeapTupleIsValid(tuple))
510 return tuple;
511 newtuple = heap_copytuple(tuple);
512 ReleaseSysCache(tuple);
513 return newtuple;
514}
515
516/*
517 * SearchSysCacheExistsAttName
518 *
519 * As above, an attisdropped-aware version of SearchSysCacheExists.
520 */
521bool
523{
524 HeapTuple tuple;
525
526 tuple = SearchSysCacheAttName(relid, attname);
527 if (!HeapTupleIsValid(tuple))
528 return false;
529 ReleaseSysCache(tuple);
530 return true;
531}
532
533
534/*
535 * SearchSysCacheAttNum
536 *
537 * This routine is equivalent to SearchSysCache on the ATTNUM cache,
538 * except that it will return NULL if the found attribute is marked
539 * attisdropped. This is convenient for callers that want to act as
540 * though dropped attributes don't exist.
541 */
544{
545 HeapTuple tuple;
546
547 tuple = SearchSysCache2(ATTNUM,
548 ObjectIdGetDatum(relid),
550 if (!HeapTupleIsValid(tuple))
551 return NULL;
552 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
553 {
554 ReleaseSysCache(tuple);
555 return NULL;
556 }
557 return tuple;
558}
559
560/*
561 * SearchSysCacheCopyAttNum
562 *
563 * As above, an attisdropped-aware version of SearchSysCacheCopy.
564 */
567{
568 HeapTuple tuple,
569 newtuple;
570
571 tuple = SearchSysCacheAttNum(relid, attnum);
572 if (!HeapTupleIsValid(tuple))
573 return NULL;
574 newtuple = heap_copytuple(tuple);
575 ReleaseSysCache(tuple);
576 return newtuple;
577}
578
579
580/*
581 * SysCacheGetAttr
582 *
583 * Given a tuple previously fetched by SearchSysCache(),
584 * extract a specific attribute.
585 *
586 * This is equivalent to using heap_getattr() on a tuple fetched
587 * from a non-cached relation. Usually, this is only used for attributes
588 * that could be NULL or variable length; the fixed-size attributes in
589 * a system table are accessed just by mapping the tuple onto the C struct
590 * declarations from include/catalog/.
591 *
592 * As with heap_getattr(), if the attribute is of a pass-by-reference type
593 * then a pointer into the tuple data area is returned --- the caller must
594 * not modify or pfree the datum!
595 *
596 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
597 * a different cache for the same catalog the tuple was fetched from.
598 */
599Datum
600SysCacheGetAttr(int cacheId, HeapTuple tup,
601 AttrNumber attributeNumber,
602 bool *isNull)
603{
604 /*
605 * We just need to get the TupleDesc out of the cache entry, and then we
606 * can apply heap_getattr(). Normally the cache control data is already
607 * valid (because the caller recently fetched the tuple via this same
608 * cache), but there are cases where we have to initialize the cache here.
609 */
610 if (cacheId < 0 || cacheId >= SysCacheSize ||
611 !PointerIsValid(SysCache[cacheId]))
612 elog(ERROR, "invalid cache ID: %d", cacheId);
613 if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
614 {
615 InitCatCachePhase2(SysCache[cacheId], false);
616 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
617 }
618
619 return heap_getattr(tup, attributeNumber,
620 SysCache[cacheId]->cc_tupdesc,
621 isNull);
622}
623
624/*
625 * SysCacheGetAttrNotNull
626 *
627 * As above, a version of SysCacheGetAttr which knows that the attr cannot
628 * be NULL.
629 */
630Datum
632 AttrNumber attributeNumber)
633{
634 bool isnull;
635 Datum attr;
636
637 attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
638
639 if (isnull)
640 {
641 elog(ERROR,
642 "unexpected null value in cached tuple for catalog %s column %s",
643 get_rel_name(cacheinfo[cacheId].reloid),
644 NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
645 }
646
647 return attr;
648}
649
650/*
651 * GetSysCacheHashValue
652 *
653 * Get the hash value that would be used for a tuple in the specified cache
654 * with the given search keys.
655 *
656 * The reason for exposing this as part of the API is that the hash value is
657 * exposed in cache invalidation operations, so there are places outside the
658 * catcache code that need to be able to compute the hash values.
659 */
660uint32
662 Datum key1,
663 Datum key2,
664 Datum key3,
665 Datum key4)
666{
667 if (cacheId < 0 || cacheId >= SysCacheSize ||
668 !PointerIsValid(SysCache[cacheId]))
669 elog(ERROR, "invalid cache ID: %d", cacheId);
670
671 return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
672}
673
674/*
675 * List-search interface
676 */
677struct catclist *
678SearchSysCacheList(int cacheId, int nkeys,
679 Datum key1, Datum key2, Datum key3)
680{
681 if (cacheId < 0 || cacheId >= SysCacheSize ||
682 !PointerIsValid(SysCache[cacheId]))
683 elog(ERROR, "invalid cache ID: %d", cacheId);
684
685 return SearchCatCacheList(SysCache[cacheId], nkeys,
686 key1, key2, key3);
687}
688
689/*
690 * SysCacheInvalidate
691 *
692 * Invalidate entries in the specified cache, given a hash value.
693 * See CatCacheInvalidate() for more info.
694 *
695 * This routine is only quasi-public: it should only be used by inval.c.
696 */
697void
698SysCacheInvalidate(int cacheId, uint32 hashValue)
699{
700 if (cacheId < 0 || cacheId >= SysCacheSize)
701 elog(ERROR, "invalid cache ID: %d", cacheId);
702
703 /* if this cache isn't initialized yet, no need to do anything */
704 if (!PointerIsValid(SysCache[cacheId]))
705 return;
706
707 CatCacheInvalidate(SysCache[cacheId], hashValue);
708}
709
710/*
711 * Certain relations that do not have system caches send snapshot invalidation
712 * messages in lieu of catcache messages. This is for the benefit of
713 * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
714 * for scanning one of those catalogs, rather than taking a new one, if no
715 * invalidation has been received.
716 *
717 * Relations that have syscaches need not (and must not) be listed here. The
718 * catcache invalidation messages will also flush the snapshot. If you add a
719 * syscache for one of these relations, remove it from this list.
720 */
721bool
723{
724 switch (relid)
725 {
726 case DbRoleSettingRelationId:
727 case DependRelationId:
728 case SharedDependRelationId:
729 case DescriptionRelationId:
730 case SharedDescriptionRelationId:
731 case SecLabelRelationId:
732 case SharedSecLabelRelationId:
733 return true;
734 default:
735 break;
736 }
737
738 return false;
739}
740
741/*
742 * Test whether a relation has a system cache.
743 */
744bool
746{
747 int low = 0,
748 high = SysCacheRelationOidSize - 1;
749
750 while (low <= high)
751 {
752 int middle = low + (high - low) / 2;
753
754 if (SysCacheRelationOid[middle] == relid)
755 return true;
756 if (SysCacheRelationOid[middle] < relid)
757 low = middle + 1;
758 else
759 high = middle - 1;
760 }
761
762 return false;
763}
764
765/*
766 * Test whether a relation supports a system cache, ie it is either a
767 * cached table or the index used for a cache.
768 */
769bool
771{
772 int low = 0,
774
775 while (low <= high)
776 {
777 int middle = low + (high - low) / 2;
778
779 if (SysCacheSupportingRelOid[middle] == relid)
780 return true;
781 if (SysCacheSupportingRelOid[middle] < relid)
782 low = middle + 1;
783 else
784 high = middle - 1;
785 }
786
787 return false;
788}
789
790
791/*
792 * OID comparator for qsort
793 */
794static int
795oid_compare(const void *a, const void *b)
796{
797 Oid oa = *((const Oid *) a);
798 Oid ob = *((const Oid *) b);
799
800 return pg_cmp_u32(oa, ob);
801}
int16 AttrNumber
Definition: attnum.h:21
#define NameStr(name)
Definition: c.h:703
#define Assert(condition)
Definition: c.h:815
#define PointerIsValid(pointer)
Definition: c.h:720
int16_t int16
Definition: c.h:483
uint32_t uint32
Definition: c.h:488
#define lengthof(array)
Definition: c.h:745
#define OidIsValid(objectId)
Definition: c.h:732
CatCache * InitCatCache(int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
Definition: catcache.c:878
HeapTuple SearchCatCache2(CatCache *cache, Datum v1, Datum v2)
Definition: catcache.c:1337
HeapTuple SearchCatCache3(CatCache *cache, Datum v1, Datum v2, Datum v3)
Definition: catcache.c:1345
void InitCatCachePhase2(CatCache *cache, bool touch_index)
Definition: catcache.c:1195
CatCList * SearchCatCacheList(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
Definition: catcache.c:1696
uint32 GetCatCacheHashValue(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1662
HeapTuple SearchCatCache4(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1353
void CatCacheInvalidate(CatCache *cache, uint32 hashValue)
Definition: catcache.c:625
HeapTuple SearchCatCache1(CatCache *cache, Datum v1)
Definition: catcache.c:1329
void ReleaseCatCache(HeapTuple tuple)
Definition: catcache.c:1623
HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1312
#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:778
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:903
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:652
void AcceptInvalidationMessages(void)
Definition: inval.c:863
int b
Definition: isn.c:69
int a
Definition: isn.c:68
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:803
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:2011
#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:200
#define qsort(a, b, c, d)
Definition: port.h:474
uintptr_t Datum
Definition: postgres.h:69
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:177
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
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
Oid cc_reloid
Definition: catcache.h:60
bool cc_relisshared
Definition: catcache.h:62
short nkeys
Definition: catcache.h:177
HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname)
Definition: syscache.c:503
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:698
struct catclist * SearchSysCacheList(int cacheId, int nkeys, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:678
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:745
HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
Definition: syscache.c:566
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:404
static int oid_compare(const void *a, const void *b)
Definition: syscache.c:795
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:661
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:543
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:770
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
bool SearchSysCacheExistsAttName(Oid relid, const char *attname)
Definition: syscache.c:522
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:480
bool SearchSysCacheExists(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:425
HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:379
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:722
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:631
Oid GetSysCacheOid(int cacheId, AttrNumber oidcol, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:448
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153