OSDN Git Service

Clean up handling of variable-free qual clauses. System now does the
[pg-rex/syncrep.git] / src / backend / utils / cache / lsyscache.c
1 /*-------------------------------------------------------------------------
2  *
3  * lsyscache.c
4  *        Convenience routines for common queries in the system catalog cache.
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.45 2000/08/13 02:50:16 tgl Exp $
11  *
12  * NOTES
13  *        Eventually, the index information should go through here, too.
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17
18 #include "catalog/pg_operator.h"
19 #include "catalog/pg_proc.h"
20 #include "catalog/pg_type.h"
21 #include "utils/lsyscache.h"
22 #include "utils/syscache.h"
23
24 /*                              ---------- AMOP CACHES ----------                                                */
25
26 /*
27  * op_class
28  *
29  *              Return t iff operator 'opno' is in operator class 'opclass' for
30  *              access method 'amopid'.
31  */
32 bool
33 op_class(Oid opno, Oid opclass, Oid amopid)
34 {
35         if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID,
36                                                                                          ObjectIdGetDatum(opclass),
37                                                                                          ObjectIdGetDatum(opno),
38                                                                                          ObjectIdGetDatum(amopid),
39                                                                                          0)))
40                 return true;
41         else
42                 return false;
43 }
44
45 /*                              ---------- ATTRIBUTE CACHES ----------                                   */
46
47 /*
48  * get_attname
49  *
50  *              Given the relation id and the attribute number,
51  *              return the "attname" field from the attribute relation.
52  */
53 char *
54 get_attname(Oid relid, AttrNumber attnum)
55 {
56         HeapTuple       tp;
57
58         tp = SearchSysCacheTuple(ATTNUM,
59                                                          ObjectIdGetDatum(relid),
60                                                          Int16GetDatum(attnum),
61                                                          0, 0);
62         if (HeapTupleIsValid(tp))
63         {
64                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
65
66                 return pstrdup(NameStr(att_tup->attname));
67         }
68         else
69                 return NULL;
70 }
71
72 /*
73  * get_attnum
74  *
75  *              Given the relation id and the attribute name,
76  *              return the "attnum" field from the attribute relation.
77  */
78 AttrNumber
79 get_attnum(Oid relid, char *attname)
80 {
81         HeapTuple       tp;
82
83         tp = SearchSysCacheTuple(ATTNAME,
84                                                          ObjectIdGetDatum(relid),
85                                                          PointerGetDatum(attname),
86                                                          0, 0);
87         if (HeapTupleIsValid(tp))
88         {
89                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
90
91                 return att_tup->attnum;
92         }
93         else
94                 return InvalidAttrNumber;
95 }
96
97 /*
98  * get_atttype
99  *
100  *              Given the relation OID and the attribute number with the relation,
101  *              return the attribute type OID.
102  */
103 Oid
104 get_atttype(Oid relid, AttrNumber attnum)
105 {
106         HeapTuple       tp;
107
108         tp = SearchSysCacheTuple(ATTNUM,
109                                                          ObjectIdGetDatum(relid),
110                                                          Int16GetDatum(attnum),
111                                                          0, 0);
112         if (HeapTupleIsValid(tp))
113         {
114                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
115
116                 return att_tup->atttypid;
117         }
118         else
119                 return InvalidOid;
120 }
121
122 /* This routine uses the attname instead of the attnum because it
123  * replaces the routine find_atttype, which is called sometimes when
124  * only the attname, not the attno, is available.
125  */
126 bool
127 get_attisset(Oid relid, char *attname)
128 {
129         HeapTuple       tp;
130
131         tp = SearchSysCacheTuple(ATTNAME,
132                                                          ObjectIdGetDatum(relid),
133                                                          PointerGetDatum(attname),
134                                                          0, 0);
135         if (HeapTupleIsValid(tp))
136         {
137                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
138
139                 return att_tup->attisset;
140         }
141         else
142                 return false;
143 }
144
145 /*
146  * get_atttypmod
147  *
148  *              Given the relation id and the attribute number,
149  *              return the "atttypmod" field from the attribute relation.
150  */
151 int32
152 get_atttypmod(Oid relid, AttrNumber attnum)
153 {
154         HeapTuple       tp;
155
156         tp = SearchSysCacheTuple(ATTNUM,
157                                                          ObjectIdGetDatum(relid),
158                                                          Int16GetDatum(attnum),
159                                                          0, 0);
160         if (HeapTupleIsValid(tp))
161         {
162                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
163
164                 return att_tup->atttypmod;
165         }
166         else
167                 return -1;
168 }
169
170 /*
171  * get_attdisbursion
172  *
173  *        Retrieve the disbursion statistic for an attribute,
174  *        or produce an estimate if no info is available.
175  *
176  * min_estimate is the minimum estimate to return if insufficient data
177  * is available to produce a reliable value.  This value may vary
178  * depending on context.  (For example, when deciding whether it is
179  * safe to use a hashjoin, we want to be more conservative than when
180  * estimating the number of tuples produced by an equijoin.)
181  */
182 double
183 get_attdisbursion(Oid relid, AttrNumber attnum, double min_estimate)
184 {
185         HeapTuple       atp;
186         Form_pg_attribute att_tup;
187         double          disbursion;
188         int32           ntuples;
189
190         atp = SearchSysCacheTuple(ATTNUM,
191                                                           ObjectIdGetDatum(relid),
192                                                           Int16GetDatum(attnum),
193                                                           0, 0);
194         if (!HeapTupleIsValid(atp))
195         {
196                 /* this should not happen */
197                 elog(ERROR, "get_attdisbursion: no attribute tuple %u %d",
198                          relid, attnum);
199                 return min_estimate;
200         }
201         att_tup = (Form_pg_attribute) GETSTRUCT(atp);
202
203         disbursion = att_tup->attdisbursion;
204         if (disbursion > 0.0)
205                 return disbursion;              /* we have a specific estimate from VACUUM */
206
207         /*
208          * Special-case boolean columns: the disbursion of a boolean is highly
209          * unlikely to be anywhere near 1/numtuples, instead it's probably
210          * more like 0.5.
211          *
212          * Are there any other cases we should wire in special estimates for?
213          */
214         if (att_tup->atttypid == BOOLOID)
215                 return 0.5;
216
217         /*
218          * Disbursion is either 0 (no data available) or -1 (disbursion is
219          * 1/numtuples).  Either way, we need the relation size.
220          */
221
222         atp = SearchSysCacheTuple(RELOID,
223                                                           ObjectIdGetDatum(relid),
224                                                           0, 0, 0);
225         if (!HeapTupleIsValid(atp))
226         {
227                 /* this should not happen */
228                 elog(ERROR, "get_attdisbursion: no relation tuple %u", relid);
229                 return min_estimate;
230         }
231
232         ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
233
234         if (ntuples == 0)
235                 return min_estimate;    /* no data available */
236
237         if (disbursion < 0.0)           /* VACUUM thinks there are no duplicates */
238                 return 1.0 / (double) ntuples;
239
240         /*
241          * VACUUM ANALYZE does not compute disbursion for system attributes,
242          * but some of them can reasonably be assumed unique anyway.
243          */
244         if (attnum == ObjectIdAttributeNumber ||
245                 attnum == SelfItemPointerAttributeNumber)
246                 return 1.0 / (double) ntuples;
247         if (attnum == TableOidAttributeNumber)
248                 return 1.0;
249
250         /*
251          * VACUUM ANALYZE has not been run for this table. Produce an estimate
252          * = 1/numtuples.  This may produce unreasonably small estimates for
253          * large tables, so limit the estimate to no less than min_estimate.
254          */
255         disbursion = 1.0 / (double) ntuples;
256         if (disbursion < min_estimate)
257                 disbursion = min_estimate;
258
259         return disbursion;
260 }
261
262 /*                              ---------- INDEX CACHE ----------                                                */
263
264 /*              watch this space...
265  */
266
267 /*                              ---------- OPERATOR CACHE ----------                                     */
268
269 /*
270  * get_opcode
271  *
272  *              Returns the regproc id of the routine used to implement an
273  *              operator given the operator oid.
274  */
275 RegProcedure
276 get_opcode(Oid opno)
277 {
278         HeapTuple       tp;
279
280         tp = SearchSysCacheTuple(OPEROID,
281                                                          ObjectIdGetDatum(opno),
282                                                          0, 0, 0);
283         if (HeapTupleIsValid(tp))
284         {
285                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
286
287                 return optup->oprcode;
288         }
289         else
290                 return (RegProcedure) InvalidOid;
291 }
292
293 /*
294  * get_opname
295  *        returns the name of the operator with the given opno
296  *
297  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
298  */
299 char *
300 get_opname(Oid opno)
301 {
302         HeapTuple       tp;
303
304         tp = SearchSysCacheTuple(OPEROID,
305                                                          ObjectIdGetDatum(opno),
306                                                          0, 0, 0);
307         if (HeapTupleIsValid(tp))
308         {
309                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
310
311                 return pstrdup(NameStr(optup->oprname));
312         }
313         else
314                 return NULL;
315 }
316
317 /*
318  * op_mergejoinable
319  *
320  *              Returns the left and right sort operators and types corresponding to a
321  *              mergejoinable operator, or nil if the operator is not mergejoinable.
322  */
323 bool
324 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
325 {
326         HeapTuple       tp;
327
328         tp = SearchSysCacheTuple(OPEROID,
329                                                          ObjectIdGetDatum(opno),
330                                                          0, 0, 0);
331         if (HeapTupleIsValid(tp))
332         {
333                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
334
335                 if (optup->oprlsortop &&
336                         optup->oprrsortop &&
337                         optup->oprleft == ltype &&
338                         optup->oprright == rtype)
339                 {
340                         *leftOp = optup->oprlsortop;
341                         *rightOp = optup->oprrsortop;
342                         return true;
343                 }
344         }
345         return false;
346 }
347
348 /*
349  * op_hashjoinable
350  *
351  * Returns the hash operator corresponding to a hashjoinable operator,
352  * or InvalidOid if the operator is not hashjoinable.
353  */
354 Oid
355 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
356 {
357         HeapTuple       tp;
358
359         tp = SearchSysCacheTuple(OPEROID,
360                                                          ObjectIdGetDatum(opno),
361                                                          0, 0, 0);
362         if (HeapTupleIsValid(tp))
363         {
364                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
365
366                 if (optup->oprcanhash &&
367                         optup->oprleft == ltype &&
368                         optup->oprright == rtype)
369                         return opno;
370         }
371         return InvalidOid;
372 }
373
374 /*
375  * op_iscachable
376  *
377  * Get the proiscachable flag for the operator's underlying function.
378  */
379 bool
380 op_iscachable(Oid opno)
381 {
382         RegProcedure    funcid = get_opcode(opno);
383
384         if (funcid == (RegProcedure) InvalidOid)
385                 elog(ERROR, "Operator OID %u does not exist", opno);
386
387         return func_iscachable((Oid) funcid);
388 }
389
390 HeapTuple
391 get_operator_tuple(Oid opno)
392 {
393         return SearchSysCacheTuple(OPEROID,
394                                                            ObjectIdGetDatum(opno),
395                                                            0, 0, 0);
396 }
397
398 /*
399  * get_commutator
400  *
401  *              Returns the corresponding commutator of an operator.
402  */
403 Oid
404 get_commutator(Oid opno)
405 {
406         HeapTuple       tp;
407
408         tp = SearchSysCacheTuple(OPEROID,
409                                                          ObjectIdGetDatum(opno),
410                                                          0, 0, 0);
411         if (HeapTupleIsValid(tp))
412         {
413                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
414
415                 return optup->oprcom;
416         }
417         else
418                 return InvalidOid;
419 }
420
421 /*
422  * get_negator
423  *
424  *              Returns the corresponding negator of an operator.
425  */
426 Oid
427 get_negator(Oid opno)
428 {
429         HeapTuple       tp;
430
431         tp = SearchSysCacheTuple(OPEROID,
432                                                          ObjectIdGetDatum(opno),
433                                                          0, 0, 0);
434         if (HeapTupleIsValid(tp))
435         {
436                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
437
438                 return optup->oprnegate;
439         }
440         else
441                 return InvalidOid;
442 }
443
444 /*
445  * get_oprrest
446  *
447  *              Returns procedure id for computing selectivity of an operator.
448  */
449 RegProcedure
450 get_oprrest(Oid opno)
451 {
452         HeapTuple       tp;
453
454         tp = SearchSysCacheTuple(OPEROID,
455                                                          ObjectIdGetDatum(opno),
456                                                          0, 0, 0);
457         if (HeapTupleIsValid(tp))
458         {
459                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
460
461                 return optup->oprrest;
462         }
463         else
464                 return (RegProcedure) InvalidOid;
465 }
466
467 /*
468  * get_oprjoin
469  *
470  *              Returns procedure id for computing selectivity of a join.
471  */
472 RegProcedure
473 get_oprjoin(Oid opno)
474 {
475         HeapTuple       tp;
476
477         tp = SearchSysCacheTuple(OPEROID,
478                                                          ObjectIdGetDatum(opno),
479                                                          0, 0, 0);
480         if (HeapTupleIsValid(tp))
481         {
482                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
483
484                 return optup->oprjoin;
485         }
486         else
487                 return (RegProcedure) InvalidOid;
488 }
489
490 /*                              ---------- FUNCTION CACHE ----------                                     */
491
492 /*
493  * get_func_rettype
494  *              Given procedure id, return the function's result type.
495  */
496 Oid
497 get_func_rettype(Oid funcid)
498 {
499         HeapTuple       func_tuple;
500
501         func_tuple = SearchSysCacheTuple(PROCOID,
502                                                                          ObjectIdGetDatum(funcid),
503                                                                          0, 0, 0);
504         if (!HeapTupleIsValid(func_tuple))
505                 elog(ERROR, "Function OID %u does not exist", funcid);
506
507         return ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
508 }
509
510 /*
511  * func_iscachable
512  *              Given procedure id, return the function's proiscachable flag.
513  */
514 bool
515 func_iscachable(Oid funcid)
516 {
517         HeapTuple       func_tuple;
518
519         func_tuple = SearchSysCacheTuple(PROCOID,
520                                                                          ObjectIdGetDatum(funcid),
521                                                                          0, 0, 0);
522         if (!HeapTupleIsValid(func_tuple))
523                 elog(ERROR, "Function OID %u does not exist", funcid);
524
525         return ((Form_pg_proc) GETSTRUCT(func_tuple))->proiscachable;
526 }
527
528 /*                              ---------- RELATION CACHE ----------                                     */
529
530 #ifdef NOT_USED
531 /*
532  * get_relnatts
533  *
534  *              Returns the number of attributes for a given relation.
535  */
536 int
537 get_relnatts(Oid relid)
538 {
539         HeapTuple       tp;
540
541         tp = SearchSysCacheTuple(RELOID,
542                                                          ObjectIdGetDatum(relid),
543                                                          0, 0, 0);
544         if (HeapTupleIsValid(tp))
545         {
546                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
547
548                 return reltup->relnatts;
549         }
550         else
551                 return InvalidAttrNumber;
552 }
553 #endif
554
555 /*
556  * get_rel_name
557  *
558  *              Returns the name of a given relation.
559  */
560 char *
561 get_rel_name(Oid relid)
562 {
563         HeapTuple       tp;
564
565         tp = SearchSysCacheTuple(RELOID,
566                                                          ObjectIdGetDatum(relid),
567                                                          0, 0, 0);
568         if (HeapTupleIsValid(tp))
569         {
570                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
571
572                 return pstrdup(NameStr(reltup->relname));
573         }
574         else
575                 return NULL;
576 }
577
578 /*                              ---------- TYPE CACHE ----------                                                 */
579
580 /*
581  * get_typlen
582  *
583  *              Given the type OID, return the length of the type.
584  */
585 int16
586 get_typlen(Oid typid)
587 {
588         HeapTuple       tp;
589
590         tp = SearchSysCacheTuple(TYPEOID,
591                                                          ObjectIdGetDatum(typid),
592                                                          0, 0, 0);
593         if (HeapTupleIsValid(tp))
594         {
595                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
596
597                 return typtup->typlen;
598         }
599         else
600                 return 0;
601 }
602
603 /*
604  * get_typbyval
605  *
606  *              Given the type OID, determine whether the type is returned by value or
607  *              not.  Returns true if by value, false if by reference.
608  */
609 bool
610 get_typbyval(Oid typid)
611 {
612         HeapTuple       tp;
613
614         tp = SearchSysCacheTuple(TYPEOID,
615                                                          ObjectIdGetDatum(typid),
616                                                          0, 0, 0);
617         if (HeapTupleIsValid(tp))
618         {
619                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
620
621                 return typtup->typbyval;
622         }
623         else
624                 return false;
625 }
626
627 #ifdef NOT_USED
628 char
629 get_typalign(Oid typid)
630 {
631         HeapTuple       tp;
632
633         tp = SearchSysCacheTuple(TYPEOID,
634                                                          ObjectIdGetDatum(typid),
635                                                          0, 0, 0);
636         if (HeapTupleIsValid(tp))
637         {
638                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
639
640                 return typtup->typalign;
641         }
642         else
643                 return 'i';
644 }
645
646 #endif
647
648 /*
649  * get_typdefault
650  *
651  *        Given a type OID, return the typdefault field associated with that
652  *        type, or Datum(NULL) if there is no typdefault.  (This implies
653  *        that pass-by-value types can't have a default value that has
654  *        a representation of zero.  Not worth fixing now.)
655  *        The result points to palloc'd storage for non-pass-by-value types.
656  */
657 Datum
658 get_typdefault(Oid typid)
659 {
660         HeapTuple       typeTuple;
661         Form_pg_type type;
662         struct varlena *typDefault;
663         bool            isNull;
664         int32           dataSize;
665         int32           typLen;
666         bool            typByVal;
667         Datum           returnValue;
668
669         typeTuple = SearchSysCacheTuple(TYPEOID,
670                                                                         ObjectIdGetDatum(typid),
671                                                                         0, 0, 0);
672
673         if (!HeapTupleIsValid(typeTuple))
674                 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
675
676         type = (Form_pg_type) GETSTRUCT(typeTuple);
677
678         /*
679          * First, see if there is a non-null typdefault field (usually there
680          * isn't)
681          */
682         typDefault = (struct varlena *) SysCacheGetAttr(TYPEOID,
683                                                                                                         typeTuple,
684                                                                                                  Anum_pg_type_typdefault,
685                                                                                                         &isNull);
686
687         if (isNull)
688                 return PointerGetDatum(NULL);
689
690         /*
691          * Otherwise, extract/copy the value.
692          */
693         dataSize = VARSIZE(typDefault) - VARHDRSZ;
694         typLen = type->typlen;
695         typByVal = type->typbyval;
696
697         if (typByVal)
698         {
699                 int8            i8;
700                 int16           i16;
701                 int32           i32 = 0;
702
703                 if (dataSize == typLen)
704                 {
705                         switch (typLen)
706                         {
707                                 case sizeof(int8):
708                                         memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
709                                         i32 = i8;
710                                         break;
711                                 case sizeof(int16):
712                                         memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
713                                         i32 = i16;
714                                         break;
715                                 case sizeof(int32):
716                                         memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
717                                         break;
718                         }
719                         returnValue = Int32GetDatum(i32);
720                 }
721                 else
722                         returnValue = PointerGetDatum(NULL);
723         }
724         else if (typLen < 0)
725         {
726                 /* variable-size type */
727                 if (dataSize < 0)
728                         returnValue = PointerGetDatum(NULL);
729                 else
730                 {
731                         returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
732                         memcpy((char *) DatumGetPointer(returnValue),
733                                    (char *) typDefault,
734                                    (int) VARSIZE(typDefault));
735                 }
736         }
737         else
738         {
739                 /* fixed-size pass-by-ref type */
740                 if (dataSize != typLen)
741                         returnValue = PointerGetDatum(NULL);
742                 else
743                 {
744                         returnValue = PointerGetDatum(palloc(dataSize));
745                         memcpy((char *) DatumGetPointer(returnValue),
746                                    VARDATA(typDefault),
747                                    (int) dataSize);
748                 }
749         }
750
751         return returnValue;
752 }
753
754 /*
755  * get_typtype
756  *
757  *              Given the type OID, find if it is a basic type, a named relation
758  *              or the generic type 'relation'.
759  *              It returns the null char if the cache lookup fails...
760  */
761 #ifdef NOT_USED
762 char
763 get_typtype(Oid typid)
764 {
765         HeapTuple       tp;
766
767         tp = SearchSysCacheTuple(TYPEOID,
768                                                          ObjectIdGetDatum(typid),
769                                                          0, 0, 0);
770         if (HeapTupleIsValid(tp))
771         {
772                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
773
774                 return typtup->typtype;
775         }
776         else
777                 return '\0';
778 }
779
780 #endif