1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.52 2001/03/23 04:49:55 momjian Exp $
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
18 #include "access/tupmacs.h"
19 #include "catalog/pg_operator.h"
20 #include "catalog/pg_proc.h"
21 #include "catalog/pg_type.h"
22 #include "utils/lsyscache.h"
23 #include "utils/syscache.h"
25 /* ---------- AMOP CACHES ---------- */
30 * Return t iff operator 'opno' is in operator class 'opclass' for
31 * access method 'amopid'.
34 op_class(Oid opno, Oid opclass, Oid amopid)
36 return SearchSysCacheExists(AMOPOPID,
37 ObjectIdGetDatum(opclass),
38 ObjectIdGetDatum(opno),
39 ObjectIdGetDatum(amopid),
43 /* ---------- ATTRIBUTE CACHES ---------- */
48 * Given the relation id and the attribute number,
49 * return the "attname" field from the attribute relation.
51 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
54 get_attname(Oid relid, AttrNumber attnum)
58 tp = SearchSysCache(ATTNUM,
59 ObjectIdGetDatum(relid),
60 Int16GetDatum(attnum),
62 if (HeapTupleIsValid(tp))
64 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
67 result = pstrdup(NameStr(att_tup->attname));
78 * Given the relation id and the attribute name,
79 * return the "attnum" field from the attribute relation.
82 get_attnum(Oid relid, char *attname)
86 tp = SearchSysCache(ATTNAME,
87 ObjectIdGetDatum(relid),
88 PointerGetDatum(attname),
90 if (HeapTupleIsValid(tp))
92 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
95 result = att_tup->attnum;
100 return InvalidAttrNumber;
106 * Given the relation OID and the attribute number with the relation,
107 * return the attribute type OID.
110 get_atttype(Oid relid, AttrNumber attnum)
114 tp = SearchSysCache(ATTNUM,
115 ObjectIdGetDatum(relid),
116 Int16GetDatum(attnum),
118 if (HeapTupleIsValid(tp))
120 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
123 result = att_tup->atttypid;
131 /* This routine uses the attname instead of the attnum because it
132 * replaces the routine find_atttype, which is called sometimes when
133 * only the attname, not the attno, is available.
136 get_attisset(Oid relid, char *attname)
140 tp = SearchSysCache(ATTNAME,
141 ObjectIdGetDatum(relid),
142 PointerGetDatum(attname),
144 if (HeapTupleIsValid(tp))
146 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
149 result = att_tup->attisset;
160 * Given the relation id and the attribute number,
161 * return the "atttypmod" field from the attribute relation.
164 get_atttypmod(Oid relid, AttrNumber attnum)
168 tp = SearchSysCache(ATTNUM,
169 ObjectIdGetDatum(relid),
170 Int16GetDatum(attnum),
172 if (HeapTupleIsValid(tp))
174 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
177 result = att_tup->atttypmod;
188 * Retrieve the dispersion statistic for an attribute,
189 * or produce an estimate if no info is available.
191 * min_estimate is the minimum estimate to return if insufficient data
192 * is available to produce a reliable value. This value may vary
193 * depending on context. (For example, when deciding whether it is
194 * safe to use a hashjoin, we want to be more conservative than when
195 * estimating the number of tuples produced by an equijoin.)
198 get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
201 Form_pg_attribute att_tup;
206 atp = SearchSysCache(ATTNUM,
207 ObjectIdGetDatum(relid),
208 Int16GetDatum(attnum),
210 if (!HeapTupleIsValid(atp))
212 /* this should not happen */
213 elog(ERROR, "get_attdispersion: no attribute tuple %u %d",
218 att_tup = (Form_pg_attribute) GETSTRUCT(atp);
220 dispersion = att_tup->attdispersion;
221 atttypid = att_tup->atttypid;
223 ReleaseSysCache(atp);
225 if (dispersion > 0.0)
226 return dispersion; /* we have a specific estimate from VACUUM */
229 * Special-case boolean columns: the dispersion of a boolean is highly
230 * unlikely to be anywhere near 1/numtuples, instead it's probably
233 * Are there any other cases we should wire in special estimates for?
235 if (atttypid == BOOLOID)
239 * Dispersion is either 0 (no data available) or -1 (dispersion is
240 * 1/numtuples). Either way, we need the relation size.
243 atp = SearchSysCache(RELOID,
244 ObjectIdGetDatum(relid),
246 if (!HeapTupleIsValid(atp))
248 /* this should not happen */
249 elog(ERROR, "get_attdispersion: no relation tuple %u", relid);
253 ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
255 ReleaseSysCache(atp);
258 return min_estimate; /* no data available */
260 if (dispersion < 0.0) /* VACUUM thinks there are no duplicates */
261 return 1.0 / (double) ntuples;
264 * VACUUM ANALYZE does not compute dispersion for system attributes,
265 * but some of them can reasonably be assumed unique anyway.
267 if (attnum == ObjectIdAttributeNumber ||
268 attnum == SelfItemPointerAttributeNumber)
269 return 1.0 / (double) ntuples;
270 if (attnum == TableOidAttributeNumber)
274 * VACUUM ANALYZE has not been run for this table. Produce an estimate
275 * of 1/numtuples. This may produce unreasonably small estimates for
276 * large tables, so limit the estimate to no less than min_estimate.
278 dispersion = 1.0 / (double) ntuples;
279 if (dispersion < min_estimate)
280 dispersion = min_estimate;
285 /* ---------- INDEX CACHE ---------- */
287 /* watch this space...
290 /* ---------- OPERATOR CACHE ---------- */
295 * Returns the regproc id of the routine used to implement an
296 * operator given the operator oid.
303 tp = SearchSysCache(OPEROID,
304 ObjectIdGetDatum(opno),
306 if (HeapTupleIsValid(tp))
308 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
311 result = optup->oprcode;
316 return (RegProcedure) InvalidOid;
321 * returns the name of the operator with the given opno
323 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
330 tp = SearchSysCache(OPEROID,
331 ObjectIdGetDatum(opno),
333 if (HeapTupleIsValid(tp))
335 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
338 result = pstrdup(NameStr(optup->oprname));
349 * Returns the left and right sort operators and types corresponding to a
350 * mergejoinable operator, or nil if the operator is not mergejoinable.
353 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
358 tp = SearchSysCache(OPEROID,
359 ObjectIdGetDatum(opno),
361 if (HeapTupleIsValid(tp))
363 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
365 if (optup->oprlsortop &&
367 optup->oprleft == ltype &&
368 optup->oprright == rtype)
370 *leftOp = optup->oprlsortop;
371 *rightOp = optup->oprrsortop;
382 * Returns the hash operator corresponding to a hashjoinable operator,
383 * or InvalidOid if the operator is not hashjoinable.
386 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
389 Oid result = InvalidOid;
391 tp = SearchSysCache(OPEROID,
392 ObjectIdGetDatum(opno),
394 if (HeapTupleIsValid(tp))
396 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
398 if (optup->oprcanhash &&
399 optup->oprleft == ltype &&
400 optup->oprright == rtype)
410 * Get the proiscachable flag for the operator's underlying function.
413 op_iscachable(Oid opno)
415 RegProcedure funcid = get_opcode(opno);
417 if (funcid == (RegProcedure) InvalidOid)
418 elog(ERROR, "Operator OID %u does not exist", opno);
420 return func_iscachable((Oid) funcid);
426 * Returns the corresponding commutator of an operator.
429 get_commutator(Oid opno)
433 tp = SearchSysCache(OPEROID,
434 ObjectIdGetDatum(opno),
436 if (HeapTupleIsValid(tp))
438 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
441 result = optup->oprcom;
452 * Returns the corresponding negator of an operator.
455 get_negator(Oid opno)
459 tp = SearchSysCache(OPEROID,
460 ObjectIdGetDatum(opno),
462 if (HeapTupleIsValid(tp))
464 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
467 result = optup->oprnegate;
478 * Returns procedure id for computing selectivity of an operator.
481 get_oprrest(Oid opno)
485 tp = SearchSysCache(OPEROID,
486 ObjectIdGetDatum(opno),
488 if (HeapTupleIsValid(tp))
490 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
493 result = optup->oprrest;
498 return (RegProcedure) InvalidOid;
504 * Returns procedure id for computing selectivity of a join.
507 get_oprjoin(Oid opno)
511 tp = SearchSysCache(OPEROID,
512 ObjectIdGetDatum(opno),
514 if (HeapTupleIsValid(tp))
516 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
519 result = optup->oprjoin;
524 return (RegProcedure) InvalidOid;
527 /* ---------- FUNCTION CACHE ---------- */
531 * Given procedure id, return the function's result type.
534 get_func_rettype(Oid funcid)
539 tp = SearchSysCache(PROCOID,
540 ObjectIdGetDatum(funcid),
542 if (!HeapTupleIsValid(tp))
543 elog(ERROR, "Function OID %u does not exist", funcid);
545 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
552 * Given procedure id, return the function's proiscachable flag.
555 func_iscachable(Oid funcid)
560 tp = SearchSysCache(PROCOID,
561 ObjectIdGetDatum(funcid),
563 if (!HeapTupleIsValid(tp))
564 elog(ERROR, "Function OID %u does not exist", funcid);
566 result = ((Form_pg_proc) GETSTRUCT(tp))->proiscachable;
571 /* ---------- RELATION CACHE ---------- */
577 * Returns the number of attributes for a given relation.
580 get_relnatts(Oid relid)
584 tp = SearchSysCache(RELOID,
585 ObjectIdGetDatum(relid),
587 if (HeapTupleIsValid(tp))
589 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
592 result = reltup->relnatts;
597 return InvalidAttrNumber;
605 * Returns the name of a given relation.
607 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
610 get_rel_name(Oid relid)
614 tp = SearchSysCache(RELOID,
615 ObjectIdGetDatum(relid),
617 if (HeapTupleIsValid(tp))
619 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
622 result = pstrdup(NameStr(reltup->relname));
630 /* ---------- TYPE CACHE ---------- */
635 * Given the type OID, return the length of the type.
638 get_typlen(Oid typid)
642 tp = SearchSysCache(TYPEOID,
643 ObjectIdGetDatum(typid),
645 if (HeapTupleIsValid(tp))
647 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
650 result = typtup->typlen;
661 * Given the type OID, determine whether the type is returned by value or
662 * not. Returns true if by value, false if by reference.
665 get_typbyval(Oid typid)
669 tp = SearchSysCache(TYPEOID,
670 ObjectIdGetDatum(typid),
672 if (HeapTupleIsValid(tp))
674 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
677 result = typtup->typbyval;
688 * A two-fer: given the type OID, return both typlen and typbyval.
690 * Since both pieces of info are needed to know how to copy a Datum,
691 * many places need both. Might as well get them with one cache lookup
692 * instead of two. Also, this routine raises an error instead of
693 * returning a bogus value when given a bad type OID.
696 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
701 tp = SearchSysCache(TYPEOID,
702 ObjectIdGetDatum(typid),
704 if (!HeapTupleIsValid(tp))
705 elog(ERROR, "cache lookup failed for type %u", typid);
706 typtup = (Form_pg_type) GETSTRUCT(tp);
707 *typlen = typtup->typlen;
708 *typbyval = typtup->typbyval;
714 get_typalign(Oid typid)
718 tp = SearchSysCache(TYPEOID,
719 ObjectIdGetDatum(typid),
721 if (HeapTupleIsValid(tp))
723 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
726 result = typtup->typalign;
737 get_typstorage(Oid typid)
741 tp = SearchSysCache(TYPEOID,
742 ObjectIdGetDatum(typid),
744 if (HeapTupleIsValid(tp))
746 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
749 result = typtup->typstorage;
760 * Given a type OID, return the typdefault field associated with that
761 * type, or Datum(NULL) if there is no typdefault. (This implies
762 * that pass-by-value types can't have a default value that has
763 * a representation of zero. Not worth fixing now.)
764 * The result points to palloc'd storage for non-pass-by-value types.
767 get_typdefault(Oid typid)
771 struct varlena *typDefault;
778 typeTuple = SearchSysCache(TYPEOID,
779 ObjectIdGetDatum(typid),
782 if (!HeapTupleIsValid(typeTuple))
783 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
785 type = (Form_pg_type) GETSTRUCT(typeTuple);
788 * First, see if there is a non-null typdefault field (usually there
791 typDefault = (struct varlena *)
792 DatumGetPointer(SysCacheGetAttr(TYPEOID,
794 Anum_pg_type_typdefault,
799 ReleaseSysCache(typeTuple);
800 return PointerGetDatum(NULL);
804 * Otherwise, extract/copy the value.
806 dataSize = VARSIZE(typDefault) - VARHDRSZ;
807 typLen = type->typlen;
808 typByVal = type->typbyval;
812 if (dataSize == typLen)
813 returnValue = fetch_att(VARDATA(typDefault), typByVal, typLen);
815 returnValue = PointerGetDatum(NULL);
819 /* variable-size type */
821 returnValue = PointerGetDatum(NULL);
824 returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
825 memcpy((char *) DatumGetPointer(returnValue),
827 (int) VARSIZE(typDefault));
832 /* fixed-size pass-by-ref type */
833 if (dataSize != typLen)
834 returnValue = PointerGetDatum(NULL);
837 returnValue = PointerGetDatum(palloc(dataSize));
838 memcpy((char *) DatumGetPointer(returnValue),
844 ReleaseSysCache(typeTuple);
852 * Given the type OID, find if it is a basic type, a named relation
853 * or the generic type 'relation'.
854 * It returns the null char if the cache lookup fails...
858 get_typtype(Oid typid)
862 tp = SearchSysCache(TYPEOID,
863 ObjectIdGetDatum(typid),
865 if (HeapTupleIsValid(tp))
867 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
870 result = typtup->typtype;