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.39 2000/01/26 05:57:17 momjian 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'.
34 op_class(Oid opid, Oid opclass, Oid amopid)
36 if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID,
37 ObjectIdGetDatum(opclass),
38 ObjectIdGetDatum(opid),
39 ObjectIdGetDatum(amopid),
46 /* ---------- ATTRIBUTE CACHES ---------- */
51 * Given the relation id and the attribute number,
52 * return the "attname" field from the attribute relation.
56 get_attname(Oid relid, AttrNumber attnum)
60 tp = SearchSysCacheTuple(ATTNUM,
61 ObjectIdGetDatum(relid),
62 UInt16GetDatum(attnum),
64 if (HeapTupleIsValid(tp))
66 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
67 return pstrdup(NameStr(att_tup->attname));
76 * Given the relation id and the attribute name,
77 * return the "attnum" field from the attribute relation.
81 get_attnum(Oid relid, char *attname)
85 tp = SearchSysCacheTuple(ATTNAME,
86 ObjectIdGetDatum(relid),
87 PointerGetDatum(attname),
89 if (HeapTupleIsValid(tp))
91 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
92 return att_tup->attnum;
95 return InvalidAttrNumber;
101 * Given the relation OID and the attribute number with the relation,
102 * return the attribute type OID.
106 get_atttype(Oid relid, AttrNumber attnum)
110 tp = SearchSysCacheTuple(ATTNUM,
111 ObjectIdGetDatum(relid),
112 UInt16GetDatum(attnum),
114 if (HeapTupleIsValid(tp))
116 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
117 return att_tup->atttypid;
123 /* This routine uses the attname instead of the attnum because it
124 * replaces the routine find_atttype, which is called sometimes when
125 * only the attname, not the attno, is available.
128 get_attisset(Oid relid, char *attname)
132 tp = SearchSysCacheTuple(ATTNAME,
133 ObjectIdGetDatum(relid),
134 PointerGetDatum(attname),
136 if (HeapTupleIsValid(tp))
138 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.
153 get_atttypmod(Oid relid, AttrNumber attnum)
157 tp = SearchSysCacheTuple(ATTNUM,
158 ObjectIdGetDatum(relid),
159 UInt16GetDatum(attnum),
161 if (HeapTupleIsValid(tp))
163 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)
189 atp = SearchSysCacheTuple(ATTNUM,
190 ObjectIdGetDatum(relid),
191 Int16GetDatum(attnum),
193 if (!HeapTupleIsValid(atp))
195 /* this should not happen */
196 elog(ERROR, "get_attdisbursion: no attribute tuple %u %d",
201 disbursion = ((Form_pg_attribute) GETSTRUCT(atp))->attdisbursion;
202 if (disbursion > 0.0)
203 return disbursion; /* we have a specific estimate */
206 * Disbursion is either 0 (no data available) or -1 (disbursion
207 * is 1/numtuples). Either way, we need the relation size.
210 atp = SearchSysCacheTuple(RELOID,
211 ObjectIdGetDatum(relid),
213 if (!HeapTupleIsValid(atp))
215 /* this should not happen */
216 elog(ERROR, "get_attdisbursion: no relation tuple %u", relid);
220 ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
223 return min_estimate; /* no data available */
225 if (disbursion < 0.0) /* VACUUM thinks there are no duplicates */
226 return 1.0 / (double) ntuples;
229 * VACUUM ANALYZE does not compute disbursion for system attributes,
230 * but some of them can reasonably be assumed unique anyway.
232 if (attnum == ObjectIdAttributeNumber ||
233 attnum == SelfItemPointerAttributeNumber)
234 return 1.0 / (double) ntuples;
237 * VACUUM ANALYZE has not been run for this table.
238 * Produce an estimate = 1/numtuples. This may produce
239 * unreasonably small estimates for large tables, so limit
240 * the estimate to no less than min_estimate.
242 disbursion = 1.0 / (double) ntuples;
243 if (disbursion < min_estimate)
244 disbursion = min_estimate;
249 /* ---------- INDEX CACHE ---------- */
251 /* watch this space...
254 /* ---------- OPERATOR CACHE ---------- */
259 * Returns the regproc id of the routine used to implement an
260 * operator given the operator oid.
268 tp = SearchSysCacheTuple(OPEROID,
269 ObjectIdGetDatum(opno),
271 if (HeapTupleIsValid(tp))
273 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
274 return optup->oprcode;
277 return (RegProcedure) NULL;
282 * returns the name of the operator with the given opno
284 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
291 tp = SearchSysCacheTuple(OPEROID,
292 ObjectIdGetDatum(opno),
294 if (HeapTupleIsValid(tp))
296 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
297 return pstrdup(NameStr(optup->oprname));
306 * Returns the left and right sort operators and types corresponding to a
307 * mergejoinable operator, or nil if the operator is not mergejoinable.
311 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
315 tp = SearchSysCacheTuple(OPEROID,
316 ObjectIdGetDatum(opno),
318 if (HeapTupleIsValid(tp))
320 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
322 if (optup->oprlsortop &&
324 optup->oprleft == ltype &&
325 optup->oprright == rtype)
327 *leftOp = ObjectIdGetDatum(optup->oprlsortop);
328 *rightOp = ObjectIdGetDatum(optup->oprrsortop);
338 * Returns the hash operator corresponding to a hashjoinable operator,
339 * or nil if the operator is not hashjoinable.
343 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
347 tp = SearchSysCacheTuple(OPEROID,
348 ObjectIdGetDatum(opno),
350 if (HeapTupleIsValid(tp))
352 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
354 if (optup->oprcanhash &&
355 optup->oprleft == ltype &&
356 optup->oprright == rtype)
363 get_operator_tuple(Oid opno)
367 if ((optup = SearchSysCacheTuple(OPEROID,
368 ObjectIdGetDatum(opno),
372 return (HeapTuple) NULL;
378 * Returns the corresponding commutator of an operator.
382 get_commutator(Oid opno)
386 tp = SearchSysCacheTuple(OPEROID,
387 ObjectIdGetDatum(opno),
389 if (HeapTupleIsValid(tp))
391 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
392 return optup->oprcom;
401 * Returns the corresponding negator of an operator.
405 get_negator(Oid opno)
409 tp = SearchSysCacheTuple(OPEROID,
410 ObjectIdGetDatum(opno),
412 if (HeapTupleIsValid(tp))
414 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
415 return optup->oprnegate;
424 * Returns procedure id for computing selectivity of an operator.
428 get_oprrest(Oid opno)
432 tp = SearchSysCacheTuple(OPEROID,
433 ObjectIdGetDatum(opno),
435 if (HeapTupleIsValid(tp))
437 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
438 return optup->oprrest;
441 return (RegProcedure) NULL;
447 * Returns procedure id for computing selectivity of a join.
451 get_oprjoin(Oid opno)
455 tp = SearchSysCacheTuple(OPEROID,
456 ObjectIdGetDatum(opno),
458 if (HeapTupleIsValid(tp))
460 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
461 return optup->oprjoin;
464 return (RegProcedure) NULL;
467 /* ---------- FUNCTION CACHE ---------- */
471 * Given procedure id, return the function's result type.
474 get_func_rettype(Oid funcid)
476 HeapTuple func_tuple;
479 func_tuple = SearchSysCacheTuple(PROCOID,
480 ObjectIdGetDatum(funcid),
483 if (!HeapTupleIsValid(func_tuple))
484 elog(ERROR, "Function OID %u does not exist", funcid);
487 ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
492 /* ---------- RELATION CACHE ---------- */
497 * Returns the number of attributes for a given relation.
501 get_relnatts(Oid relid)
505 tp = SearchSysCacheTuple(RELOID,
506 ObjectIdGetDatum(relid),
508 if (HeapTupleIsValid(tp))
510 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
511 return reltup->relnatts;
514 return InvalidAttrNumber;
520 * Returns the name of a given relation.
524 get_rel_name(Oid relid)
528 tp = SearchSysCacheTuple(RELOID,
529 ObjectIdGetDatum(relid),
531 if (HeapTupleIsValid(tp))
533 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
534 return pstrdup(NameStr(reltup->relname));
540 /* ---------- TYPE CACHE ---------- */
545 * Given the type OID, return the length of the type.
549 get_typlen(Oid typid)
553 tp = SearchSysCacheTuple(TYPEOID,
554 ObjectIdGetDatum(typid),
556 if (HeapTupleIsValid(tp))
558 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
559 return typtup->typlen;
568 * Given the type OID, determine whether the type is returned by value or
569 * not. Returns 1 if by value, 0 if by reference.
573 get_typbyval(Oid typid)
577 tp = SearchSysCacheTuple(TYPEOID,
578 ObjectIdGetDatum(typid),
580 if (HeapTupleIsValid(tp))
582 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
583 return (bool) typtup->typbyval;
591 get_typalign(Oid typid)
595 tp = SearchSysCacheTuple(TYPEOID,
596 ObjectIdGetDatum(typid),
598 if (HeapTupleIsValid(tp))
600 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
601 return typtup->typalign;
612 * Given a type OID, return the typdefault field associated with that
613 * type, or Datum(NULL) if there is no typdefault. (This implies
614 * that pass-by-value types can't have a default value that has
615 * a representation of zero. Not worth fixing now.)
616 * The result points to palloc'd storage for non-pass-by-value types.
619 get_typdefault(Oid typid)
623 struct varlena *typDefault;
630 typeTuple = SearchSysCacheTuple(TYPEOID,
631 ObjectIdGetDatum(typid),
634 if (!HeapTupleIsValid(typeTuple))
635 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
637 type = (Form_pg_type) GETSTRUCT(typeTuple);
640 * First, see if there is a non-null typdefault field (usually there isn't)
642 typDefault = (struct varlena *) SysCacheGetAttr(TYPEOID,
644 Anum_pg_type_typdefault,
648 return PointerGetDatum(NULL);
651 * Otherwise, extract/copy the value.
653 dataSize = VARSIZE(typDefault) - VARHDRSZ;
654 typLen = type->typlen;
655 typByVal = type->typbyval;
663 if (dataSize == typLen)
668 memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
672 memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
676 memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
679 returnValue = Int32GetDatum(i32);
682 returnValue = PointerGetDatum(NULL);
686 /* variable-size type */
688 returnValue = PointerGetDatum(NULL);
691 returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
692 memcpy((char *) DatumGetPointer(returnValue),
694 (int) VARSIZE(typDefault));
699 /* fixed-size pass-by-ref type */
700 if (dataSize != typLen)
701 returnValue = PointerGetDatum(NULL);
704 returnValue = PointerGetDatum(palloc(dataSize));
705 memcpy((char *) DatumGetPointer(returnValue),
717 * Given the type OID, find if it is a basic type, a named relation
718 * or the generic type 'relation'.
719 * It returns the null char if the cache lookup fails...
724 get_typtype(Oid typid)
728 tp = SearchSysCacheTuple(TYPEOID,
729 ObjectIdGetDatum(typid),
731 if (HeapTupleIsValid(tp))
733 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
734 return typtup->typtype;