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