1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2002, 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.91 2003/03/23 05:14:36 tgl Exp $
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
17 #include "miscadmin.h"
19 #include "access/tupmacs.h"
20 #include "catalog/pg_amop.h"
21 #include "catalog/pg_namespace.h"
22 #include "catalog/pg_opclass.h"
23 #include "catalog/pg_operator.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_shadow.h"
26 #include "catalog/pg_statistic.h"
27 #include "catalog/pg_type.h"
28 #include "nodes/makefuncs.h"
29 #include "utils/array.h"
30 #include "utils/builtins.h"
31 #include "utils/datum.h"
32 #include "utils/lsyscache.h"
33 #include "utils/syscache.h"
36 /* ---------- AMOP CACHES ---------- */
41 * Return t iff operator 'opno' is in operator class 'opclass'.
44 op_in_opclass(Oid opno, Oid opclass)
46 return SearchSysCacheExists(AMOPOPID,
47 ObjectIdGetDatum(opclass),
48 ObjectIdGetDatum(opno),
55 * Return t if operator 'opno' requires a recheck when used as a
56 * member of opclass 'opclass' (ie, this opclass is lossy for this
59 * Caller should already have verified that opno is a member of opclass,
60 * therefore we raise an error if the tuple is not found.
63 op_requires_recheck(Oid opno, Oid opclass)
66 Form_pg_amop amop_tup;
69 tp = SearchSysCache(AMOPOPID,
70 ObjectIdGetDatum(opclass),
71 ObjectIdGetDatum(opno),
73 if (!HeapTupleIsValid(tp))
74 elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u",
76 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
78 result = amop_tup->amopreqcheck;
83 /* ---------- ATTRIBUTE CACHES ---------- */
88 * Given the relation id and the attribute number,
89 * return the "attname" field from the attribute relation.
91 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
94 get_attname(Oid relid, AttrNumber attnum)
98 tp = SearchSysCache(ATTNUM,
99 ObjectIdGetDatum(relid),
100 Int16GetDatum(attnum),
102 if (HeapTupleIsValid(tp))
104 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
107 result = pstrdup(NameStr(att_tup->attname));
118 * Given the relation id and the attribute name,
119 * return the "attnum" field from the attribute relation.
121 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
124 get_attnum(Oid relid, const char *attname)
128 tp = SearchSysCacheAttName(relid, attname);
129 if (HeapTupleIsValid(tp))
131 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
134 result = att_tup->attnum;
139 return InvalidAttrNumber;
145 * Given the relation OID and the attribute number with the relation,
146 * return the attribute type OID.
149 get_atttype(Oid relid, AttrNumber attnum)
153 tp = SearchSysCache(ATTNUM,
154 ObjectIdGetDatum(relid),
155 Int16GetDatum(attnum),
157 if (HeapTupleIsValid(tp))
159 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
162 result = att_tup->atttypid;
173 * Given the relation id and the attribute number,
174 * return the "atttypmod" field from the attribute relation.
177 get_atttypmod(Oid relid, AttrNumber attnum)
181 tp = SearchSysCache(ATTNUM,
182 ObjectIdGetDatum(relid),
183 Int16GetDatum(attnum),
185 if (HeapTupleIsValid(tp))
187 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
190 result = att_tup->atttypmod;
201 * A two-fer: given the relation id and the attribute number,
202 * fetch both type OID and atttypmod in a single cache lookup.
204 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
205 * raises an error if it can't obtain the information.
208 get_atttypetypmod(Oid relid, AttrNumber attnum,
209 Oid *typid, int32 *typmod)
212 Form_pg_attribute att_tup;
214 tp = SearchSysCache(ATTNUM,
215 ObjectIdGetDatum(relid),
216 Int16GetDatum(attnum),
218 if (!HeapTupleIsValid(tp))
219 elog(ERROR, "cache lookup failed for relation %u attribute %d",
221 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
223 *typid = att_tup->atttypid;
224 *typmod = att_tup->atttypmod;
228 /* ---------- INDEX CACHE ---------- */
230 /* watch this space...
233 /* ---------- OPCLASS CACHE ---------- */
238 * Returns TRUE iff the specified opclass is associated with the
239 * btree index access method.
242 opclass_is_btree(Oid opclass)
245 Form_pg_opclass cla_tup;
248 tp = SearchSysCache(CLAOID,
249 ObjectIdGetDatum(opclass),
251 if (!HeapTupleIsValid(tp))
252 elog(ERROR, "cache lookup failed for opclass %u", opclass);
253 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
255 result = (cla_tup->opcamid == BTREE_AM_OID);
260 /* ---------- OPERATOR CACHE ---------- */
265 * Returns the regproc id of the routine used to implement an
266 * operator given the operator oid.
273 tp = SearchSysCache(OPEROID,
274 ObjectIdGetDatum(opno),
276 if (HeapTupleIsValid(tp))
278 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
281 result = optup->oprcode;
286 return (RegProcedure) InvalidOid;
291 * returns the name of the operator with the given opno
293 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
300 tp = SearchSysCache(OPEROID,
301 ObjectIdGetDatum(opno),
303 if (HeapTupleIsValid(tp))
305 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
308 result = pstrdup(NameStr(optup->oprname));
319 * Returns the left and right sort operators corresponding to a
320 * mergejoinable operator, or false if the operator is not mergejoinable.
323 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
328 tp = SearchSysCache(OPEROID,
329 ObjectIdGetDatum(opno),
331 if (HeapTupleIsValid(tp))
333 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
335 if (optup->oprlsortop &&
338 *leftOp = optup->oprlsortop;
339 *rightOp = optup->oprrsortop;
348 * op_mergejoin_crossops
350 * Returns the cross-type comparison operators (ltype "<" rtype and
351 * ltype ">" rtype) for an operator previously determined to be
352 * mergejoinable. Optionally, fetches the regproc ids of these
353 * operators, as well as their operator OIDs.
356 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
357 RegProcedure *ltproc, RegProcedure *gtproc)
360 Form_pg_operator optup;
363 * Get the declared comparison operators of the operator.
365 tp = SearchSysCache(OPEROID,
366 ObjectIdGetDatum(opno),
368 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
369 elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
370 optup = (Form_pg_operator) GETSTRUCT(tp);
371 *ltop = optup->oprltcmpop;
372 *gtop = optup->oprgtcmpop;
375 /* Check < op provided */
376 if (!OidIsValid(*ltop))
377 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
380 *ltproc = get_opcode(*ltop);
382 /* Check > op provided */
383 if (!OidIsValid(*gtop))
384 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
387 *gtproc = get_opcode(*gtop);
393 * Returns true if the operator is hashjoinable.
396 op_hashjoinable(Oid opno)
401 tp = SearchSysCache(OPEROID,
402 ObjectIdGetDatum(opno),
404 if (HeapTupleIsValid(tp))
406 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
408 result = optup->oprcanhash;
417 * Get the proisstrict flag for the operator's underlying function.
422 RegProcedure funcid = get_opcode(opno);
424 if (funcid == (RegProcedure) InvalidOid)
425 elog(ERROR, "Operator OID %u does not exist", opno);
427 return func_strict((Oid) funcid);
433 * Get the provolatile flag for the operator's underlying function.
436 op_volatile(Oid opno)
438 RegProcedure funcid = get_opcode(opno);
440 if (funcid == (RegProcedure) InvalidOid)
441 elog(ERROR, "Operator OID %u does not exist", opno);
443 return func_volatile((Oid) funcid);
449 * Returns the corresponding commutator of an operator.
452 get_commutator(Oid opno)
456 tp = SearchSysCache(OPEROID,
457 ObjectIdGetDatum(opno),
459 if (HeapTupleIsValid(tp))
461 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
464 result = optup->oprcom;
475 * Returns the corresponding negator of an operator.
478 get_negator(Oid opno)
482 tp = SearchSysCache(OPEROID,
483 ObjectIdGetDatum(opno),
485 if (HeapTupleIsValid(tp))
487 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
490 result = optup->oprnegate;
501 * Returns procedure id for computing selectivity of an operator.
504 get_oprrest(Oid opno)
508 tp = SearchSysCache(OPEROID,
509 ObjectIdGetDatum(opno),
511 if (HeapTupleIsValid(tp))
513 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
516 result = optup->oprrest;
521 return (RegProcedure) InvalidOid;
527 * Returns procedure id for computing selectivity of a join.
530 get_oprjoin(Oid opno)
534 tp = SearchSysCache(OPEROID,
535 ObjectIdGetDatum(opno),
537 if (HeapTupleIsValid(tp))
539 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
542 result = optup->oprjoin;
547 return (RegProcedure) InvalidOid;
550 /* ---------- FUNCTION CACHE ---------- */
554 * returns the name of the function with the given funcid
556 * Note: returns a palloc'd copy of the string, or NULL if no such function.
559 get_func_name(Oid funcid)
563 tp = SearchSysCache(PROCOID,
564 ObjectIdGetDatum(funcid),
566 if (HeapTupleIsValid(tp))
568 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
571 result = pstrdup(NameStr(functup->proname));
581 * Given procedure id, return the function's result type.
584 get_func_rettype(Oid funcid)
589 tp = SearchSysCache(PROCOID,
590 ObjectIdGetDatum(funcid),
592 if (!HeapTupleIsValid(tp))
593 elog(ERROR, "Function OID %u does not exist", funcid);
595 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
602 * Given procedure id, return the function's proretset flag.
605 get_func_retset(Oid funcid)
610 tp = SearchSysCache(PROCOID,
611 ObjectIdGetDatum(funcid),
613 if (!HeapTupleIsValid(tp))
614 elog(ERROR, "Function OID %u does not exist", funcid);
616 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
623 * Given procedure id, return the function's proisstrict flag.
626 func_strict(Oid funcid)
631 tp = SearchSysCache(PROCOID,
632 ObjectIdGetDatum(funcid),
634 if (!HeapTupleIsValid(tp))
635 elog(ERROR, "Function OID %u does not exist", funcid);
637 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
644 * Given procedure id, return the function's provolatile flag.
647 func_volatile(Oid funcid)
652 tp = SearchSysCache(PROCOID,
653 ObjectIdGetDatum(funcid),
655 if (!HeapTupleIsValid(tp))
656 elog(ERROR, "Function OID %u does not exist", funcid);
658 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
663 /* ---------- RELATION CACHE ---------- */
667 * Given name and namespace of a relation, look up the OID.
669 * Returns InvalidOid if there is no such relation.
672 get_relname_relid(const char *relname, Oid relnamespace)
674 return GetSysCacheOid(RELNAMENSP,
675 PointerGetDatum(relname),
676 ObjectIdGetDatum(relnamespace),
681 * get_system_catalog_relid
682 * Get the OID of a system catalog identified by name.
685 get_system_catalog_relid(const char *catname)
689 relid = GetSysCacheOid(RELNAMENSP,
690 PointerGetDatum(catname),
691 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
693 if (!OidIsValid(relid))
694 elog(ERROR, "get_system_catalog_relid: cannot find %s", catname);
703 * Returns the number of attributes for a given relation.
706 get_relnatts(Oid relid)
710 tp = SearchSysCache(RELOID,
711 ObjectIdGetDatum(relid),
713 if (HeapTupleIsValid(tp))
715 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
718 result = reltup->relnatts;
723 return InvalidAttrNumber;
729 * Returns the name of a given relation.
731 * Returns a palloc'd copy of the string, or NULL if no such relation.
733 * NOTE: since relation name is not unique, be wary of code that uses this
734 * for anything except preparing error messages.
737 get_rel_name(Oid relid)
741 tp = SearchSysCache(RELOID,
742 ObjectIdGetDatum(relid),
744 if (HeapTupleIsValid(tp))
746 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
749 result = pstrdup(NameStr(reltup->relname));
760 * Returns the pg_namespace OID associated with a given relation.
763 get_rel_namespace(Oid relid)
767 tp = SearchSysCache(RELOID,
768 ObjectIdGetDatum(relid),
770 if (HeapTupleIsValid(tp))
772 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
775 result = reltup->relnamespace;
786 * Returns the pg_type OID associated with a given relation.
788 * Note: not all pg_class entries have associated pg_type OIDs; so be
789 * careful to check for InvalidOid result.
792 get_rel_type_id(Oid relid)
796 tp = SearchSysCache(RELOID,
797 ObjectIdGetDatum(relid),
799 if (HeapTupleIsValid(tp))
801 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
804 result = reltup->reltype;
815 * Returns the relkind associated with a given relation.
818 get_rel_relkind(Oid relid)
822 tp = SearchSysCache(RELOID,
823 ObjectIdGetDatum(relid),
825 if (HeapTupleIsValid(tp))
827 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
830 result = reltup->relkind;
839 /* ---------- TYPE CACHE ---------- */
844 * Given the type OID, determine whether the type is defined
845 * (if not, it's only a shell).
848 get_typisdefined(Oid typid)
852 tp = SearchSysCache(TYPEOID,
853 ObjectIdGetDatum(typid),
855 if (HeapTupleIsValid(tp))
857 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
860 result = typtup->typisdefined;
871 * Given the type OID, return the length of the type.
874 get_typlen(Oid typid)
878 tp = SearchSysCache(TYPEOID,
879 ObjectIdGetDatum(typid),
881 if (HeapTupleIsValid(tp))
883 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
886 result = typtup->typlen;
897 * Given the type OID, determine whether the type is returned by value or
898 * not. Returns true if by value, false if by reference.
901 get_typbyval(Oid typid)
905 tp = SearchSysCache(TYPEOID,
906 ObjectIdGetDatum(typid),
908 if (HeapTupleIsValid(tp))
910 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
913 result = typtup->typbyval;
924 * A two-fer: given the type OID, return both typlen and typbyval.
926 * Since both pieces of info are needed to know how to copy a Datum,
927 * many places need both. Might as well get them with one cache lookup
928 * instead of two. Also, this routine raises an error instead of
929 * returning a bogus value when given a bad type OID.
932 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
937 tp = SearchSysCache(TYPEOID,
938 ObjectIdGetDatum(typid),
940 if (!HeapTupleIsValid(tp))
941 elog(ERROR, "cache lookup failed for type %u", typid);
942 typtup = (Form_pg_type) GETSTRUCT(tp);
943 *typlen = typtup->typlen;
944 *typbyval = typtup->typbyval;
949 * get_typlenbyvalalign
951 * A three-fer: given the type OID, return typlen, typbyval, typalign.
954 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
960 tp = SearchSysCache(TYPEOID,
961 ObjectIdGetDatum(typid),
963 if (!HeapTupleIsValid(tp))
964 elog(ERROR, "cache lookup failed for type %u", typid);
965 typtup = (Form_pg_type) GETSTRUCT(tp);
966 *typlen = typtup->typlen;
967 *typbyval = typtup->typbyval;
968 *typalign = typtup->typalign;
974 get_typalign(Oid typid)
978 tp = SearchSysCache(TYPEOID,
979 ObjectIdGetDatum(typid),
981 if (HeapTupleIsValid(tp))
983 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
986 result = typtup->typalign;
996 get_typstorage(Oid typid)
1000 tp = SearchSysCache(TYPEOID,
1001 ObjectIdGetDatum(typid),
1003 if (HeapTupleIsValid(tp))
1005 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1008 result = typtup->typstorage;
1009 ReleaseSysCache(tp);
1019 * Given the type OID, return the typtypmod field (domain's typmod
1023 get_typtypmod(Oid typid)
1027 tp = SearchSysCache(TYPEOID,
1028 ObjectIdGetDatum(typid),
1030 if (HeapTupleIsValid(tp))
1032 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1035 result = typtup->typtypmod;
1036 ReleaseSysCache(tp);
1045 * Given a type OID, return the type's default value, if any.
1047 * The result is a palloc'd expression node tree, or NULL if there
1048 * is no defined default for the datatype.
1050 * NB: caller should be prepared to coerce result to correct datatype;
1051 * the returned expression tree might produce something of the wrong type.
1054 get_typdefault(Oid typid)
1056 HeapTuple typeTuple;
1062 typeTuple = SearchSysCache(TYPEOID,
1063 ObjectIdGetDatum(typid),
1065 if (!HeapTupleIsValid(typeTuple))
1066 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
1067 type = (Form_pg_type) GETSTRUCT(typeTuple);
1070 * typdefault and typdefaultbin are potentially null, so don't try to
1071 * access 'em as struct fields. Must do it the hard way with
1074 datum = SysCacheGetAttr(TYPEOID,
1076 Anum_pg_type_typdefaultbin,
1081 /* We have an expression default */
1082 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1087 /* Perhaps we have a plain literal default */
1088 datum = SysCacheGetAttr(TYPEOID,
1090 Anum_pg_type_typdefault,
1095 char *strDefaultVal;
1097 /* Convert text datum to C string */
1098 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1100 /* Convert C string to a value of the given type */
1101 datum = OidFunctionCall3(type->typinput,
1102 CStringGetDatum(strDefaultVal),
1103 ObjectIdGetDatum(type->typelem),
1105 /* Build a Const node containing the value */
1106 expr = (Node *) makeConst(typid,
1111 pfree(strDefaultVal);
1120 ReleaseSysCache(typeTuple);
1127 * If the given type is a domain, return its base type;
1128 * otherwise return the type's own OID.
1131 getBaseType(Oid typid)
1134 * We loop to find the bottom base type in a stack of domains.
1139 Form_pg_type typTup;
1141 tup = SearchSysCache(TYPEOID,
1142 ObjectIdGetDatum(typid),
1144 if (!HeapTupleIsValid(tup))
1145 elog(ERROR, "getBaseType: failed to lookup type %u", typid);
1146 typTup = (Form_pg_type) GETSTRUCT(tup);
1147 if (typTup->typtype != 'd')
1149 /* Not a domain, so done */
1150 ReleaseSysCache(tup);
1154 typid = typTup->typbasetype;
1155 ReleaseSysCache(tup);
1164 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1165 * estimate the average width of values of the type. This is used by
1166 * the planner, which doesn't require absolutely correct results;
1167 * it's OK (and expected) to guess if we don't know for sure.
1170 get_typavgwidth(Oid typid, int32 typmod)
1172 int typlen = get_typlen(typid);
1176 * Easy if it's a fixed-width type
1182 * type_maximum_size knows the encoding of typmod for some datatypes;
1183 * don't duplicate that knowledge here.
1185 maxwidth = type_maximum_size(typid, typmod);
1189 * For BPCHAR, the max width is also the only width. Otherwise we
1190 * need to guess about the typical data width given the max. A
1191 * sliding scale for percentage of max width seems reasonable.
1193 if (typid == BPCHAROID)
1196 return maxwidth; /* assume full width */
1197 if (maxwidth < 1000)
1198 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1201 * Beyond 1000, assume we're looking at something like
1202 * "varchar(10000)" where the limit isn't actually reached often,
1203 * and use a fixed estimate.
1205 return 32 + (1000 - 32) / 2;
1209 * Ooops, we have no idea ... wild guess time.
1217 * Given the type OID, find if it is a basic type, a complex type, etc.
1218 * It returns the null char if the cache lookup fails...
1221 get_typtype(Oid typid)
1225 tp = SearchSysCache(TYPEOID,
1226 ObjectIdGetDatum(typid),
1228 if (HeapTupleIsValid(tp))
1230 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1233 result = typtup->typtype;
1234 ReleaseSysCache(tp);
1244 * Given the type OID, get the typrelid (InvalidOid if not a complex
1248 get_typ_typrelid(Oid typid)
1252 tp = SearchSysCache(TYPEOID,
1253 ObjectIdGetDatum(typid),
1255 if (HeapTupleIsValid(tp))
1257 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1260 result = typtup->typrelid;
1261 ReleaseSysCache(tp);
1271 * Get info needed for converting values of a type to internal form
1274 getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem)
1276 HeapTuple typeTuple;
1279 typeTuple = SearchSysCache(TYPEOID,
1280 ObjectIdGetDatum(type),
1282 if (!HeapTupleIsValid(typeTuple))
1283 elog(ERROR, "getTypeInputInfo: Cache lookup of type %u failed", type);
1284 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1286 if (!pt->typisdefined)
1287 elog(ERROR, "Type \"%s\" is only a shell", NameStr(pt->typname));
1289 *typInput = pt->typinput;
1290 *typElem = pt->typelem;
1292 ReleaseSysCache(typeTuple);
1298 * Get info needed for printing values of a type
1300 * Returns true if data valid (a false result probably means it's a shell type)
1303 getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
1306 HeapTuple typeTuple;
1309 typeTuple = SearchSysCache(TYPEOID,
1310 ObjectIdGetDatum(type),
1312 if (!HeapTupleIsValid(typeTuple))
1313 elog(ERROR, "getTypeOutputInfo: Cache lookup of type %u failed", type);
1314 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1316 *typOutput = pt->typoutput;
1317 *typElem = pt->typelem;
1318 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1319 ReleaseSysCache(typeTuple);
1320 return OidIsValid(*typOutput);
1324 /* ---------- STATISTICS CACHE ---------- */
1329 * Given the table and attribute number of a column, get the average
1330 * width of entries in the column. Return zero if no data available.
1333 get_attavgwidth(Oid relid, AttrNumber attnum)
1337 tp = SearchSysCache(STATRELATT,
1338 ObjectIdGetDatum(relid),
1339 Int16GetDatum(attnum),
1341 if (HeapTupleIsValid(tp))
1343 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1345 ReleaseSysCache(tp);
1355 * Extract the contents of a "slot" of a pg_statistic tuple.
1356 * Returns TRUE if requested slot type was found, else FALSE.
1358 * Unlike other routines in this file, this takes a pointer to an
1359 * already-looked-up tuple in the pg_statistic cache. We do this since
1360 * most callers will want to extract more than one value from the cache
1361 * entry, and we don't want to repeat the cache lookup unnecessarily.
1363 * statstuple: pg_statistics tuple to be examined.
1364 * atttype: type OID of attribute.
1365 * atttypmod: typmod of attribute.
1366 * reqkind: STAKIND code for desired statistics slot kind.
1367 * reqop: STAOP value wanted, or InvalidOid if don't care.
1368 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1369 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1371 * If assigned, values and numbers are set to point to palloc'd arrays.
1372 * If the attribute type is pass-by-reference, the values referenced by
1373 * the values array are themselves palloc'd. The palloc'd stuff can be
1374 * freed by calling free_attstatsslot.
1377 get_attstatsslot(HeapTuple statstuple,
1378 Oid atttype, int32 atttypmod,
1379 int reqkind, Oid reqop,
1380 Datum **values, int *nvalues,
1381 float4 **numbers, int *nnumbers)
1383 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1388 ArrayType *statarray;
1390 HeapTuple typeTuple;
1391 Form_pg_type typeForm;
1393 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1395 if ((&stats->stakind1)[i] == reqkind &&
1396 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1399 if (i >= STATISTIC_NUM_SLOTS)
1400 return false; /* not there */
1404 val = SysCacheGetAttr(STATRELATT, statstuple,
1405 Anum_pg_statistic_stavalues1 + i,
1408 elog(ERROR, "get_attstatsslot: stavalues is null");
1409 statarray = DatumGetArrayTypeP(val);
1411 /* Need to get info about the array element type */
1412 typeTuple = SearchSysCache(TYPEOID,
1413 ObjectIdGetDatum(atttype),
1415 if (!HeapTupleIsValid(typeTuple))
1416 elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u",
1418 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1420 /* Deconstruct array into Datum elements */
1421 deconstruct_array(statarray,
1429 * If the element type is pass-by-reference, we now have a bunch
1430 * of Datums that are pointers into the syscache value. Copy them
1431 * to avoid problems if syscache decides to drop the entry.
1433 if (!typeForm->typbyval)
1435 for (j = 0; j < *nvalues; j++)
1437 (*values)[j] = datumCopy((*values)[j],
1443 ReleaseSysCache(typeTuple);
1446 * Free statarray if it's a detoasted copy.
1448 if ((Pointer) statarray != DatumGetPointer(val))
1454 val = SysCacheGetAttr(STATRELATT, statstuple,
1455 Anum_pg_statistic_stanumbers1 + i,
1458 elog(ERROR, "get_attstatsslot: stanumbers is null");
1459 statarray = DatumGetArrayTypeP(val);
1462 * We expect the array to be a 1-D float4 array; verify that. We
1463 * don't need to use deconstruct_array() since the array data is
1464 * just going to look like a C array of float4 values.
1466 narrayelem = ARR_DIMS(statarray)[0];
1467 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1468 ARR_ELEMTYPE(statarray) != FLOAT4OID)
1469 elog(ERROR, "get_attstatsslot: stanumbers is not a 1-D float4 array");
1470 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1471 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1472 *nnumbers = narrayelem;
1475 * Free statarray if it's a detoasted copy.
1477 if ((Pointer) statarray != DatumGetPointer(val))
1485 free_attstatsslot(Oid atttype,
1486 Datum *values, int nvalues,
1487 float4 *numbers, int nnumbers)
1491 if (!get_typbyval(atttype))
1495 for (i = 0; i < nvalues; i++)
1496 pfree(DatumGetPointer(values[i]));
1504 /* ---------- PG_NAMESPACE CACHE ---------- */
1507 * get_namespace_name
1508 * Returns the name of a given namespace
1510 * Returns a palloc'd copy of the string, or NULL if no such namespace.
1513 get_namespace_name(Oid nspid)
1517 tp = SearchSysCache(NAMESPACEOID,
1518 ObjectIdGetDatum(nspid),
1520 if (HeapTupleIsValid(tp))
1522 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
1525 result = pstrdup(NameStr(nsptup->nspname));
1526 ReleaseSysCache(tp);
1533 /* ---------- PG_SHADOW CACHE ---------- */
1538 * Given a user name, look up the user's sysid.
1539 * Raises an error if no such user (rather than returning zero,
1540 * which might possibly be a valid usesysid).
1542 * Note: the type of usesysid is currently int4, but may change to Oid
1543 * someday. It'd be reasonable to return zero on failure if we were
1547 get_usesysid(const char *username)
1552 userTup = SearchSysCache(SHADOWNAME,
1553 PointerGetDatum(username),
1555 if (!HeapTupleIsValid(userTup))
1556 elog(ERROR, "user \"%s\" does not exist", username);
1558 result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
1560 ReleaseSysCache(userTup);