PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2014, 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 "access/sysattr.h"
25 #include "catalog/indexing.h"
26 #include "catalog/pg_aggregate.h"
27 #include "catalog/pg_amop.h"
28 #include "catalog/pg_amproc.h"
30 #include "catalog/pg_authid.h"
31 #include "catalog/pg_cast.h"
32 #include "catalog/pg_collation.h"
33 #include "catalog/pg_constraint.h"
34 #include "catalog/pg_conversion.h"
35 #include "catalog/pg_database.h"
37 #include "catalog/pg_default_acl.h"
38 #include "catalog/pg_depend.h"
39 #include "catalog/pg_description.h"
40 #include "catalog/pg_enum.h"
45 #include "catalog/pg_language.h"
46 #include "catalog/pg_namespace.h"
47 #include "catalog/pg_opclass.h"
48 #include "catalog/pg_operator.h"
49 #include "catalog/pg_opfamily.h"
50 #include "catalog/pg_proc.h"
51 #include "catalog/pg_range.h"
52 #include "catalog/pg_rewrite.h"
53 #include "catalog/pg_seclabel.h"
54 #include "catalog/pg_shdepend.h"
56 #include "catalog/pg_shseclabel.h"
57 #include "catalog/pg_statistic.h"
58 #include "catalog/pg_tablespace.h"
59 #include "catalog/pg_ts_config.h"
61 #include "catalog/pg_ts_dict.h"
62 #include "catalog/pg_ts_parser.h"
63 #include "catalog/pg_ts_template.h"
64 #include "catalog/pg_type.h"
66 #include "utils/rel.h"
67 #include "utils/catcache.h"
68 #include "utils/syscache.h"
69 
70 
71 /*---------------------------------------------------------------------------
72 
73  Adding system caches:
74 
75  Add your new cache to the list in include/utils/syscache.h.
76  Keep the list sorted alphabetically.
77 
78  Add your entry to the cacheinfo[] array below. All cache lists are
79  alphabetical, so add it in the proper place. Specify the relation OID,
80  index OID, number of keys, key attribute numbers, and initial number of
81  hash buckets.
82 
83  The number of hash buckets must be a power of 2. It's reasonable to
84  set this to the number of entries that might be in the particular cache
85  in a medium-size database.
86 
87  There must be a unique index underlying each syscache (ie, an index
88  whose key is the same as that of the cache). If there is not one
89  already, add definitions for it to include/catalog/indexing.h: you need
90  to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID.
91  (Adding an index requires a catversion.h update, while simply
92  adding/deleting caches only requires a recompile.)
93 
94  Finally, any place your relation gets heap_insert() or
95  heap_update() calls, make sure there is a CatalogUpdateIndexes() or
96  similar call. The heap_* calls do not update indexes.
97 
98  bjm 1999/11/22
99 
100 *---------------------------------------------------------------------------
101 */
102 
103 /*
104  * struct cachedesc: information defining a single syscache
105  */
106 struct cachedesc
107 {
108  Oid reloid; /* OID of the relation being cached */
109  Oid indoid; /* OID of index relation for this cache */
110  int nkeys; /* # of keys needed for cache lookup */
111  int key[4]; /* attribute numbers of key attrs */
112  int nbuckets; /* number of hash buckets for this cache */
113 };
114 
115 static const struct cachedesc cacheinfo[] = {
116  {AggregateRelationId, /* AGGFNOID */
118  1,
119  {
121  0,
122  0,
123  0
124  },
125  16
126  },
127  {AccessMethodRelationId, /* AMNAME */
129  1,
130  {
132  0,
133  0,
134  0
135  },
136  4
137  },
138  {AccessMethodRelationId, /* AMOID */
139  AmOidIndexId,
140  1,
141  {
143  0,
144  0,
145  0
146  },
147  4
148  },
149  {AccessMethodOperatorRelationId, /* AMOPOPID */
151  3,
152  {
156  0
157  },
158  64
159  },
160  {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
162  4,
163  {
168  },
169  64
170  },
171  {AccessMethodProcedureRelationId, /* AMPROCNUM */
173  4,
174  {
179  },
180  16
181  },
182  {AttributeRelationId, /* ATTNAME */
184  2,
185  {
188  0,
189  0
190  },
191  32
192  },
193  {AttributeRelationId, /* ATTNUM */
195  2,
196  {
199  0,
200  0
201  },
202  128
203  },
204  {AuthMemRelationId, /* AUTHMEMMEMROLE */
206  2,
207  {
210  0,
211  0
212  },
213  8
214  },
215  {AuthMemRelationId, /* AUTHMEMROLEMEM */
217  2,
218  {
221  0,
222  0
223  },
224  8
225  },
226  {AuthIdRelationId, /* AUTHNAME */
228  1,
229  {
231  0,
232  0,
233  0
234  },
235  8
236  },
237  {AuthIdRelationId, /* AUTHOID */
239  1,
240  {
242  0,
243  0,
244  0
245  },
246  8
247  },
248  {
249  CastRelationId, /* CASTSOURCETARGET */
251  2,
252  {
255  0,
256  0
257  },
258  256
259  },
260  {OperatorClassRelationId, /* CLAAMNAMENSP */
262  3,
263  {
267  0
268  },
269  8
270  },
271  {OperatorClassRelationId, /* CLAOID */
273  1,
274  {
276  0,
277  0,
278  0
279  },
280  8
281  },
282  {CollationRelationId, /* COLLNAMEENCNSP */
284  3,
285  {
289  0
290  },
291  8
292  },
293  {CollationRelationId, /* COLLOID */
295  1,
296  {
298  0,
299  0,
300  0
301  },
302  8
303  },
304  {ConversionRelationId, /* CONDEFAULT */
306  4,
307  {
312  },
313  8
314  },
315  {ConversionRelationId, /* CONNAMENSP */
317  2,
318  {
321  0,
322  0
323  },
324  8
325  },
326  {ConstraintRelationId, /* CONSTROID */
328  1,
329  {
331  0,
332  0,
333  0
334  },
335  16
336  },
337  {ConversionRelationId, /* CONVOID */
339  1,
340  {
342  0,
343  0,
344  0
345  },
346  8
347  },
348  {DatabaseRelationId, /* DATABASEOID */
350  1,
351  {
353  0,
354  0,
355  0
356  },
357  4
358  },
359  {DefaultAclRelationId, /* DEFACLROLENSPOBJ */
361  3,
362  {
366  0
367  },
368  8
369  },
370  {EnumRelationId, /* ENUMOID */
372  1,
373  {
375  0,
376  0,
377  0
378  },
379  8
380  },
381  {EnumRelationId, /* ENUMTYPOIDNAME */
383  2,
384  {
387  0,
388  0
389  },
390  8
391  },
392  {EventTriggerRelationId, /* EVENTTRIGGERNAME */
394  1,
395  {
397  0,
398  0,
399  0
400  },
401  8
402  },
403  {EventTriggerRelationId, /* EVENTTRIGGEROID */
405  1,
406  {
408  0,
409  0,
410  0
411  },
412  8
413  },
414  {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
416  1,
417  {
419  0,
420  0,
421  0
422  },
423  2
424  },
425  {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
427  1,
428  {
430  0,
431  0,
432  0
433  },
434  2
435  },
436  {ForeignServerRelationId, /* FOREIGNSERVERNAME */
438  1,
439  {
441  0,
442  0,
443  0
444  },
445  2
446  },
447  {ForeignServerRelationId, /* FOREIGNSERVEROID */
449  1,
450  {
452  0,
453  0,
454  0
455  },
456  2
457  },
458  {ForeignTableRelationId, /* FOREIGNTABLEREL */
460  1,
461  {
463  0,
464  0,
465  0
466  },
467  4
468  },
469  {IndexRelationId, /* INDEXRELID */
471  1,
472  {
474  0,
475  0,
476  0
477  },
478  64
479  },
480  {LanguageRelationId, /* LANGNAME */
482  1,
483  {
485  0,
486  0,
487  0
488  },
489  4
490  },
491  {LanguageRelationId, /* LANGOID */
493  1,
494  {
496  0,
497  0,
498  0
499  },
500  4
501  },
502  {NamespaceRelationId, /* NAMESPACENAME */
504  1,
505  {
507  0,
508  0,
509  0
510  },
511  4
512  },
513  {NamespaceRelationId, /* NAMESPACEOID */
515  1,
516  {
518  0,
519  0,
520  0
521  },
522  16
523  },
524  {OperatorRelationId, /* OPERNAMENSP */
526  4,
527  {
532  },
533  256
534  },
535  {OperatorRelationId, /* OPEROID */
537  1,
538  {
540  0,
541  0,
542  0
543  },
544  32
545  },
546  {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
548  3,
549  {
553  0
554  },
555  8
556  },
557  {OperatorFamilyRelationId, /* OPFAMILYOID */
559  1,
560  {
562  0,
563  0,
564  0
565  },
566  8
567  },
568  {ProcedureRelationId, /* PROCNAMEARGSNSP */
570  3,
571  {
575  0
576  },
577  128
578  },
579  {ProcedureRelationId, /* PROCOID */
581  1,
582  {
584  0,
585  0,
586  0
587  },
588  128
589  },
590  {RangeRelationId, /* RANGETYPE */
592  1,
593  {
595  0,
596  0,
597  0
598  },
599  4
600  },
601  {RelationRelationId, /* RELNAMENSP */
603  2,
604  {
607  0,
608  0
609  },
610  128
611  },
612  {RelationRelationId, /* RELOID */
614  1,
615  {
617  0,
618  0,
619  0
620  },
621  128
622  },
623  {RewriteRelationId, /* RULERELNAME */
625  2,
626  {
629  0,
630  0
631  },
632  8
633  },
634  {StatisticRelationId, /* STATRELATTINH */
636  3,
637  {
641  0
642  },
643  128
644  },
645  {TableSpaceRelationId, /* TABLESPACEOID */
647  1,
648  {
650  0,
651  0,
652  0,
653  },
654  4
655  },
656  {TSConfigMapRelationId, /* TSCONFIGMAP */
658  3,
659  {
663  0
664  },
665  2
666  },
667  {TSConfigRelationId, /* TSCONFIGNAMENSP */
669  2,
670  {
673  0,
674  0
675  },
676  2
677  },
678  {TSConfigRelationId, /* TSCONFIGOID */
680  1,
681  {
683  0,
684  0,
685  0
686  },
687  2
688  },
689  {TSDictionaryRelationId, /* TSDICTNAMENSP */
691  2,
692  {
695  0,
696  0
697  },
698  2
699  },
700  {TSDictionaryRelationId, /* TSDICTOID */
702  1,
703  {
705  0,
706  0,
707  0
708  },
709  2
710  },
711  {TSParserRelationId, /* TSPARSERNAMENSP */
713  2,
714  {
717  0,
718  0
719  },
720  2
721  },
722  {TSParserRelationId, /* TSPARSEROID */
724  1,
725  {
727  0,
728  0,
729  0
730  },
731  2
732  },
733  {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
735  2,
736  {
739  0,
740  0
741  },
742  2
743  },
744  {TSTemplateRelationId, /* TSTEMPLATEOID */
746  1,
747  {
749  0,
750  0,
751  0
752  },
753  2
754  },
755  {TypeRelationId, /* TYPENAMENSP */
757  2,
758  {
761  0,
762  0
763  },
764  64
765  },
766  {TypeRelationId, /* TYPEOID */
768  1,
769  {
771  0,
772  0,
773  0
774  },
775  64
776  },
777  {UserMappingRelationId, /* USERMAPPINGOID */
779  1,
780  {
782  0,
783  0,
784  0
785  },
786  2
787  },
788  {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
790  2,
791  {
794  0,
795  0
796  },
797  2
798  }
799 };
800 
801 static CatCache *SysCache[
802  lengthof(cacheinfo)];
803 static int SysCacheSize = lengthof(cacheinfo);
804 static bool CacheInitialized = false;
805 
806 static Oid SysCacheRelationOid[lengthof(cacheinfo)];
808 
809 static int oid_compare(const void *a, const void *b);
810 
811 /*
812  * InitCatalogCache - initialize the caches
813  *
814  * Note that no database access is done here; we only allocate memory
815  * and initialize the cache structure. Interrogation of the database
816  * to complete initialization of a cache happens upon first use
817  * of that cache.
818  */
819 void
821 {
822  int cacheId;
823  int i,
824  j = 0;
825 
827 
828  MemSet(SysCache, 0, sizeof(SysCache));
829 
830  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
831  {
832  SysCache[cacheId] = InitCatCache(cacheId,
833  cacheinfo[cacheId].reloid,
834  cacheinfo[cacheId].indoid,
835  cacheinfo[cacheId].nkeys,
836  cacheinfo[cacheId].key,
837  cacheinfo[cacheId].nbuckets);
838  if (!PointerIsValid(SysCache[cacheId]))
839  elog(ERROR, "could not initialize cache %u (%d)",
840  cacheinfo[cacheId].reloid, cacheId);
842  cacheinfo[cacheId].reloid;
843  /* see comments for RelationInvalidatesSnapshotsOnly */
844  Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
845  }
846 
847  /* Sort and dedup OIDs. */
849  sizeof(Oid), oid_compare);
850  for (i = 1; i < SysCacheRelationOidSize; ++i)
853  SysCacheRelationOidSize = j + 1;
854 
855  CacheInitialized = true;
856 }
857 
858 /*
859  * InitCatalogCachePhase2 - finish initializing the caches
860  *
861  * Finish initializing all the caches, including necessary database
862  * access.
863  *
864  * This is *not* essential; normally we allow syscaches to be initialized
865  * on first use. However, it is useful as a mechanism to preload the
866  * relcache with entries for the most-commonly-used system catalogs.
867  * Therefore, we invoke this routine when we need to write a new relcache
868  * init file.
869  */
870 void
872 {
873  int cacheId;
874 
876 
877  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
878  InitCatCachePhase2(SysCache[cacheId], true);
879 }
880 
881 
882 /*
883  * SearchSysCache
884  *
885  * A layer on top of SearchCatCache that does the initialization and
886  * key-setting for you.
887  *
888  * Returns the cache copy of the tuple if one is found, NULL if not.
889  * The tuple is the 'cache' copy and must NOT be modified!
890  *
891  * When the caller is done using the tuple, call ReleaseSysCache()
892  * to release the reference count grabbed by SearchSysCache(). If this
893  * is not done, the tuple will remain locked in cache until end of
894  * transaction, which is tolerable but not desirable.
895  *
896  * CAUTION: The tuple that is returned must NOT be freed by the caller!
897  */
898 HeapTuple
899 SearchSysCache(int cacheId,
900  Datum key1,
901  Datum key2,
902  Datum key3,
903  Datum key4)
904 {
905  if (cacheId < 0 || cacheId >= SysCacheSize ||
906  !PointerIsValid(SysCache[cacheId]))
907  elog(ERROR, "invalid cache ID: %d", cacheId);
908 
909  return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
910 }
911 
912 /*
913  * ReleaseSysCache
914  * Release previously grabbed reference count on a tuple
915  */
916 void
918 {
919  ReleaseCatCache(tuple);
920 }
921 
922 /*
923  * SearchSysCacheCopy
924  *
925  * A convenience routine that does SearchSysCache and (if successful)
926  * returns a modifiable copy of the syscache entry. The original
927  * syscache entry is released before returning. The caller should
928  * heap_freetuple() the result when done with it.
929  */
930 HeapTuple
931 SearchSysCacheCopy(int cacheId,
932  Datum key1,
933  Datum key2,
934  Datum key3,
935  Datum key4)
936 {
937  HeapTuple tuple,
938  newtuple;
939 
940  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
941  if (!HeapTupleIsValid(tuple))
942  return tuple;
943  newtuple = heap_copytuple(tuple);
944  ReleaseSysCache(tuple);
945  return newtuple;
946 }
947 
948 /*
949  * SearchSysCacheExists
950  *
951  * A convenience routine that just probes to see if a tuple can be found.
952  * No lock is retained on the syscache entry.
953  */
954 bool
956  Datum key1,
957  Datum key2,
958  Datum key3,
959  Datum key4)
960 {
961  HeapTuple tuple;
962 
963  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
964  if (!HeapTupleIsValid(tuple))
965  return false;
966  ReleaseSysCache(tuple);
967  return true;
968 }
969 
970 /*
971  * GetSysCacheOid
972  *
973  * A convenience routine that does SearchSysCache and returns the OID
974  * of the found tuple, or InvalidOid if no tuple could be found.
975  * No lock is retained on the syscache entry.
976  */
977 Oid
978 GetSysCacheOid(int cacheId,
979  Datum key1,
980  Datum key2,
981  Datum key3,
982  Datum key4)
983 {
984  HeapTuple tuple;
985  Oid result;
986 
987  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
988  if (!HeapTupleIsValid(tuple))
989  return InvalidOid;
990  result = HeapTupleGetOid(tuple);
991  ReleaseSysCache(tuple);
992  return result;
993 }
994 
995 
996 /*
997  * SearchSysCacheAttName
998  *
999  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1000  * except that it will return NULL if the found attribute is marked
1001  * attisdropped. This is convenient for callers that want to act as
1002  * though dropped attributes don't exist.
1003  */
1004 HeapTuple
1005 SearchSysCacheAttName(Oid relid, const char *attname)
1006 {
1007  HeapTuple tuple;
1008 
1009  tuple = SearchSysCache2(ATTNAME,
1010  ObjectIdGetDatum(relid),
1011  CStringGetDatum(attname));
1012  if (!HeapTupleIsValid(tuple))
1013  return NULL;
1014  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1015  {
1016  ReleaseSysCache(tuple);
1017  return NULL;
1018  }
1019  return tuple;
1020 }
1021 
1022 /*
1023  * SearchSysCacheCopyAttName
1024  *
1025  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1026  */
1027 HeapTuple
1028 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1029 {
1030  HeapTuple tuple,
1031  newtuple;
1032 
1033  tuple = SearchSysCacheAttName(relid, attname);
1034  if (!HeapTupleIsValid(tuple))
1035  return tuple;
1036  newtuple = heap_copytuple(tuple);
1037  ReleaseSysCache(tuple);
1038  return newtuple;
1039 }
1040 
1041 /*
1042  * SearchSysCacheExistsAttName
1043  *
1044  * As above, an attisdropped-aware version of SearchSysCacheExists.
1045  */
1046 bool
1047 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1048 {
1049  HeapTuple tuple;
1050 
1051  tuple = SearchSysCacheAttName(relid, attname);
1052  if (!HeapTupleIsValid(tuple))
1053  return false;
1054  ReleaseSysCache(tuple);
1055  return true;
1056 }
1057 
1058 
1059 /*
1060  * SysCacheGetAttr
1061  *
1062  * Given a tuple previously fetched by SearchSysCache(),
1063  * extract a specific attribute.
1064  *
1065  * This is equivalent to using heap_getattr() on a tuple fetched
1066  * from a non-cached relation. Usually, this is only used for attributes
1067  * that could be NULL or variable length; the fixed-size attributes in
1068  * a system table are accessed just by mapping the tuple onto the C struct
1069  * declarations from include/catalog/.
1070  *
1071  * As with heap_getattr(), if the attribute is of a pass-by-reference type
1072  * then a pointer into the tuple data area is returned --- the caller must
1073  * not modify or pfree the datum!
1074  *
1075  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1076  * a different cache for the same catalog the tuple was fetched from.
1077  */
1078 Datum
1079 SysCacheGetAttr(int cacheId, HeapTuple tup,
1080  AttrNumber attributeNumber,
1081  bool *isNull)
1082 {
1083  /*
1084  * We just need to get the TupleDesc out of the cache entry, and then we
1085  * can apply heap_getattr(). Normally the cache control data is already
1086  * valid (because the caller recently fetched the tuple via this same
1087  * cache), but there are cases where we have to initialize the cache here.
1088  */
1089  if (cacheId < 0 || cacheId >= SysCacheSize ||
1090  !PointerIsValid(SysCache[cacheId]))
1091  elog(ERROR, "invalid cache ID: %d", cacheId);
1092  if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1093  {
1094  InitCatCachePhase2(SysCache[cacheId], false);
1095  Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1096  }
1097 
1098  return heap_getattr(tup, attributeNumber,
1099  SysCache[cacheId]->cc_tupdesc,
1100  isNull);
1101 }
1102 
1103 /*
1104  * GetSysCacheHashValue
1105  *
1106  * Get the hash value that would be used for a tuple in the specified cache
1107  * with the given search keys.
1108  *
1109  * The reason for exposing this as part of the API is that the hash value is
1110  * exposed in cache invalidation operations, so there are places outside the
1111  * catcache code that need to be able to compute the hash values.
1112  */
1113 uint32
1115  Datum key1,
1116  Datum key2,
1117  Datum key3,
1118  Datum key4)
1119 {
1120  if (cacheId < 0 || cacheId >= SysCacheSize ||
1121  !PointerIsValid(SysCache[cacheId]))
1122  elog(ERROR, "invalid cache ID: %d", cacheId);
1123 
1124  return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1125 }
1126 
1127 /*
1128  * List-search interface
1129  */
1130 struct catclist *
1131 SearchSysCacheList(int cacheId, int nkeys,
1132  Datum key1, Datum key2, Datum key3, Datum key4)
1133 {
1134  if (cacheId < 0 || cacheId >= SysCacheSize ||
1135  !PointerIsValid(SysCache[cacheId]))
1136  elog(ERROR, "invalid cache ID: %d", cacheId);
1137 
1138  return SearchCatCacheList(SysCache[cacheId], nkeys,
1139  key1, key2, key3, key4);
1140 }
1141 
1142 /*
1143  * Certain relations that do not have system caches send snapshot invalidation
1144  * messages in lieu of catcache messages. This is for the benefit of
1145  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1146  * for scanning one of those catalogs, rather than taking a new one, if no
1147  * invalidation has been received.
1148  *
1149  * Relations that have syscaches need not (and must not) be listed here. The
1150  * catcache invalidation messages will also flush the snapshot. If you add a
1151  * syscache for one of these relations, remove it from this list.
1152  */
1153 bool
1155 {
1156  switch (relid)
1157  {
1159  case DependRelationId:
1161  case DescriptionRelationId:
1163  case SecLabelRelationId:
1165  return true;
1166  default:
1167  break;
1168  }
1169 
1170  return false;
1171 }
1172 
1173 /*
1174  * Test whether a relation has a system cache.
1175  */
1176 bool
1178 {
1179  int low = 0,
1180  high = SysCacheRelationOidSize - 1;
1181 
1182  while (low <= high)
1183  {
1184  int middle = low + (high - low) / 2;
1185 
1186  if (SysCacheRelationOid[middle] == relid)
1187  return true;
1188  if (SysCacheRelationOid[middle] < relid)
1189  low = middle + 1;
1190  else
1191  high = middle - 1;
1192  }
1193 
1194  return false;
1195 }
1196 
1197 
1198 /*
1199  * OID comparator for pg_qsort
1200  */
1201 static int
1202 oid_compare(const void *a, const void *b)
1203 {
1204  Oid oa = *((Oid *) a);
1205  Oid ob = *((Oid *) b);
1206 
1207  if (oa == ob)
1208  return 0;
1209  return (oa > ob) ? 1 : -1;
1210 }