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.45 2000/08/13 02:50:16 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 'opno' is in operator class 'opclass' for
30 * access method 'amopid'.
33 op_class(Oid opno, Oid opclass, Oid amopid)
35 if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID,
36 ObjectIdGetDatum(opclass),
37 ObjectIdGetDatum(opno),
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) InvalidOid;
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)
377 * Get the proiscachable flag for the operator's underlying function.
380 op_iscachable(Oid opno)
382 RegProcedure funcid = get_opcode(opno);
384 if (funcid == (RegProcedure) InvalidOid)
385 elog(ERROR, "Operator OID %u does not exist", opno);
387 return func_iscachable((Oid) funcid);
391 get_operator_tuple(Oid opno)
393 return SearchSysCacheTuple(OPEROID,
394 ObjectIdGetDatum(opno),
401 * Returns the corresponding commutator of an operator.
404 get_commutator(Oid opno)
408 tp = SearchSysCacheTuple(OPEROID,
409 ObjectIdGetDatum(opno),
411 if (HeapTupleIsValid(tp))
413 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
415 return optup->oprcom;
424 * Returns the corresponding negator of an operator.
427 get_negator(Oid opno)
431 tp = SearchSysCacheTuple(OPEROID,
432 ObjectIdGetDatum(opno),
434 if (HeapTupleIsValid(tp))
436 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
438 return optup->oprnegate;
447 * Returns procedure id for computing selectivity of an operator.
450 get_oprrest(Oid opno)
454 tp = SearchSysCacheTuple(OPEROID,
455 ObjectIdGetDatum(opno),
457 if (HeapTupleIsValid(tp))
459 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
461 return optup->oprrest;
464 return (RegProcedure) InvalidOid;
470 * Returns procedure id for computing selectivity of a join.
473 get_oprjoin(Oid opno)
477 tp = SearchSysCacheTuple(OPEROID,
478 ObjectIdGetDatum(opno),
480 if (HeapTupleIsValid(tp))
482 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
484 return optup->oprjoin;
487 return (RegProcedure) InvalidOid;
490 /* ---------- FUNCTION CACHE ---------- */
494 * Given procedure id, return the function's result type.
497 get_func_rettype(Oid funcid)
499 HeapTuple func_tuple;
501 func_tuple = SearchSysCacheTuple(PROCOID,
502 ObjectIdGetDatum(funcid),
504 if (!HeapTupleIsValid(func_tuple))
505 elog(ERROR, "Function OID %u does not exist", funcid);
507 return ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
512 * Given procedure id, return the function's proiscachable flag.
515 func_iscachable(Oid funcid)
517 HeapTuple func_tuple;
519 func_tuple = SearchSysCacheTuple(PROCOID,
520 ObjectIdGetDatum(funcid),
522 if (!HeapTupleIsValid(func_tuple))
523 elog(ERROR, "Function OID %u does not exist", funcid);
525 return ((Form_pg_proc) GETSTRUCT(func_tuple))->proiscachable;
528 /* ---------- RELATION CACHE ---------- */
534 * Returns the number of attributes for a given relation.
537 get_relnatts(Oid relid)
541 tp = SearchSysCacheTuple(RELOID,
542 ObjectIdGetDatum(relid),
544 if (HeapTupleIsValid(tp))
546 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
548 return reltup->relnatts;
551 return InvalidAttrNumber;
558 * Returns the name of a given relation.
561 get_rel_name(Oid relid)
565 tp = SearchSysCacheTuple(RELOID,
566 ObjectIdGetDatum(relid),
568 if (HeapTupleIsValid(tp))
570 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
572 return pstrdup(NameStr(reltup->relname));
578 /* ---------- TYPE CACHE ---------- */
583 * Given the type OID, return the length of the type.
586 get_typlen(Oid typid)
590 tp = SearchSysCacheTuple(TYPEOID,
591 ObjectIdGetDatum(typid),
593 if (HeapTupleIsValid(tp))
595 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
597 return typtup->typlen;
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.
610 get_typbyval(Oid typid)
614 tp = SearchSysCacheTuple(TYPEOID,
615 ObjectIdGetDatum(typid),
617 if (HeapTupleIsValid(tp))
619 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
621 return typtup->typbyval;
629 get_typalign(Oid typid)
633 tp = SearchSysCacheTuple(TYPEOID,
634 ObjectIdGetDatum(typid),
636 if (HeapTupleIsValid(tp))
638 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
640 return typtup->typalign;
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.
658 get_typdefault(Oid typid)
662 struct varlena *typDefault;
669 typeTuple = SearchSysCacheTuple(TYPEOID,
670 ObjectIdGetDatum(typid),
673 if (!HeapTupleIsValid(typeTuple))
674 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
676 type = (Form_pg_type) GETSTRUCT(typeTuple);
679 * First, see if there is a non-null typdefault field (usually there
682 typDefault = (struct varlena *) SysCacheGetAttr(TYPEOID,
684 Anum_pg_type_typdefault,
688 return PointerGetDatum(NULL);
691 * Otherwise, extract/copy the value.
693 dataSize = VARSIZE(typDefault) - VARHDRSZ;
694 typLen = type->typlen;
695 typByVal = type->typbyval;
703 if (dataSize == typLen)
708 memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
712 memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
716 memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
719 returnValue = Int32GetDatum(i32);
722 returnValue = PointerGetDatum(NULL);
726 /* variable-size type */
728 returnValue = PointerGetDatum(NULL);
731 returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
732 memcpy((char *) DatumGetPointer(returnValue),
734 (int) VARSIZE(typDefault));
739 /* fixed-size pass-by-ref type */
740 if (dataSize != typLen)
741 returnValue = PointerGetDatum(NULL);
744 returnValue = PointerGetDatum(palloc(dataSize));
745 memcpy((char *) DatumGetPointer(returnValue),
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...
763 get_typtype(Oid typid)
767 tp = SearchSysCacheTuple(TYPEOID,
768 ObjectIdGetDatum(typid),
770 if (HeapTupleIsValid(tp))
772 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
774 return typtup->typtype;