1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.44 2000/07/23 03:50:26 tgl Exp $
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
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"
24 /* ---------- AMOP CACHES ---------- */
29 * Return t iff operator 'opid' is in operator class 'opclass' for
30 * access method 'amopid'.
33 op_class(Oid opid, Oid opclass, Oid amopid)
35 if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID,
36 ObjectIdGetDatum(opclass),
37 ObjectIdGetDatum(opid),
38 ObjectIdGetDatum(amopid),
45 /* ---------- ATTRIBUTE CACHES ---------- */
50 * Given the relation id and the attribute number,
51 * return the "attname" field from the attribute relation.
54 get_attname(Oid relid, AttrNumber attnum)
58 tp = SearchSysCacheTuple(ATTNUM,
59 ObjectIdGetDatum(relid),
60 Int16GetDatum(attnum),
62 if (HeapTupleIsValid(tp))
64 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
66 return pstrdup(NameStr(att_tup->attname));
75 * Given the relation id and the attribute name,
76 * return the "attnum" field from the attribute relation.
79 get_attnum(Oid relid, char *attname)
83 tp = SearchSysCacheTuple(ATTNAME,
84 ObjectIdGetDatum(relid),
85 PointerGetDatum(attname),
87 if (HeapTupleIsValid(tp))
89 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
91 return att_tup->attnum;
94 return InvalidAttrNumber;
100 * Given the relation OID and the attribute number with the relation,
101 * return the attribute type OID.
104 get_atttype(Oid relid, AttrNumber attnum)
108 tp = SearchSysCacheTuple(ATTNUM,
109 ObjectIdGetDatum(relid),
110 Int16GetDatum(attnum),
112 if (HeapTupleIsValid(tp))
114 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
116 return att_tup->atttypid;
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.
127 get_attisset(Oid relid, char *attname)
131 tp = SearchSysCacheTuple(ATTNAME,
132 ObjectIdGetDatum(relid),
133 PointerGetDatum(attname),
135 if (HeapTupleIsValid(tp))
137 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
139 return att_tup->attisset;
148 * Given the relation id and the attribute number,
149 * return the "atttypmod" field from the attribute relation.
152 get_atttypmod(Oid relid, AttrNumber attnum)
156 tp = SearchSysCacheTuple(ATTNUM,
157 ObjectIdGetDatum(relid),
158 Int16GetDatum(attnum),
160 if (HeapTupleIsValid(tp))
162 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
164 return att_tup->atttypmod;
173 * Retrieve the disbursion statistic for an attribute,
174 * or produce an estimate if no info is available.
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.)
183 get_attdisbursion(Oid relid, AttrNumber attnum, double min_estimate)
186 Form_pg_attribute att_tup;
190 atp = SearchSysCacheTuple(ATTNUM,
191 ObjectIdGetDatum(relid),
192 Int16GetDatum(attnum),
194 if (!HeapTupleIsValid(atp))
196 /* this should not happen */
197 elog(ERROR, "get_attdisbursion: no attribute tuple %u %d",
201 att_tup = (Form_pg_attribute) GETSTRUCT(atp);
203 disbursion = att_tup->attdisbursion;
204 if (disbursion > 0.0)
205 return disbursion; /* we have a specific estimate from VACUUM */
208 * Special-case boolean columns: the disbursion of a boolean is highly
209 * unlikely to be anywhere near 1/numtuples, instead it's probably
212 * Are there any other cases we should wire in special estimates for?
214 if (att_tup->atttypid == BOOLOID)
218 * Disbursion is either 0 (no data available) or -1 (disbursion is
219 * 1/numtuples). Either way, we need the relation size.
222 atp = SearchSysCacheTuple(RELOID,
223 ObjectIdGetDatum(relid),
225 if (!HeapTupleIsValid(atp))
227 /* this should not happen */
228 elog(ERROR, "get_attdisbursion: no relation tuple %u", relid);
232 ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
235 return min_estimate; /* no data available */
237 if (disbursion < 0.0) /* VACUUM thinks there are no duplicates */
238 return 1.0 / (double) ntuples;
241 * VACUUM ANALYZE does not compute disbursion for system attributes,
242 * but some of them can reasonably be assumed unique anyway.
244 if (attnum == ObjectIdAttributeNumber ||
245 attnum == SelfItemPointerAttributeNumber)
246 return 1.0 / (double) ntuples;
247 if (attnum == TableOidAttributeNumber)
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.
255 disbursion = 1.0 / (double) ntuples;
256 if (disbursion < min_estimate)
257 disbursion = min_estimate;
262 /* ---------- INDEX CACHE ---------- */
264 /* watch this space...
267 /* ---------- OPERATOR CACHE ---------- */
272 * Returns the regproc id of the routine used to implement an
273 * operator given the operator oid.
280 tp = SearchSysCacheTuple(OPEROID,
281 ObjectIdGetDatum(opno),
283 if (HeapTupleIsValid(tp))
285 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
287 return optup->oprcode;
290 return (RegProcedure) NULL;
295 * returns the name of the operator with the given opno
297 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
304 tp = SearchSysCacheTuple(OPEROID,
305 ObjectIdGetDatum(opno),
307 if (HeapTupleIsValid(tp))
309 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
311 return pstrdup(NameStr(optup->oprname));
320 * Returns the left and right sort operators and types corresponding to a
321 * mergejoinable operator, or nil if the operator is not mergejoinable.
324 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
328 tp = SearchSysCacheTuple(OPEROID,
329 ObjectIdGetDatum(opno),
331 if (HeapTupleIsValid(tp))
333 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
335 if (optup->oprlsortop &&
337 optup->oprleft == ltype &&
338 optup->oprright == rtype)
340 *leftOp = optup->oprlsortop;
341 *rightOp = optup->oprrsortop;
351 * Returns the hash operator corresponding to a hashjoinable operator,
352 * or InvalidOid if the operator is not hashjoinable.
355 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
359 tp = SearchSysCacheTuple(OPEROID,
360 ObjectIdGetDatum(opno),
362 if (HeapTupleIsValid(tp))
364 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
366 if (optup->oprcanhash &&
367 optup->oprleft == ltype &&
368 optup->oprright == rtype)
375 get_operator_tuple(Oid opno)
379 if ((optup = SearchSysCacheTuple(OPEROID,
380 ObjectIdGetDatum(opno),
384 return (HeapTuple) NULL;
390 * Returns the corresponding commutator of an operator.
393 get_commutator(Oid opno)
397 tp = SearchSysCacheTuple(OPEROID,
398 ObjectIdGetDatum(opno),
400 if (HeapTupleIsValid(tp))
402 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
404 return optup->oprcom;
413 * Returns the corresponding negator of an operator.
416 get_negator(Oid opno)
420 tp = SearchSysCacheTuple(OPEROID,
421 ObjectIdGetDatum(opno),
423 if (HeapTupleIsValid(tp))
425 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
427 return optup->oprnegate;
436 * Returns procedure id for computing selectivity of an operator.
439 get_oprrest(Oid opno)
443 tp = SearchSysCacheTuple(OPEROID,
444 ObjectIdGetDatum(opno),
446 if (HeapTupleIsValid(tp))
448 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
450 return optup->oprrest;
453 return (RegProcedure) NULL;
459 * Returns procedure id for computing selectivity of a join.
462 get_oprjoin(Oid opno)
466 tp = SearchSysCacheTuple(OPEROID,
467 ObjectIdGetDatum(opno),
469 if (HeapTupleIsValid(tp))
471 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
473 return optup->oprjoin;
476 return (RegProcedure) NULL;
479 /* ---------- FUNCTION CACHE ---------- */
483 * Given procedure id, return the function's result type.
486 get_func_rettype(Oid funcid)
488 HeapTuple func_tuple;
490 func_tuple = SearchSysCacheTuple(PROCOID,
491 ObjectIdGetDatum(funcid),
493 if (!HeapTupleIsValid(func_tuple))
494 elog(ERROR, "Function OID %u does not exist", funcid);
496 return ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
499 /* ---------- RELATION CACHE ---------- */
505 * Returns the number of attributes for a given relation.
508 get_relnatts(Oid relid)
512 tp = SearchSysCacheTuple(RELOID,
513 ObjectIdGetDatum(relid),
515 if (HeapTupleIsValid(tp))
517 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
519 return reltup->relnatts;
522 return InvalidAttrNumber;
529 * Returns the name of a given relation.
532 get_rel_name(Oid relid)
536 tp = SearchSysCacheTuple(RELOID,
537 ObjectIdGetDatum(relid),
539 if (HeapTupleIsValid(tp))
541 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
543 return pstrdup(NameStr(reltup->relname));
549 /* ---------- TYPE CACHE ---------- */
554 * Given the type OID, return the length of the type.
557 get_typlen(Oid typid)
561 tp = SearchSysCacheTuple(TYPEOID,
562 ObjectIdGetDatum(typid),
564 if (HeapTupleIsValid(tp))
566 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
568 return typtup->typlen;
577 * Given the type OID, determine whether the type is returned by value or
578 * not. Returns true if by value, false if by reference.
581 get_typbyval(Oid typid)
585 tp = SearchSysCacheTuple(TYPEOID,
586 ObjectIdGetDatum(typid),
588 if (HeapTupleIsValid(tp))
590 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
592 return typtup->typbyval;
600 get_typalign(Oid typid)
604 tp = SearchSysCacheTuple(TYPEOID,
605 ObjectIdGetDatum(typid),
607 if (HeapTupleIsValid(tp))
609 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
611 return typtup->typalign;
622 * Given a type OID, return the typdefault field associated with that
623 * type, or Datum(NULL) if there is no typdefault. (This implies
624 * that pass-by-value types can't have a default value that has
625 * a representation of zero. Not worth fixing now.)
626 * The result points to palloc'd storage for non-pass-by-value types.
629 get_typdefault(Oid typid)
633 struct varlena *typDefault;
640 typeTuple = SearchSysCacheTuple(TYPEOID,
641 ObjectIdGetDatum(typid),
644 if (!HeapTupleIsValid(typeTuple))
645 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
647 type = (Form_pg_type) GETSTRUCT(typeTuple);
650 * First, see if there is a non-null typdefault field (usually there
653 typDefault = (struct varlena *) SysCacheGetAttr(TYPEOID,
655 Anum_pg_type_typdefault,
659 return PointerGetDatum(NULL);
662 * Otherwise, extract/copy the value.
664 dataSize = VARSIZE(typDefault) - VARHDRSZ;
665 typLen = type->typlen;
666 typByVal = type->typbyval;
674 if (dataSize == typLen)
679 memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
683 memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
687 memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
690 returnValue = Int32GetDatum(i32);
693 returnValue = PointerGetDatum(NULL);
697 /* variable-size type */
699 returnValue = PointerGetDatum(NULL);
702 returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
703 memcpy((char *) DatumGetPointer(returnValue),
705 (int) VARSIZE(typDefault));
710 /* fixed-size pass-by-ref type */
711 if (dataSize != typLen)
712 returnValue = PointerGetDatum(NULL);
715 returnValue = PointerGetDatum(palloc(dataSize));
716 memcpy((char *) DatumGetPointer(returnValue),
728 * Given the type OID, find if it is a basic type, a named relation
729 * or the generic type 'relation'.
730 * It returns the null char if the cache lookup fails...
734 get_typtype(Oid typid)
738 tp = SearchSysCacheTuple(TYPEOID,
739 ObjectIdGetDatum(typid),
741 if (HeapTupleIsValid(tp))
743 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
745 return typtup->typtype;