1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Copyright (c) 1994, Regents of the University of California
9 * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.35 1999/11/07 23:08:26 momjian Exp $
12 * Eventually, the index information should go through here, too.
13 *-------------------------------------------------------------------------
17 #include "catalog/pg_operator.h"
18 #include "catalog/pg_proc.h"
19 #include "catalog/pg_type.h"
20 #include "utils/lsyscache.h"
21 #include "utils/syscache.h"
23 /* ---------- AMOP CACHES ---------- */
28 * Return t iff operator 'opno' is in operator class 'opclass'.
32 op_class(Oid oprno, int32 opclass, Oid amopid)
34 if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID,
35 ObjectIdGetDatum(opclass),
36 ObjectIdGetDatum(oprno),
37 ObjectIdGetDatum(amopid),
44 /* ---------- ATTRIBUTE CACHES ---------- */
49 * Given the relation id and the attribute number,
50 * return the "attname" field from the attribute relation.
54 get_attname(Oid relid, AttrNumber attnum)
58 tp = SearchSysCacheTuple(ATTNUM,
59 ObjectIdGetDatum(relid),
60 UInt16GetDatum(attnum),
62 if (HeapTupleIsValid(tp))
64 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
65 return pstrdup(NameStr(att_tup->attname));
74 * Given the relation id and the attribute name,
75 * 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);
90 return att_tup->attnum;
93 return InvalidAttrNumber;
99 * Given the relation OID and the attribute number with the relation,
100 * return the attribute type OID.
104 get_atttype(Oid relid, AttrNumber attnum)
108 tp = SearchSysCacheTuple(ATTNUM,
109 ObjectIdGetDatum(relid),
110 UInt16GetDatum(attnum),
112 if (HeapTupleIsValid(tp))
114 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
115 return att_tup->atttypid;
121 /* This routine uses the attname instead of the attnum because it
122 * replaces the routine find_atttype, which is called sometimes when
123 * only the attname, not the attno, is available.
126 get_attisset(Oid relid, char *attname)
130 tp = SearchSysCacheTuple(ATTNAME,
131 ObjectIdGetDatum(relid),
132 PointerGetDatum(attname),
134 if (HeapTupleIsValid(tp))
136 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
137 return att_tup->attisset;
146 * Given the relation id and the attribute number,
147 * return the "atttypmod" field from the attribute relation.
151 get_atttypmod(Oid relid, AttrNumber attnum)
155 tp = SearchSysCacheTuple(ATTNUM,
156 ObjectIdGetDatum(relid),
157 UInt16GetDatum(attnum),
159 if (HeapTupleIsValid(tp))
161 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
162 return att_tup->atttypmod;
171 * Retrieve the disbursion statistic for an attribute,
172 * or produce an estimate if no info is available.
174 * min_estimate is the minimum estimate to return if insufficient data
175 * is available to produce a reliable value. This value may vary
176 * depending on context. (For example, when deciding whether it is
177 * safe to use a hashjoin, we want to be more conservative than when
178 * estimating the number of tuples produced by an equijoin.)
181 get_attdisbursion(Oid relid, AttrNumber attnum, double min_estimate)
187 atp = SearchSysCacheTuple(ATTNUM,
188 ObjectIdGetDatum(relid),
189 Int16GetDatum(attnum),
191 if (!HeapTupleIsValid(atp))
193 /* this should not happen */
194 elog(ERROR, "get_attdisbursion: no attribute tuple %u %d",
199 disbursion = ((Form_pg_attribute) GETSTRUCT(atp))->attdisbursion;
200 if (disbursion > 0.0)
201 return disbursion; /* we have a specific estimate */
204 * Disbursion is either 0 (no data available) or -1 (disbursion
205 * is 1/numtuples). Either way, we need the relation size.
208 atp = SearchSysCacheTuple(RELOID,
209 ObjectIdGetDatum(relid),
211 if (!HeapTupleIsValid(atp))
213 /* this should not happen */
214 elog(ERROR, "get_attdisbursion: no relation tuple %u", relid);
218 ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
221 return min_estimate; /* no data available */
223 if (disbursion < 0.0) /* VACUUM thinks there are no duplicates */
224 return 1.0 / (double) ntuples;
227 * VACUUM ANALYZE does not compute disbursion for system attributes,
228 * but some of them can reasonably be assumed unique anyway.
230 if (attnum == ObjectIdAttributeNumber ||
231 attnum == SelfItemPointerAttributeNumber)
232 return 1.0 / (double) ntuples;
235 * VACUUM ANALYZE has not been run for this table.
236 * Produce an estimate = 1/numtuples. This may produce
237 * unreasonably small estimates for large tables, so limit
238 * the estimate to no less than min_estimate.
240 disbursion = 1.0 / (double) ntuples;
241 if (disbursion < min_estimate)
242 disbursion = min_estimate;
247 /* ---------- INDEX CACHE ---------- */
249 /* watch this space...
252 /* ---------- OPERATOR CACHE ---------- */
257 * Returns the regproc id of the routine used to implement an
258 * operator given the operator oid.
266 tp = SearchSysCacheTuple(OPROID,
267 ObjectIdGetDatum(opno),
269 if (HeapTupleIsValid(tp))
271 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
272 return optup->oprcode;
275 return (RegProcedure) NULL;
280 * returns the name of the operator with the given opno
282 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
289 tp = SearchSysCacheTuple(OPROID,
290 ObjectIdGetDatum(opno),
292 if (HeapTupleIsValid(tp))
294 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
295 return pstrdup(NameStr(optup->oprname));
304 * Returns the left and right sort operators and types corresponding to a
305 * mergejoinable operator, or nil if the operator is not mergejoinable.
309 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
313 tp = SearchSysCacheTuple(OPROID,
314 ObjectIdGetDatum(opno),
316 if (HeapTupleIsValid(tp))
318 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
320 if (optup->oprlsortop &&
322 optup->oprleft == ltype &&
323 optup->oprright == rtype)
325 *leftOp = ObjectIdGetDatum(optup->oprlsortop);
326 *rightOp = ObjectIdGetDatum(optup->oprrsortop);
336 * Returns the hash operator corresponding to a hashjoinable operator,
337 * or nil if the operator is not hashjoinable.
341 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
345 tp = SearchSysCacheTuple(OPROID,
346 ObjectIdGetDatum(opno),
348 if (HeapTupleIsValid(tp))
350 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
352 if (optup->oprcanhash &&
353 optup->oprleft == ltype &&
354 optup->oprright == rtype)
361 get_operator_tuple(Oid opno)
365 if ((optup = SearchSysCacheTuple(OPROID,
366 ObjectIdGetDatum(opno),
370 return (HeapTuple) NULL;
376 * Returns the corresponding commutator of an operator.
380 get_commutator(Oid opno)
384 tp = SearchSysCacheTuple(OPROID,
385 ObjectIdGetDatum(opno),
387 if (HeapTupleIsValid(tp))
389 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
390 return optup->oprcom;
399 * Returns the corresponding negator of an operator.
403 get_negator(Oid opno)
407 tp = SearchSysCacheTuple(OPROID,
408 ObjectIdGetDatum(opno),
410 if (HeapTupleIsValid(tp))
412 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
413 return optup->oprnegate;
422 * Returns procedure id for computing selectivity of an operator.
426 get_oprrest(Oid opno)
430 tp = SearchSysCacheTuple(OPROID,
431 ObjectIdGetDatum(opno),
433 if (HeapTupleIsValid(tp))
435 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
436 return optup->oprrest;
439 return (RegProcedure) NULL;
445 * Returns procedure id for computing selectivity of a join.
449 get_oprjoin(Oid opno)
453 tp = SearchSysCacheTuple(OPROID,
454 ObjectIdGetDatum(opno),
456 if (HeapTupleIsValid(tp))
458 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
459 return optup->oprjoin;
462 return (RegProcedure) NULL;
465 /* ---------- FUNCTION CACHE ---------- */
469 * Given procedure id, return the function's result type.
472 get_func_rettype(Oid funcid)
474 HeapTuple func_tuple;
477 func_tuple = SearchSysCacheTuple(PROOID,
478 ObjectIdGetDatum(funcid),
481 if (!HeapTupleIsValid(func_tuple))
482 elog(ERROR, "Function OID %u does not exist", funcid);
485 ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
490 /* ---------- RELATION CACHE ---------- */
495 * Returns the number of attributes for a given relation.
499 get_relnatts(Oid relid)
503 tp = SearchSysCacheTuple(RELOID,
504 ObjectIdGetDatum(relid),
506 if (HeapTupleIsValid(tp))
508 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
509 return reltup->relnatts;
512 return InvalidAttrNumber;
518 * Returns the name of a given relation.
522 get_rel_name(Oid relid)
526 tp = SearchSysCacheTuple(RELOID,
527 ObjectIdGetDatum(relid),
529 if (HeapTupleIsValid(tp))
531 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
532 return pstrdup(NameStr(reltup->relname));
538 /* ---------- TYPE CACHE ---------- */
543 * Given the type OID, return the length of the type.
547 get_typlen(Oid typid)
551 tp = SearchSysCacheTuple(TYPOID,
552 ObjectIdGetDatum(typid),
554 if (HeapTupleIsValid(tp))
556 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
557 return typtup->typlen;
566 * Given the type OID, determine whether the type is returned by value or
567 * not. Returns 1 if by value, 0 if by reference.
571 get_typbyval(Oid typid)
575 tp = SearchSysCacheTuple(TYPOID,
576 ObjectIdGetDatum(typid),
578 if (HeapTupleIsValid(tp))
580 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
581 return (bool) typtup->typbyval;
589 get_typalign(Oid typid)
593 tp = SearchSysCacheTuple(TYPOID,
594 ObjectIdGetDatum(typid),
596 if (HeapTupleIsValid(tp))
598 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
599 return typtup->typalign;
610 * Given a type OID, return the typdefault field associated with that
611 * type, or Datum(NULL) if there is no typdefault. (This implies
612 * that pass-by-value types can't have a default value that has
613 * a representation of zero. Not worth fixing now.)
614 * The result points to palloc'd storage for non-pass-by-value types.
617 get_typdefault(Oid typid)
619 struct varlena *typDefault;
628 * First, see if there is a non-null typdefault field (usually there isn't)
630 typDefault = (struct varlena *)
631 SearchSysCacheGetAttribute(TYPOID,
632 Anum_pg_type_typdefault,
633 ObjectIdGetDatum(typid),
636 if (typDefault == NULL)
637 return PointerGetDatum(NULL);
639 dataSize = VARSIZE(typDefault) - VARHDRSZ;
642 * Need the type's length and byVal fields.
644 * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
645 * just did --- but at present this path isn't taken often enough to
646 * make it worth fixing.
648 typeTuple = SearchSysCacheTuple(TYPOID,
649 ObjectIdGetDatum(typid),
652 if (!HeapTupleIsValid(typeTuple))
653 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
655 type = (Form_pg_type) GETSTRUCT(typeTuple);
656 typLen = type->typlen;
657 typByVal = type->typbyval;
665 if (dataSize == typLen)
670 memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
674 memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
678 memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
681 returnValue = Int32GetDatum(i32);
684 returnValue = PointerGetDatum(NULL);
688 /* variable-size type */
690 returnValue = PointerGetDatum(NULL);
693 returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
694 memcpy((char *) DatumGetPointer(returnValue),
696 (int) VARSIZE(typDefault));
701 /* fixed-size pass-by-ref type */
702 if (dataSize != typLen)
703 returnValue = PointerGetDatum(NULL);
706 returnValue = PointerGetDatum(palloc(dataSize));
707 memcpy((char *) DatumGetPointer(returnValue),
719 * Given the type OID, find if it is a basic type, a named relation
720 * or the generic type 'relation'.
721 * It returns the null char if the cache lookup fails...
726 get_typtype(Oid typid)
730 tp = SearchSysCacheTuple(TYPOID,
731 ObjectIdGetDatum(typid),
733 if (HeapTupleIsValid(tp))
735 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
736 return typtup->typtype;