Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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