]> granicus.if.org Git - postgresql/blob - src/backend/utils/cache/syscache.c
Final cleanup
[postgresql] / src / backend / utils / cache / syscache.c
1 /*-------------------------------------------------------------------------
2  *
3  * syscache.c
4  *        System cache management routines
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.30 1999/07/16 05:23:21 momjian Exp $
11  *
12  * NOTES
13  *        These routines allow the parser/planner/executor to perform
14  *        rapid lookups on the contents of the system catalogs.
15  *
16  *        see catalog/syscache.h for a list of the cache id's
17  *
18  *-------------------------------------------------------------------------
19  */
20 #include <string.h>
21 #include "postgres.h"
22
23 #include "access/heapam.h"
24 #include "catalog/catname.h"
25 #include "catalog/pg_aggregate.h"
26 #include "catalog/pg_amop.h"
27 #include "catalog/pg_group.h"
28 #include "catalog/pg_index.h"
29 #include "catalog/pg_inherits.h"
30 #include "catalog/pg_language.h"
31 #include "catalog/pg_listener.h"
32 #include "catalog/pg_opclass.h"
33 #include "catalog/pg_operator.h"
34 #include "catalog/pg_proc.h"
35 #include "catalog/pg_rewrite.h"
36 #include "catalog/pg_shadow.h"
37 #include "catalog/pg_type.h"
38 #include "utils/catcache.h"
39
40 extern bool AMI_OVERRIDE;               /* XXX style */
41
42 #include "utils/syscache.h"
43 #include "catalog/indexing.h"
44
45 typedef HeapTuple (*ScanFunc) ();
46
47 /* ----------------
48  *              Warning:  cacheinfo[] below is changed, then be sure and
49  *              update the magic constants in syscache.h!
50  * ----------------
51  */
52 static struct cachedesc cacheinfo[] = {
53         {AccessMethodOperatorRelationName,      /* AMOPOPID */
54                 3,
55                 {
56                         Anum_pg_amop_amopclaid,
57                         Anum_pg_amop_amopopr,
58                         Anum_pg_amop_amopid,
59                         0
60                 },
61                 sizeof(FormData_pg_amop),
62                 NULL,
63         (ScanFunc) NULL},
64         {AccessMethodOperatorRelationName,      /* AMOPSTRATEGY */
65                 3,
66                 {
67                         Anum_pg_amop_amopid,
68                         Anum_pg_amop_amopclaid,
69                         Anum_pg_amop_amopstrategy,
70                         0
71                 },
72                 sizeof(FormData_pg_amop),
73                 NULL,
74         (ScanFunc) NULL},
75         {AttributeRelationName,         /* ATTNAME */
76                 2,
77                 {
78                         Anum_pg_attribute_attrelid,
79                         Anum_pg_attribute_attname,
80                         0,
81                         0
82                 },
83                 ATTRIBUTE_TUPLE_SIZE,
84                 AttributeNameIndex,
85         (ScanFunc) AttributeNameIndexScan},
86         {AttributeRelationName,         /* ATTNUM */
87                 2,
88                 {
89                         Anum_pg_attribute_attrelid,
90                         Anum_pg_attribute_attnum,
91                         0,
92                         0
93                 },
94                 ATTRIBUTE_TUPLE_SIZE,
95                 AttributeNumIndex,
96         (ScanFunc) AttributeNumIndexScan},
97         {IndexRelationName,                     /* INDEXRELID */
98                 1,
99                 {
100                         Anum_pg_index_indexrelid,
101                         0,
102                         0,
103                         0
104                 },
105                 offsetof(FormData_pg_index, indpred),
106                 NULL,
107         NULL},
108         {LanguageRelationName,          /* LANNAME */
109                 1,
110                 {
111                         Anum_pg_language_lanname,
112                         0,
113                         0,
114                         0
115                 },
116                 offsetof(FormData_pg_language, lancompiler),
117                 NULL,
118         NULL},
119         {OperatorRelationName,          /* OPRNAME */
120                 4,
121                 {
122                         Anum_pg_operator_oprname,
123                         Anum_pg_operator_oprleft,
124                         Anum_pg_operator_oprright,
125                         Anum_pg_operator_oprkind
126                 },
127                 sizeof(FormData_pg_operator),
128                 NULL,
129         NULL},
130         {OperatorRelationName,          /* OPROID */
131                 1,
132                 {
133                         ObjectIdAttributeNumber,
134                         0,
135                         0,
136                         0
137                 },
138                 sizeof(FormData_pg_operator),
139                 NULL,
140         (ScanFunc) NULL},
141         {ProcedureRelationName,         /* PRONAME */
142                 3,
143                 {
144                         Anum_pg_proc_proname,
145                         Anum_pg_proc_pronargs,
146                         Anum_pg_proc_proargtypes,
147                         0
148                 },
149                 offsetof(FormData_pg_proc, prosrc),
150                 ProcedureNameIndex,
151         (ScanFunc) ProcedureNameIndexScan},
152         {ProcedureRelationName,         /* PROOID */
153                 1,
154                 {
155                         ObjectIdAttributeNumber,
156                         0,
157                         0,
158                         0
159                 },
160                 offsetof(FormData_pg_proc, prosrc),
161                 ProcedureOidIndex,
162         (ScanFunc) ProcedureOidIndexScan},
163         {RelationRelationName,          /* RELNAME */
164                 1,
165                 {
166                         Anum_pg_class_relname,
167                         0,
168                         0,
169                         0
170                 },
171                 CLASS_TUPLE_SIZE,
172                 ClassNameIndex,
173         (ScanFunc) ClassNameIndexScan},
174         {RelationRelationName,          /* RELOID */
175                 1,
176                 {
177                         ObjectIdAttributeNumber,
178                         0,
179                         0,
180                         0
181                 },
182                 CLASS_TUPLE_SIZE,
183                 ClassOidIndex,
184         (ScanFunc) ClassOidIndexScan},
185         {TypeRelationName,                      /* TYPNAME */
186                 1,
187                 {
188                         Anum_pg_type_typname,
189                         0,
190                         0,
191                         0
192                 },
193                 offsetof(FormData_pg_type, typalign) +sizeof(char),
194                 TypeNameIndex,
195         TypeNameIndexScan},
196         {TypeRelationName,                      /* TYPOID */
197                 1,
198                 {
199                         ObjectIdAttributeNumber,
200                         0,
201                         0,
202                         0
203                 },
204                 offsetof(FormData_pg_type, typalign) +sizeof(char),
205                 TypeOidIndex,
206         TypeOidIndexScan},
207         {AccessMethodRelationName,      /* AMNAME */
208                 1,
209                 {
210                         Anum_pg_am_amname,
211                         0,
212                         0,
213                         0
214                 },
215                 sizeof(FormData_pg_am),
216                 NULL,
217         NULL},
218         {OperatorClassRelationName, /* CLANAME */
219                 1,
220                 {
221                         Anum_pg_opclass_opcname,
222                         0,
223                         0,
224                         0
225                 },
226                 sizeof(FormData_pg_opclass),
227                 NULL,
228         NULL},
229         {IndexRelationName,                     /* INDRELIDKEY *//* never used */
230                 2,
231                 {
232                         Anum_pg_index_indrelid,
233                         Anum_pg_index_indkey,
234                         0,
235                         0
236                 },
237                 offsetof(FormData_pg_index, indpred),
238                 NULL,
239         (ScanFunc) NULL},
240         {InheritsRelationName,          /* INHRELID */
241                 2,
242                 {
243                         Anum_pg_inherits_inhrel,
244                         Anum_pg_inherits_inhseqno,
245                         0,
246                         0
247                 },
248                 sizeof(FormData_pg_inherits),
249                 NULL,
250         (ScanFunc) NULL},
251         {RewriteRelationName,           /* RULOID */
252                 1,
253                 {
254                         ObjectIdAttributeNumber,
255                         0,
256                         0,
257                         0
258                 },
259                 offsetof(FormData_pg_rewrite, ev_qual),
260                 NULL,
261         (ScanFunc) NULL},
262         {AggregateRelationName,         /* AGGNAME */
263                 2,
264                 {
265                         Anum_pg_aggregate_aggname,
266                         Anum_pg_aggregate_aggbasetype,
267                         0,
268                         0
269                 },
270                 offsetof(FormData_pg_aggregate, agginitval1),
271                 NULL,
272         (ScanFunc) NULL},
273         {ListenerRelationName,          /* LISTENREL */
274                 2,
275                 {
276                         Anum_pg_listener_relname,
277                         Anum_pg_listener_pid,
278                         0,
279                         0
280                 },
281                 sizeof(FormData_pg_listener),
282                 NULL,
283         (ScanFunc) NULL},
284         {ShadowRelationName,            /* USENAME */
285                 1,
286                 {
287                         Anum_pg_shadow_usename,
288                         0,
289                         0,
290                         0
291                 },
292                 sizeof(FormData_pg_shadow),
293                 NULL,
294         (ScanFunc) NULL},
295         {ShadowRelationName,            /* USESYSID */
296                 1,
297                 {
298                         Anum_pg_shadow_usesysid,
299                         0,
300                         0,
301                         0
302                 },
303                 sizeof(FormData_pg_shadow),
304                 NULL,
305         (ScanFunc) NULL},
306         {GroupRelationName,                     /* GRONAME */
307                 1,
308                 {
309                         Anum_pg_group_groname,
310                         0,
311                         0,
312                         0
313                 },
314                 offsetof(FormData_pg_group, grolist[0]),
315                 NULL,
316         (ScanFunc) NULL},
317         {GroupRelationName,                     /* GROSYSID */
318                 1,
319                 {
320                         Anum_pg_group_grosysid,
321                         0,
322                         0,
323                         0
324                 },
325                 offsetof(FormData_pg_group, grolist[0]),
326                 NULL,
327         (ScanFunc) NULL},
328         {RewriteRelationName,           /* REWRITENAME */
329                 1,
330                 {
331                         Anum_pg_rewrite_rulename,
332                         0,
333                         0,
334                         0
335                 },
336                 offsetof(FormData_pg_rewrite, ev_qual),
337                 NULL,
338         (ScanFunc) NULL},
339         {ProcedureRelationName,         /* PROSRC */
340                 1,
341                 {
342                         Anum_pg_proc_prosrc,
343                         0,
344                         0,
345                         0
346                 },
347                 offsetof(FormData_pg_proc, prosrc),
348                 ProcedureSrcIndex,
349         (ScanFunc) ProcedureSrcIndexScan},
350         {OperatorClassRelationName, /* CLADEFTYPE */
351                 1,
352                 {
353                         Anum_pg_opclass_opcdeftype,
354                         0,
355                         0,
356                         0
357                 },
358                 sizeof(FormData_pg_opclass),
359                 NULL,
360         (ScanFunc) NULL},
361         {LanguageRelationName,          /* LANOID */
362                 1,
363                 {
364                         ObjectIdAttributeNumber,
365                         0,
366                         0,
367                         0
368                 },
369                 offsetof(FormData_pg_language, lancompiler),
370                 NULL,
371         NULL}
372 };
373
374 static struct catcache *SysCache[lengthof(cacheinfo)];
375 static int32 SysCacheSize = lengthof(cacheinfo);
376
377
378 /*
379  * zerocaches
380  *
381  *        Make sure the SysCache structure is zero'd.
382  */
383 void
384 zerocaches()
385 {
386         MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));
387 }
388
389 /*
390  * Note:
391  *              This function was written because the initialized catalog caches
392  *              are used to determine which caches may contain tuples which need
393  *              to be invalidated in other backends.
394  */
395 void
396 InitCatalogCache()
397 {
398         int                     cacheId;                /* XXX type */
399
400         if (!AMI_OVERRIDE)
401         {
402                 for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
403                 {
404
405                         Assert(!PointerIsValid((Pointer) SysCache[cacheId]));
406
407                         SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
408                                                                                          cacheinfo[cacheId].indname,
409                                                                                          cacheId,
410                                                                                          cacheinfo[cacheId].nkeys,
411                                                                                          cacheinfo[cacheId].key,
412                                                                                    cacheinfo[cacheId].iScanFunc);
413                         if (!PointerIsValid((char *) SysCache[cacheId]))
414                         {
415                                 elog(ERROR,
416                                          "InitCatalogCache: Can't init cache %s(%d)",
417                                          cacheinfo[cacheId].name,
418                                          cacheId);
419                         }
420
421                 }
422         }
423 }
424
425 /*
426  * SearchSysCacheTupleCopy
427  *
428  *      This is like SearchSysCacheTuple, except it returns a copy of the tuple
429  *      that the user is required to pfree().
430  */
431 HeapTuple
432 SearchSysCacheTupleCopy(int cacheId,    /* cache selection code */
433                                                 Datum key1,
434                                                 Datum key2,
435                                                 Datum key3,
436                                                 Datum key4)
437 {
438         HeapTuple       cachetup;
439
440         cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
441         if (PointerIsValid(cachetup))
442                 return heap_copytuple(cachetup);
443         else
444                 return cachetup;                /* NULL */
445 }
446
447
448 /*
449  * SearchSysCacheTuple
450  *
451  *      A layer on top of SearchSysCache that does the initialization and
452  *      key-setting for you.
453  *
454  *      Returns the cache copy of the tuple if one is found, NULL if not.
455  *      The tuple is the 'cache' copy.
456  *
457  *      XXX The tuple that is returned is NOT supposed to be pfree'd!
458  */
459 HeapTuple
460 SearchSysCacheTuple(int cacheId,/* cache selection code */
461                                         Datum key1,
462                                         Datum key2,
463                                         Datum key3,
464                                         Datum key4)
465 {
466         HeapTuple       tp;
467
468         if (cacheId < 0 || cacheId >= SysCacheSize)
469         {
470                 elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
471                 return (HeapTuple) NULL;
472         }
473
474         Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId]));
475
476         if (!PointerIsValid(SysCache[cacheId]))
477         {
478                 SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
479                                                                                  cacheinfo[cacheId].indname,
480                                                                                  cacheId,
481                                                                                  cacheinfo[cacheId].nkeys,
482                                                                                  cacheinfo[cacheId].key,
483                                                                                  cacheinfo[cacheId].iScanFunc);
484                 if (!PointerIsValid(SysCache[cacheId]))
485                         elog(ERROR,
486                                  "InitCatalogCache: Can't init cache %s(%d)",
487                                  cacheinfo[cacheId].name,
488                                  cacheId);
489         }
490
491         tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
492         if (!HeapTupleIsValid(tp))
493         {
494 #ifdef CACHEDEBUG
495                 elog(DEBUG,
496                          "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
497                          cacheinfo[cacheId].name,
498                          cacheId, key1, key2, key3, key4);
499 #endif
500                 return (HeapTuple) NULL;
501         }
502         return tp;
503 }
504
505 /*
506  * SearchSysCacheStruct
507  *        Fills 's' with the information retrieved by calling SearchSysCache()
508  *        with arguments key1...key4.  Retrieves only the portion of the tuple
509  *        which is not variable-length.
510  *
511  * NOTE: we are assuming that non-variable-length fields in the system
512  *               catalogs will always be defined!
513  *
514  * Returns 1L if a tuple was found, 0L if not.
515  */
516 int32
517 SearchSysCacheStruct(int cacheId,               /* cache selection code */
518                                          char *returnStruct,            /* (preallocated!) */
519                                          Datum key1,
520                                          Datum key2,
521                                          Datum key3,
522                                          Datum key4)
523 {
524         HeapTuple       tp;
525
526         if (!PointerIsValid(returnStruct))
527         {
528                 elog(ERROR, "SearchSysCacheStruct: No receiving struct");
529                 return 0;
530         }
531         tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
532         if (!HeapTupleIsValid(tp))
533                 return 0;
534         memcpy(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size);
535         return 1;
536 }
537
538
539 /*
540  * SearchSysCacheGetAttribute
541  *        Returns the attribute corresponding to 'attributeNumber' for
542  *        a given cached tuple.  This routine usually needs to be used for
543  *        attributes that might be NULL or might be at a variable offset
544  *        in the tuple.
545  *
546  * XXX This re-opens the relation, so this is slower than just pulling
547  * fixed-location fields out of the struct returned by SearchSysCacheTuple.
548  *
549  * [callers all assume this returns a (struct varlena *). -ay 10/94]
550  */
551 void *
552 SearchSysCacheGetAttribute(int cacheId,
553                                                    AttrNumber attributeNumber,
554                                                    Datum key1,
555                                                    Datum key2,
556                                                    Datum key3,
557                                                    Datum key4)
558 {
559         HeapTuple       tp;
560         char       *cacheName;
561         Relation        relation;
562         int32           attributeLength,
563                                 attributeByValue;
564         bool            isNull;
565         Datum           attributeValue;
566         void       *returnValue;
567
568         tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
569         cacheName = cacheinfo[cacheId].name;
570
571         if (!HeapTupleIsValid(tp))
572         {
573 #ifdef  CACHEDEBUG
574                 elog(DEBUG,
575                          "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
576                          cacheName, cacheId);
577 #endif   /* defined(CACHEDEBUG) */
578                 return NULL;
579         }
580
581         relation = heap_openr(cacheName);
582
583         if (attributeNumber < 0 &&
584                 attributeNumber > FirstLowInvalidHeapAttributeNumber)
585         {
586                 attributeLength = heap_sysattrlen(attributeNumber);
587                 attributeByValue = heap_sysattrbyval(attributeNumber);
588         }
589         else if (attributeNumber > 0 &&
590                          attributeNumber <= relation->rd_rel->relnatts)
591         {
592                 attributeLength = relation->rd_att->attrs[attributeNumber - 1]->attlen;
593                 attributeByValue = relation->rd_att->attrs[attributeNumber - 1]->attbyval;
594         }
595         else
596         {
597                 elog(ERROR,
598                          "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
599                          attributeNumber, cacheName, cacheId);
600                 return NULL;
601         }
602
603         attributeValue = heap_getattr(tp,
604                                                                   attributeNumber,
605                                                                   RelationGetDescr(relation),
606                                                                   &isNull);
607
608         if (isNull)
609         {
610
611                 /*
612                  * Used to be an elog(DEBUG, ...) here and a claim that it should
613                  * be a FATAL error, I don't think either is warranted -mer 6/9/92
614                  */
615                 return NULL;
616         }
617
618         if (attributeByValue)
619                 returnValue = (void *) attributeValue;
620         else
621         {
622                 char       *tmp;
623                 int                     size = (attributeLength < 0)
624                 ? VARSIZE((struct varlena *) attributeValue)    /* variable length */
625                 : attributeLength;              /* fixed length */
626
627                 tmp = (char *) palloc(size);
628                 memcpy(tmp, (void *) attributeValue, size);
629                 returnValue = (void *) tmp;
630         }
631
632         heap_close(relation);
633         return returnValue;
634 }
635
636 /*
637  * TypeDefaultRetrieve
638  *
639  *        Given a type OID, return the typdefault field associated with that
640  *        type.  The result is a Datum, and points to palloc'd storage for
641  *        non-pass-by-value types.
642  *
643  * [identical to get_typdefault, expecting a (struct varlena *) as ret val.
644  *      some day, either of the functions should be removed              -ay 10/94]
645  */
646 void *
647 TypeDefaultRetrieve(Oid typId)
648 {
649         struct varlena *typDefault;
650         int32           dataSize;
651         HeapTuple       typeTuple;
652         Form_pg_type type;
653         int32           typByVal,
654                                 typLen;
655         void       *returnValue;
656
657         /*
658          * First, see if there is a non-null typdefault field (usually there isn't)
659          */
660         typDefault = (struct varlena *)
661                 SearchSysCacheGetAttribute(TYPOID,
662                                                                    Anum_pg_type_typdefault,
663                                                                    ObjectIdGetDatum(typId),
664                                                                    0, 0, 0);
665
666         if (typDefault == NULL)
667         {
668 #ifdef  CACHEDEBUG
669                 elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)",
670                          cacheinfo[TYPOID].name, TYPOID);
671 #endif   /* defined(CACHEDEBUG) */
672                 return NULL;
673         }
674
675         dataSize = VARSIZE(typDefault) - VARHDRSZ;
676
677         /*
678          * Need the type's length and byVal fields.
679          *
680          * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
681          * just did --- but at present this path isn't taken often enough to
682          * make it worth fixing.
683          */
684         typeTuple = SearchSysCacheTuple(TYPOID,
685                                                                         ObjectIdGetDatum(typId),
686                                                                         0, 0, 0);
687
688         if (!HeapTupleIsValid(typeTuple))
689         {
690                 /* should never get here, really... */
691 #ifdef  CACHEDEBUG
692                 elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
693                          cacheinfo[TYPOID].name, TYPOID);
694 #endif   /* defined(CACHEDEBUG) */
695                 return NULL;
696         }
697
698         type = (Form_pg_type) GETSTRUCT(typeTuple);
699         typLen = type->typlen;
700         typByVal = type->typbyval;
701
702         if (typByVal)
703         {
704                 int8            i8;
705                 int16           i16;
706                 int32           i32 = 0;
707
708                 if (dataSize == typLen)
709                 {
710                         switch (typLen)
711                         {
712                                 case sizeof(int8):
713                                         memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
714                                         i32 = i8;
715                                         break;
716                                 case sizeof(int16):
717                                         memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
718                                         i32 = i16;
719                                         break;
720                                 case sizeof(int32):
721                                         memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
722                                         break;
723                         }
724                         returnValue = (void *) i32;
725                 }
726                 else
727                         returnValue = NULL;
728         }
729         else
730         {
731                 if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
732                         returnValue = NULL;
733                 else
734                 {
735                         returnValue = (void *) palloc(VARSIZE(typDefault));
736                         memcpy((char *) returnValue,
737                                    (char *) typDefault,
738                                    (int) VARSIZE(typDefault));
739                 }
740         }
741
742         return returnValue;
743 }