1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2003, 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.107 2003/08/17 19:58:06 tgl Exp $
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
17 #include "miscadmin.h"
19 #include "access/hash.h"
20 #include "access/tupmacs.h"
21 #include "catalog/pg_amop.h"
22 #include "catalog/pg_amproc.h"
23 #include "catalog/pg_namespace.h"
24 #include "catalog/pg_opclass.h"
25 #include "catalog/pg_operator.h"
26 #include "catalog/pg_proc.h"
27 #include "catalog/pg_shadow.h"
28 #include "catalog/pg_statistic.h"
29 #include "catalog/pg_type.h"
30 #include "nodes/makefuncs.h"
31 #include "utils/array.h"
32 #include "utils/builtins.h"
33 #include "utils/catcache.h"
34 #include "utils/datum.h"
35 #include "utils/lsyscache.h"
36 #include "utils/syscache.h"
39 /* ---------- AMOP CACHES ---------- */
44 * Return t iff operator 'opno' is in operator class 'opclass'.
47 op_in_opclass(Oid opno, Oid opclass)
49 return SearchSysCacheExists(AMOPOPID,
50 ObjectIdGetDatum(opno),
51 ObjectIdGetDatum(opclass),
58 * Return t if operator 'opno' requires a recheck when used as a
59 * member of opclass 'opclass' (ie, this opclass is lossy for this
62 * Caller should already have verified that opno is a member of opclass,
63 * therefore we raise an error if the tuple is not found.
66 op_requires_recheck(Oid opno, Oid opclass)
69 Form_pg_amop amop_tup;
72 tp = SearchSysCache(AMOPOPID,
73 ObjectIdGetDatum(opno),
74 ObjectIdGetDatum(opclass),
76 if (!HeapTupleIsValid(tp))
77 elog(ERROR, "operator %u is not a member of opclass %u",
79 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
81 result = amop_tup->amopreqcheck;
88 * Get the OID of the operator that implements the specified strategy
89 * for the specified opclass.
91 * Returns InvalidOid if there is no pg_amop entry for the given keys.
94 get_opclass_member(Oid opclass, int16 strategy)
97 Form_pg_amop amop_tup;
100 tp = SearchSysCache(AMOPSTRATEGY,
101 ObjectIdGetDatum(opclass),
102 Int16GetDatum(strategy),
104 if (!HeapTupleIsValid(tp))
106 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
107 result = amop_tup->amopopr;
113 * get_op_hash_function
114 * Get the OID of the datatype-specific hash function associated with
115 * a hashable equality operator.
117 * Returns InvalidOid if no hash function can be found. (This indicates
118 * that the operator should not have been marked oprcanhash.)
121 get_op_hash_function(Oid opno)
125 Oid opclass = InvalidOid;
128 * Search pg_amop to see if the target operator is registered as the
129 * "=" operator of any hash opclass. If the operator is registered in
130 * multiple opclasses, assume we can use the associated hash function
133 catlist = SearchSysCacheList(AMOPOPID, 1,
134 ObjectIdGetDatum(opno),
137 for (i = 0; i < catlist->n_members; i++)
139 HeapTuple tuple = &catlist->members[i]->tuple;
140 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
142 if (aform->amopstrategy == HTEqualStrategyNumber &&
143 opclass_is_hash(aform->amopclaid))
145 opclass = aform->amopclaid;
150 ReleaseSysCacheList(catlist);
152 if (OidIsValid(opclass))
154 /* Found a suitable opclass, get its hash support function */
155 return get_opclass_proc(opclass, HASHPROC);
158 /* Didn't find a match... */
163 /* ---------- AMPROC CACHES ---------- */
167 * Get the OID of the specified support function
168 * for the specified opclass.
170 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
173 get_opclass_proc(Oid opclass, int16 procnum)
176 Form_pg_amproc amproc_tup;
179 tp = SearchSysCache(AMPROCNUM,
180 ObjectIdGetDatum(opclass),
181 Int16GetDatum(procnum),
183 if (!HeapTupleIsValid(tp))
185 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
186 result = amproc_tup->amproc;
192 /* ---------- ATTRIBUTE CACHES ---------- */
196 * Given the relation id and the attribute number,
197 * return the "attname" field from the attribute relation.
199 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
202 get_attname(Oid relid, AttrNumber attnum)
206 tp = SearchSysCache(ATTNUM,
207 ObjectIdGetDatum(relid),
208 Int16GetDatum(attnum),
210 if (HeapTupleIsValid(tp))
212 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
215 result = pstrdup(NameStr(att_tup->attname));
224 * get_relid_attribute_name
226 * Same as above routine get_attname(), except that error
227 * is handled by elog() instead of returning NULL.
230 get_relid_attribute_name(Oid relid, AttrNumber attnum)
234 attname = get_attname(relid, attnum);
236 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
244 * Given the relation id and the attribute name,
245 * return the "attnum" field from the attribute relation.
247 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
250 get_attnum(Oid relid, const char *attname)
254 tp = SearchSysCacheAttName(relid, attname);
255 if (HeapTupleIsValid(tp))
257 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
260 result = att_tup->attnum;
265 return InvalidAttrNumber;
271 * Given the relation OID and the attribute number with the relation,
272 * return the attribute type OID.
275 get_atttype(Oid relid, AttrNumber attnum)
279 tp = SearchSysCache(ATTNUM,
280 ObjectIdGetDatum(relid),
281 Int16GetDatum(attnum),
283 if (HeapTupleIsValid(tp))
285 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
288 result = att_tup->atttypid;
299 * Given the relation id and the attribute number,
300 * return the "atttypmod" field from the attribute relation.
303 get_atttypmod(Oid relid, AttrNumber attnum)
307 tp = SearchSysCache(ATTNUM,
308 ObjectIdGetDatum(relid),
309 Int16GetDatum(attnum),
311 if (HeapTupleIsValid(tp))
313 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
316 result = att_tup->atttypmod;
327 * A two-fer: given the relation id and the attribute number,
328 * fetch both type OID and atttypmod in a single cache lookup.
330 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
331 * raises an error if it can't obtain the information.
334 get_atttypetypmod(Oid relid, AttrNumber attnum,
335 Oid *typid, int32 *typmod)
338 Form_pg_attribute att_tup;
340 tp = SearchSysCache(ATTNUM,
341 ObjectIdGetDatum(relid),
342 Int16GetDatum(attnum),
344 if (!HeapTupleIsValid(tp))
345 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
347 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
349 *typid = att_tup->atttypid;
350 *typmod = att_tup->atttypmod;
354 /* ---------- INDEX CACHE ---------- */
356 /* watch this space...
359 /* ---------- OPCLASS CACHE ---------- */
364 * Returns TRUE iff the specified opclass is associated with the
365 * btree index access method.
368 opclass_is_btree(Oid opclass)
371 Form_pg_opclass cla_tup;
374 tp = SearchSysCache(CLAOID,
375 ObjectIdGetDatum(opclass),
377 if (!HeapTupleIsValid(tp))
378 elog(ERROR, "cache lookup failed for opclass %u", opclass);
379 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
381 result = (cla_tup->opcamid == BTREE_AM_OID);
389 * Returns TRUE iff the specified opclass is associated with the
390 * hash index access method.
393 opclass_is_hash(Oid opclass)
396 Form_pg_opclass cla_tup;
399 tp = SearchSysCache(CLAOID,
400 ObjectIdGetDatum(opclass),
402 if (!HeapTupleIsValid(tp))
403 elog(ERROR, "cache lookup failed for opclass %u", opclass);
404 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
406 result = (cla_tup->opcamid == HASH_AM_OID);
411 /* ---------- OPERATOR CACHE ---------- */
416 * Returns the regproc id of the routine used to implement an
417 * operator given the operator oid.
424 tp = SearchSysCache(OPEROID,
425 ObjectIdGetDatum(opno),
427 if (HeapTupleIsValid(tp))
429 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
432 result = optup->oprcode;
437 return (RegProcedure) InvalidOid;
442 * returns the name of the operator with the given opno
444 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
451 tp = SearchSysCache(OPEROID,
452 ObjectIdGetDatum(opno),
454 if (HeapTupleIsValid(tp))
456 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
459 result = pstrdup(NameStr(optup->oprname));
470 * Returns the left and right sort operators corresponding to a
471 * mergejoinable operator, or false if the operator is not mergejoinable.
474 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
479 tp = SearchSysCache(OPEROID,
480 ObjectIdGetDatum(opno),
482 if (HeapTupleIsValid(tp))
484 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
486 if (optup->oprlsortop &&
489 *leftOp = optup->oprlsortop;
490 *rightOp = optup->oprrsortop;
499 * op_mergejoin_crossops
501 * Returns the cross-type comparison operators (ltype "<" rtype and
502 * ltype ">" rtype) for an operator previously determined to be
503 * mergejoinable. Optionally, fetches the regproc ids of these
504 * operators, as well as their operator OIDs.
507 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
508 RegProcedure *ltproc, RegProcedure *gtproc)
511 Form_pg_operator optup;
514 * Get the declared comparison operators of the operator.
516 tp = SearchSysCache(OPEROID,
517 ObjectIdGetDatum(opno),
519 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
520 elog(ERROR, "cache lookup failed for operator %u", opno);
521 optup = (Form_pg_operator) GETSTRUCT(tp);
522 *ltop = optup->oprltcmpop;
523 *gtop = optup->oprgtcmpop;
526 /* Check < op provided */
527 if (!OidIsValid(*ltop))
528 elog(ERROR, "mergejoin operator %u has no matching < operator",
531 *ltproc = get_opcode(*ltop);
533 /* Check > op provided */
534 if (!OidIsValid(*gtop))
535 elog(ERROR, "mergejoin operator %u has no matching > operator",
538 *gtproc = get_opcode(*gtop);
544 * Returns true if the operator is hashjoinable.
547 op_hashjoinable(Oid opno)
552 tp = SearchSysCache(OPEROID,
553 ObjectIdGetDatum(opno),
555 if (HeapTupleIsValid(tp))
557 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
559 result = optup->oprcanhash;
568 * Get the proisstrict flag for the operator's underlying function.
573 RegProcedure funcid = get_opcode(opno);
575 if (funcid == (RegProcedure) InvalidOid)
576 elog(ERROR, "operator %u does not exist", opno);
578 return func_strict((Oid) funcid);
584 * Get the provolatile flag for the operator's underlying function.
587 op_volatile(Oid opno)
589 RegProcedure funcid = get_opcode(opno);
591 if (funcid == (RegProcedure) InvalidOid)
592 elog(ERROR, "operator %u does not exist", opno);
594 return func_volatile((Oid) funcid);
600 * Returns the corresponding commutator of an operator.
603 get_commutator(Oid opno)
607 tp = SearchSysCache(OPEROID,
608 ObjectIdGetDatum(opno),
610 if (HeapTupleIsValid(tp))
612 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
615 result = optup->oprcom;
626 * Returns the corresponding negator of an operator.
629 get_negator(Oid opno)
633 tp = SearchSysCache(OPEROID,
634 ObjectIdGetDatum(opno),
636 if (HeapTupleIsValid(tp))
638 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
641 result = optup->oprnegate;
652 * Returns procedure id for computing selectivity of an operator.
655 get_oprrest(Oid opno)
659 tp = SearchSysCache(OPEROID,
660 ObjectIdGetDatum(opno),
662 if (HeapTupleIsValid(tp))
664 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
667 result = optup->oprrest;
672 return (RegProcedure) InvalidOid;
678 * Returns procedure id for computing selectivity of a join.
681 get_oprjoin(Oid opno)
685 tp = SearchSysCache(OPEROID,
686 ObjectIdGetDatum(opno),
688 if (HeapTupleIsValid(tp))
690 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
693 result = optup->oprjoin;
698 return (RegProcedure) InvalidOid;
701 /* ---------- FUNCTION CACHE ---------- */
705 * returns the name of the function with the given funcid
707 * Note: returns a palloc'd copy of the string, or NULL if no such function.
710 get_func_name(Oid funcid)
714 tp = SearchSysCache(PROCOID,
715 ObjectIdGetDatum(funcid),
717 if (HeapTupleIsValid(tp))
719 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
722 result = pstrdup(NameStr(functup->proname));
732 * Given procedure id, return the function's result type.
735 get_func_rettype(Oid funcid)
740 tp = SearchSysCache(PROCOID,
741 ObjectIdGetDatum(funcid),
743 if (!HeapTupleIsValid(tp))
744 elog(ERROR, "cache lookup failed for function %u", funcid);
746 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
753 * Given procedure id, return the function's argument and result types.
754 * (The return value is the result type.)
756 * argtypes must point to a vector of size FUNC_MAX_ARGS.
759 get_func_signature(Oid funcid, Oid *argtypes, int *nargs)
762 Form_pg_proc procstruct;
765 tp = SearchSysCache(PROCOID,
766 ObjectIdGetDatum(funcid),
768 if (!HeapTupleIsValid(tp))
769 elog(ERROR, "cache lookup failed for function %u", funcid);
771 procstruct = (Form_pg_proc) GETSTRUCT(tp);
773 result = procstruct->prorettype;
774 memcpy(argtypes, procstruct->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
775 *nargs = (int) procstruct->pronargs;
783 * Given procedure id, return the function's proretset flag.
786 get_func_retset(Oid funcid)
791 tp = SearchSysCache(PROCOID,
792 ObjectIdGetDatum(funcid),
794 if (!HeapTupleIsValid(tp))
795 elog(ERROR, "cache lookup failed for function %u", funcid);
797 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
804 * Given procedure id, return the function's proisstrict flag.
807 func_strict(Oid funcid)
812 tp = SearchSysCache(PROCOID,
813 ObjectIdGetDatum(funcid),
815 if (!HeapTupleIsValid(tp))
816 elog(ERROR, "cache lookup failed for function %u", funcid);
818 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
825 * Given procedure id, return the function's provolatile flag.
828 func_volatile(Oid funcid)
833 tp = SearchSysCache(PROCOID,
834 ObjectIdGetDatum(funcid),
836 if (!HeapTupleIsValid(tp))
837 elog(ERROR, "cache lookup failed for function %u", funcid);
839 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
844 /* ---------- RELATION CACHE ---------- */
848 * Given name and namespace of a relation, look up the OID.
850 * Returns InvalidOid if there is no such relation.
853 get_relname_relid(const char *relname, Oid relnamespace)
855 return GetSysCacheOid(RELNAMENSP,
856 PointerGetDatum(relname),
857 ObjectIdGetDatum(relnamespace),
862 * get_system_catalog_relid
863 * Get the OID of a system catalog identified by name.
866 get_system_catalog_relid(const char *catname)
870 relid = GetSysCacheOid(RELNAMENSP,
871 PointerGetDatum(catname),
872 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
874 if (!OidIsValid(relid))
875 elog(ERROR, "cache lookup failed for system relation %s", catname);
884 * Returns the number of attributes for a given relation.
887 get_relnatts(Oid relid)
891 tp = SearchSysCache(RELOID,
892 ObjectIdGetDatum(relid),
894 if (HeapTupleIsValid(tp))
896 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
899 result = reltup->relnatts;
904 return InvalidAttrNumber;
910 * Returns the name of a given relation.
912 * Returns a palloc'd copy of the string, or NULL if no such relation.
914 * NOTE: since relation name is not unique, be wary of code that uses this
915 * for anything except preparing error messages.
918 get_rel_name(Oid relid)
922 tp = SearchSysCache(RELOID,
923 ObjectIdGetDatum(relid),
925 if (HeapTupleIsValid(tp))
927 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
930 result = pstrdup(NameStr(reltup->relname));
941 * Returns the pg_namespace OID associated with a given relation.
944 get_rel_namespace(Oid relid)
948 tp = SearchSysCache(RELOID,
949 ObjectIdGetDatum(relid),
951 if (HeapTupleIsValid(tp))
953 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
956 result = reltup->relnamespace;
967 * Returns the pg_type OID associated with a given relation.
969 * Note: not all pg_class entries have associated pg_type OIDs; so be
970 * careful to check for InvalidOid result.
973 get_rel_type_id(Oid relid)
977 tp = SearchSysCache(RELOID,
978 ObjectIdGetDatum(relid),
980 if (HeapTupleIsValid(tp))
982 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
985 result = reltup->reltype;
996 * Returns the relkind associated with a given relation.
999 get_rel_relkind(Oid relid)
1003 tp = SearchSysCache(RELOID,
1004 ObjectIdGetDatum(relid),
1006 if (HeapTupleIsValid(tp))
1008 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1011 result = reltup->relkind;
1012 ReleaseSysCache(tp);
1020 /* ---------- TYPE CACHE ---------- */
1025 * Given the type OID, determine whether the type is defined
1026 * (if not, it's only a shell).
1029 get_typisdefined(Oid typid)
1033 tp = SearchSysCache(TYPEOID,
1034 ObjectIdGetDatum(typid),
1036 if (HeapTupleIsValid(tp))
1038 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1041 result = typtup->typisdefined;
1042 ReleaseSysCache(tp);
1052 * Given the type OID, return the length of the type.
1055 get_typlen(Oid typid)
1059 tp = SearchSysCache(TYPEOID,
1060 ObjectIdGetDatum(typid),
1062 if (HeapTupleIsValid(tp))
1064 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1067 result = typtup->typlen;
1068 ReleaseSysCache(tp);
1078 * Given the type OID, determine whether the type is returned by value or
1079 * not. Returns true if by value, false if by reference.
1082 get_typbyval(Oid typid)
1086 tp = SearchSysCache(TYPEOID,
1087 ObjectIdGetDatum(typid),
1089 if (HeapTupleIsValid(tp))
1091 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1094 result = typtup->typbyval;
1095 ReleaseSysCache(tp);
1105 * A two-fer: given the type OID, return both typlen and typbyval.
1107 * Since both pieces of info are needed to know how to copy a Datum,
1108 * many places need both. Might as well get them with one cache lookup
1109 * instead of two. Also, this routine raises an error instead of
1110 * returning a bogus value when given a bad type OID.
1113 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1116 Form_pg_type typtup;
1118 tp = SearchSysCache(TYPEOID,
1119 ObjectIdGetDatum(typid),
1121 if (!HeapTupleIsValid(tp))
1122 elog(ERROR, "cache lookup failed for type %u", typid);
1123 typtup = (Form_pg_type) GETSTRUCT(tp);
1124 *typlen = typtup->typlen;
1125 *typbyval = typtup->typbyval;
1126 ReleaseSysCache(tp);
1130 * get_typlenbyvalalign
1132 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1135 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1139 Form_pg_type typtup;
1141 tp = SearchSysCache(TYPEOID,
1142 ObjectIdGetDatum(typid),
1144 if (!HeapTupleIsValid(tp))
1145 elog(ERROR, "cache lookup failed for type %u", typid);
1146 typtup = (Form_pg_type) GETSTRUCT(tp);
1147 *typlen = typtup->typlen;
1148 *typbyval = typtup->typbyval;
1149 *typalign = typtup->typalign;
1150 ReleaseSysCache(tp);
1156 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1157 * typdelim, typelem, and IO function OID. The IO function
1158 * returned is controlled by IOFuncSelector
1161 get_type_io_data(Oid typid,
1162 IOFuncSelector which_func,
1170 HeapTuple typeTuple;
1171 Form_pg_type typeStruct;
1173 typeTuple = SearchSysCache(TYPEOID,
1174 ObjectIdGetDatum(typid),
1176 if (!HeapTupleIsValid(typeTuple))
1177 elog(ERROR, "cache lookup failed for type %u", typid);
1178 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1180 *typlen = typeStruct->typlen;
1181 *typbyval = typeStruct->typbyval;
1182 *typalign = typeStruct->typalign;
1183 *typdelim = typeStruct->typdelim;
1184 *typelem = typeStruct->typelem;
1188 *func = typeStruct->typinput;
1191 *func = typeStruct->typoutput;
1193 case IOFunc_receive:
1194 *func = typeStruct->typreceive;
1197 *func = typeStruct->typsend;
1200 ReleaseSysCache(typeTuple);
1205 get_typalign(Oid typid)
1209 tp = SearchSysCache(TYPEOID,
1210 ObjectIdGetDatum(typid),
1212 if (HeapTupleIsValid(tp))
1214 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1217 result = typtup->typalign;
1218 ReleaseSysCache(tp);
1227 get_typstorage(Oid typid)
1231 tp = SearchSysCache(TYPEOID,
1232 ObjectIdGetDatum(typid),
1234 if (HeapTupleIsValid(tp))
1236 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1239 result = typtup->typstorage;
1240 ReleaseSysCache(tp);
1250 * Given the type OID, return the typtypmod field (domain's typmod
1254 get_typtypmod(Oid typid)
1258 tp = SearchSysCache(TYPEOID,
1259 ObjectIdGetDatum(typid),
1261 if (HeapTupleIsValid(tp))
1263 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1266 result = typtup->typtypmod;
1267 ReleaseSysCache(tp);
1276 * Given a type OID, return the type's default value, if any.
1278 * The result is a palloc'd expression node tree, or NULL if there
1279 * is no defined default for the datatype.
1281 * NB: caller should be prepared to coerce result to correct datatype;
1282 * the returned expression tree might produce something of the wrong type.
1285 get_typdefault(Oid typid)
1287 HeapTuple typeTuple;
1293 typeTuple = SearchSysCache(TYPEOID,
1294 ObjectIdGetDatum(typid),
1296 if (!HeapTupleIsValid(typeTuple))
1297 elog(ERROR, "cache lookup failed for type %u", typid);
1298 type = (Form_pg_type) GETSTRUCT(typeTuple);
1301 * typdefault and typdefaultbin are potentially null, so don't try to
1302 * access 'em as struct fields. Must do it the hard way with
1305 datum = SysCacheGetAttr(TYPEOID,
1307 Anum_pg_type_typdefaultbin,
1312 /* We have an expression default */
1313 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1318 /* Perhaps we have a plain literal default */
1319 datum = SysCacheGetAttr(TYPEOID,
1321 Anum_pg_type_typdefault,
1326 char *strDefaultVal;
1328 /* Convert text datum to C string */
1329 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1331 /* Convert C string to a value of the given type */
1332 datum = OidFunctionCall3(type->typinput,
1333 CStringGetDatum(strDefaultVal),
1334 ObjectIdGetDatum(type->typelem),
1336 /* Build a Const node containing the value */
1337 expr = (Node *) makeConst(typid,
1342 pfree(strDefaultVal);
1351 ReleaseSysCache(typeTuple);
1358 * If the given type is a domain, return its base type;
1359 * otherwise return the type's own OID.
1362 getBaseType(Oid typid)
1365 * We loop to find the bottom base type in a stack of domains.
1370 Form_pg_type typTup;
1372 tup = SearchSysCache(TYPEOID,
1373 ObjectIdGetDatum(typid),
1375 if (!HeapTupleIsValid(tup))
1376 elog(ERROR, "cache lookup failed for type %u", typid);
1377 typTup = (Form_pg_type) GETSTRUCT(tup);
1378 if (typTup->typtype != 'd')
1380 /* Not a domain, so done */
1381 ReleaseSysCache(tup);
1385 typid = typTup->typbasetype;
1386 ReleaseSysCache(tup);
1395 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1396 * estimate the average width of values of the type. This is used by
1397 * the planner, which doesn't require absolutely correct results;
1398 * it's OK (and expected) to guess if we don't know for sure.
1401 get_typavgwidth(Oid typid, int32 typmod)
1403 int typlen = get_typlen(typid);
1407 * Easy if it's a fixed-width type
1413 * type_maximum_size knows the encoding of typmod for some datatypes;
1414 * don't duplicate that knowledge here.
1416 maxwidth = type_maximum_size(typid, typmod);
1420 * For BPCHAR, the max width is also the only width. Otherwise we
1421 * need to guess about the typical data width given the max. A
1422 * sliding scale for percentage of max width seems reasonable.
1424 if (typid == BPCHAROID)
1427 return maxwidth; /* assume full width */
1428 if (maxwidth < 1000)
1429 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1432 * Beyond 1000, assume we're looking at something like
1433 * "varchar(10000)" where the limit isn't actually reached often,
1434 * and use a fixed estimate.
1436 return 32 + (1000 - 32) / 2;
1440 * Ooops, we have no idea ... wild guess time.
1448 * Given the type OID, find if it is a basic type, a complex type, etc.
1449 * It returns the null char if the cache lookup fails...
1452 get_typtype(Oid typid)
1456 tp = SearchSysCache(TYPEOID,
1457 ObjectIdGetDatum(typid),
1459 if (HeapTupleIsValid(tp))
1461 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1464 result = typtup->typtype;
1465 ReleaseSysCache(tp);
1474 * Returns the name of a given type.
1476 * Returns a palloc'd copy of the string, or NULL if no such type.
1478 * NOTE: since type name is not unique, be wary of code that uses this
1479 * for anything except preparing error messages.
1482 get_typname(Oid typid)
1486 tp = SearchSysCache(TYPEOID,
1487 ObjectIdGetDatum(typid),
1489 if (HeapTupleIsValid(tp))
1491 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1494 result = pstrdup(NameStr(typtup->typname));
1495 ReleaseSysCache(tp);
1506 * Given the type OID, get the typrelid (InvalidOid if not a complex
1510 get_typ_typrelid(Oid typid)
1514 tp = SearchSysCache(TYPEOID,
1515 ObjectIdGetDatum(typid),
1517 if (HeapTupleIsValid(tp))
1519 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1522 result = typtup->typrelid;
1523 ReleaseSysCache(tp);
1533 * Given the type OID, get the typelem (InvalidOid if not an array type).
1535 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
1536 * returned if the input is a fixed-length array type.
1539 get_element_type(Oid typid)
1543 tp = SearchSysCache(TYPEOID,
1544 ObjectIdGetDatum(typid),
1546 if (HeapTupleIsValid(tp))
1548 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1551 if (typtup->typlen == -1)
1552 result = typtup->typelem;
1554 result = InvalidOid;
1555 ReleaseSysCache(tp);
1565 * Given the type OID, get the corresponding array type.
1566 * Returns InvalidOid if no array type can be found.
1568 * NB: this only considers varlena arrays to be true arrays.
1571 get_array_type(Oid typid)
1575 tp = SearchSysCache(TYPEOID,
1576 ObjectIdGetDatum(typid),
1578 if (HeapTupleIsValid(tp))
1580 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1581 char *array_typename;
1584 array_typename = makeArrayTypeName(NameStr(typtup->typname));
1585 namespaceId = typtup->typnamespace;
1586 ReleaseSysCache(tp);
1588 tp = SearchSysCache(TYPENAMENSP,
1589 PointerGetDatum(array_typename),
1590 ObjectIdGetDatum(namespaceId),
1593 pfree(array_typename);
1595 if (HeapTupleIsValid(tp))
1599 typtup = (Form_pg_type) GETSTRUCT(tp);
1600 if (typtup->typlen == -1 && typtup->typelem == typid)
1601 result = HeapTupleGetOid(tp);
1603 result = InvalidOid;
1604 ReleaseSysCache(tp);
1614 * Get info needed for converting values of a type to internal form
1617 getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem)
1619 HeapTuple typeTuple;
1622 typeTuple = SearchSysCache(TYPEOID,
1623 ObjectIdGetDatum(type),
1625 if (!HeapTupleIsValid(typeTuple))
1626 elog(ERROR, "cache lookup failed for type %u", type);
1627 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1629 if (!pt->typisdefined)
1631 (errcode(ERRCODE_UNDEFINED_OBJECT),
1632 errmsg("type %s is only a shell",
1633 format_type_be(type))));
1634 if (!OidIsValid(pt->typinput))
1636 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1637 errmsg("no input function available for type %s",
1638 format_type_be(type))));
1640 *typInput = pt->typinput;
1641 *typElem = pt->typelem;
1643 ReleaseSysCache(typeTuple);
1649 * Get info needed for printing values of a type
1652 getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
1655 HeapTuple typeTuple;
1658 typeTuple = SearchSysCache(TYPEOID,
1659 ObjectIdGetDatum(type),
1661 if (!HeapTupleIsValid(typeTuple))
1662 elog(ERROR, "cache lookup failed for type %u", type);
1663 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1665 if (!pt->typisdefined)
1667 (errcode(ERRCODE_UNDEFINED_OBJECT),
1668 errmsg("type %s is only a shell",
1669 format_type_be(type))));
1670 if (!OidIsValid(pt->typoutput))
1672 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1673 errmsg("no output function available for type %s",
1674 format_type_be(type))));
1676 *typOutput = pt->typoutput;
1677 *typElem = pt->typelem;
1678 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1680 ReleaseSysCache(typeTuple);
1684 * getTypeBinaryInputInfo
1686 * Get info needed for binary input of values of a type
1689 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typElem)
1691 HeapTuple typeTuple;
1694 typeTuple = SearchSysCache(TYPEOID,
1695 ObjectIdGetDatum(type),
1697 if (!HeapTupleIsValid(typeTuple))
1698 elog(ERROR, "cache lookup failed for type %u", type);
1699 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1701 if (!pt->typisdefined)
1703 (errcode(ERRCODE_UNDEFINED_OBJECT),
1704 errmsg("type %s is only a shell",
1705 format_type_be(type))));
1706 if (!OidIsValid(pt->typreceive))
1708 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1709 errmsg("no binary input function available for type %s",
1710 format_type_be(type))));
1712 *typReceive = pt->typreceive;
1713 *typElem = pt->typelem;
1715 ReleaseSysCache(typeTuple);
1719 * getTypeBinaryOutputInfo
1721 * Get info needed for binary output of values of a type
1724 getTypeBinaryOutputInfo(Oid type, Oid *typSend, Oid *typElem,
1727 HeapTuple typeTuple;
1730 typeTuple = SearchSysCache(TYPEOID,
1731 ObjectIdGetDatum(type),
1733 if (!HeapTupleIsValid(typeTuple))
1734 elog(ERROR, "cache lookup failed for type %u", type);
1735 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1737 if (!pt->typisdefined)
1739 (errcode(ERRCODE_UNDEFINED_OBJECT),
1740 errmsg("type %s is only a shell",
1741 format_type_be(type))));
1742 if (!OidIsValid(pt->typsend))
1744 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1745 errmsg("no binary output function available for type %s",
1746 format_type_be(type))));
1748 *typSend = pt->typsend;
1749 *typElem = pt->typelem;
1750 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1752 ReleaseSysCache(typeTuple);
1756 /* ---------- STATISTICS CACHE ---------- */
1761 * Given the table and attribute number of a column, get the average
1762 * width of entries in the column. Return zero if no data available.
1765 get_attavgwidth(Oid relid, AttrNumber attnum)
1769 tp = SearchSysCache(STATRELATT,
1770 ObjectIdGetDatum(relid),
1771 Int16GetDatum(attnum),
1773 if (HeapTupleIsValid(tp))
1775 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1777 ReleaseSysCache(tp);
1787 * Extract the contents of a "slot" of a pg_statistic tuple.
1788 * Returns TRUE if requested slot type was found, else FALSE.
1790 * Unlike other routines in this file, this takes a pointer to an
1791 * already-looked-up tuple in the pg_statistic cache. We do this since
1792 * most callers will want to extract more than one value from the cache
1793 * entry, and we don't want to repeat the cache lookup unnecessarily.
1795 * statstuple: pg_statistics tuple to be examined.
1796 * atttype: type OID of attribute.
1797 * atttypmod: typmod of attribute.
1798 * reqkind: STAKIND code for desired statistics slot kind.
1799 * reqop: STAOP value wanted, or InvalidOid if don't care.
1800 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1801 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1803 * If assigned, values and numbers are set to point to palloc'd arrays.
1804 * If the attribute type is pass-by-reference, the values referenced by
1805 * the values array are themselves palloc'd. The palloc'd stuff can be
1806 * freed by calling free_attstatsslot.
1809 get_attstatsslot(HeapTuple statstuple,
1810 Oid atttype, int32 atttypmod,
1811 int reqkind, Oid reqop,
1812 Datum **values, int *nvalues,
1813 float4 **numbers, int *nnumbers)
1815 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1820 ArrayType *statarray;
1822 HeapTuple typeTuple;
1823 Form_pg_type typeForm;
1825 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1827 if ((&stats->stakind1)[i] == reqkind &&
1828 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1831 if (i >= STATISTIC_NUM_SLOTS)
1832 return false; /* not there */
1836 val = SysCacheGetAttr(STATRELATT, statstuple,
1837 Anum_pg_statistic_stavalues1 + i,
1840 elog(ERROR, "stavalues is null");
1841 statarray = DatumGetArrayTypeP(val);
1843 /* Need to get info about the array element type */
1844 typeTuple = SearchSysCache(TYPEOID,
1845 ObjectIdGetDatum(atttype),
1847 if (!HeapTupleIsValid(typeTuple))
1848 elog(ERROR, "cache lookup failed for type %u", atttype);
1849 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1851 /* Deconstruct array into Datum elements */
1852 deconstruct_array(statarray,
1860 * If the element type is pass-by-reference, we now have a bunch
1861 * of Datums that are pointers into the syscache value. Copy them
1862 * to avoid problems if syscache decides to drop the entry.
1864 if (!typeForm->typbyval)
1866 for (j = 0; j < *nvalues; j++)
1868 (*values)[j] = datumCopy((*values)[j],
1874 ReleaseSysCache(typeTuple);
1877 * Free statarray if it's a detoasted copy.
1879 if ((Pointer) statarray != DatumGetPointer(val))
1885 val = SysCacheGetAttr(STATRELATT, statstuple,
1886 Anum_pg_statistic_stanumbers1 + i,
1889 elog(ERROR, "stanumbers is null");
1890 statarray = DatumGetArrayTypeP(val);
1893 * We expect the array to be a 1-D float4 array; verify that. We
1894 * don't need to use deconstruct_array() since the array data is
1895 * just going to look like a C array of float4 values.
1897 narrayelem = ARR_DIMS(statarray)[0];
1898 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1899 ARR_ELEMTYPE(statarray) != FLOAT4OID)
1900 elog(ERROR, "stanumbers is not a 1-D float4 array");
1901 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1902 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1903 *nnumbers = narrayelem;
1906 * Free statarray if it's a detoasted copy.
1908 if ((Pointer) statarray != DatumGetPointer(val))
1916 free_attstatsslot(Oid atttype,
1917 Datum *values, int nvalues,
1918 float4 *numbers, int nnumbers)
1922 if (!get_typbyval(atttype))
1926 for (i = 0; i < nvalues; i++)
1927 pfree(DatumGetPointer(values[i]));
1935 /* ---------- PG_NAMESPACE CACHE ---------- */
1938 * get_namespace_name
1939 * Returns the name of a given namespace
1941 * Returns a palloc'd copy of the string, or NULL if no such namespace.
1944 get_namespace_name(Oid nspid)
1948 tp = SearchSysCache(NAMESPACEOID,
1949 ObjectIdGetDatum(nspid),
1951 if (HeapTupleIsValid(tp))
1953 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
1956 result = pstrdup(NameStr(nsptup->nspname));
1957 ReleaseSysCache(tp);
1964 /* ---------- PG_SHADOW CACHE ---------- */
1969 * Given a user name, look up the user's sysid.
1970 * Raises an error if no such user (rather than returning zero,
1971 * which might possibly be a valid usesysid).
1973 * Note: the type of usesysid is currently int4, but may change to Oid
1974 * someday. It'd be reasonable to return zero on failure if we were
1978 get_usesysid(const char *username)
1983 userTup = SearchSysCache(SHADOWNAME,
1984 PointerGetDatum(username),
1986 if (!HeapTupleIsValid(userTup))
1988 (errcode(ERRCODE_UNDEFINED_OBJECT),
1989 errmsg("user \"%s\" does not exist", username)));
1991 result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
1993 ReleaseSysCache(userTup);