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