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 * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.113 2004/06/06 00:41:27 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),
56 * get_op_opclass_properties
58 * Get the operator's strategy number, subtype, and recheck (lossy) flag
59 * within the specified opclass.
61 * Caller should already have verified that opno is a member of opclass,
62 * therefore we raise an error if the tuple is not found.
65 get_op_opclass_properties(Oid opno, Oid opclass,
66 int *strategy, Oid *subtype, bool *recheck)
69 Form_pg_amop amop_tup;
71 tp = SearchSysCache(AMOPOPID,
72 ObjectIdGetDatum(opno),
73 ObjectIdGetDatum(opclass),
75 if (!HeapTupleIsValid(tp))
76 elog(ERROR, "operator %u is not a member of opclass %u",
78 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
79 *strategy = amop_tup->amopstrategy;
80 *subtype = amop_tup->amopsubtype;
81 *recheck = amop_tup->amopreqcheck;
87 * Get the OID of the operator that implements the specified strategy
88 * with the specified subtype for the specified opclass.
90 * Returns InvalidOid if there is no pg_amop entry for the given keys.
93 get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
96 Form_pg_amop amop_tup;
99 tp = SearchSysCache(AMOPSTRATEGY,
100 ObjectIdGetDatum(opclass),
101 ObjectIdGetDatum(subtype),
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 default hash support function */
155 return get_opclass_proc(opclass, InvalidOid, HASHPROC);
158 /* Didn't find a match... */
163 /* ---------- AMPROC CACHES ---------- */
167 * Get the OID of the specified support function
168 * for the specified opclass and subtype.
170 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
173 get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
176 Form_pg_amproc amproc_tup;
179 tp = SearchSysCache(AMPROCNUM,
180 ObjectIdGetDatum(opclass),
181 ObjectIdGetDatum(subtype),
182 Int16GetDatum(procnum),
184 if (!HeapTupleIsValid(tp))
186 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
187 result = amproc_tup->amproc;
193 /* ---------- ATTRIBUTE CACHES ---------- */
197 * Given the relation id and the attribute number,
198 * return the "attname" field from the attribute relation.
200 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
203 get_attname(Oid relid, AttrNumber attnum)
207 tp = SearchSysCache(ATTNUM,
208 ObjectIdGetDatum(relid),
209 Int16GetDatum(attnum),
211 if (HeapTupleIsValid(tp))
213 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
216 result = pstrdup(NameStr(att_tup->attname));
225 * get_relid_attribute_name
227 * Same as above routine get_attname(), except that error
228 * is handled by elog() instead of returning NULL.
231 get_relid_attribute_name(Oid relid, AttrNumber attnum)
235 attname = get_attname(relid, attnum);
237 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
245 * Given the relation id and the attribute name,
246 * return the "attnum" field from the attribute relation.
248 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
251 get_attnum(Oid relid, const char *attname)
255 tp = SearchSysCacheAttName(relid, attname);
256 if (HeapTupleIsValid(tp))
258 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
261 result = att_tup->attnum;
266 return InvalidAttrNumber;
272 * Given the relation OID and the attribute number with the relation,
273 * return the attribute type OID.
276 get_atttype(Oid relid, AttrNumber attnum)
280 tp = SearchSysCache(ATTNUM,
281 ObjectIdGetDatum(relid),
282 Int16GetDatum(attnum),
284 if (HeapTupleIsValid(tp))
286 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
289 result = att_tup->atttypid;
300 * Given the relation id and the attribute number,
301 * return the "atttypmod" field from the attribute relation.
304 get_atttypmod(Oid relid, AttrNumber attnum)
308 tp = SearchSysCache(ATTNUM,
309 ObjectIdGetDatum(relid),
310 Int16GetDatum(attnum),
312 if (HeapTupleIsValid(tp))
314 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
317 result = att_tup->atttypmod;
328 * A two-fer: given the relation id and the attribute number,
329 * fetch both type OID and atttypmod in a single cache lookup.
331 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
332 * raises an error if it can't obtain the information.
335 get_atttypetypmod(Oid relid, AttrNumber attnum,
336 Oid *typid, int32 *typmod)
339 Form_pg_attribute att_tup;
341 tp = SearchSysCache(ATTNUM,
342 ObjectIdGetDatum(relid),
343 Int16GetDatum(attnum),
345 if (!HeapTupleIsValid(tp))
346 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
348 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
350 *typid = att_tup->atttypid;
351 *typmod = att_tup->atttypmod;
355 /* ---------- INDEX CACHE ---------- */
357 /* watch this space...
360 /* ---------- OPCLASS CACHE ---------- */
365 * Returns TRUE iff the specified opclass is associated with the
366 * btree index access method.
369 opclass_is_btree(Oid opclass)
372 Form_pg_opclass cla_tup;
375 tp = SearchSysCache(CLAOID,
376 ObjectIdGetDatum(opclass),
378 if (!HeapTupleIsValid(tp))
379 elog(ERROR, "cache lookup failed for opclass %u", opclass);
380 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
382 result = (cla_tup->opcamid == BTREE_AM_OID);
390 * Returns TRUE iff the specified opclass is associated with the
391 * hash index access method.
394 opclass_is_hash(Oid opclass)
397 Form_pg_opclass cla_tup;
400 tp = SearchSysCache(CLAOID,
401 ObjectIdGetDatum(opclass),
403 if (!HeapTupleIsValid(tp))
404 elog(ERROR, "cache lookup failed for opclass %u", opclass);
405 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
407 result = (cla_tup->opcamid == HASH_AM_OID);
412 /* ---------- OPERATOR CACHE ---------- */
417 * Returns the regproc id of the routine used to implement an
418 * operator given the operator oid.
425 tp = SearchSysCache(OPEROID,
426 ObjectIdGetDatum(opno),
428 if (HeapTupleIsValid(tp))
430 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
433 result = optup->oprcode;
438 return (RegProcedure) InvalidOid;
443 * returns the name of the operator with the given opno
445 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
452 tp = SearchSysCache(OPEROID,
453 ObjectIdGetDatum(opno),
455 if (HeapTupleIsValid(tp))
457 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
460 result = pstrdup(NameStr(optup->oprname));
471 * Returns the left and right input datatypes for an operator
472 * (InvalidOid if not relevant).
475 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
478 Form_pg_operator optup;
480 tp = SearchSysCache(OPEROID,
481 ObjectIdGetDatum(opno),
483 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
484 elog(ERROR, "cache lookup failed for operator %u", opno);
485 optup = (Form_pg_operator) GETSTRUCT(tp);
486 *lefttype = optup->oprleft;
487 *righttype = optup->oprright;
494 * Returns the left and right sort operators corresponding to a
495 * mergejoinable operator, or false if the operator is not mergejoinable.
498 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
503 tp = SearchSysCache(OPEROID,
504 ObjectIdGetDatum(opno),
506 if (HeapTupleIsValid(tp))
508 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
510 if (optup->oprlsortop &&
513 *leftOp = optup->oprlsortop;
514 *rightOp = optup->oprrsortop;
523 * op_mergejoin_crossops
525 * Returns the cross-type comparison operators (ltype "<" rtype and
526 * ltype ">" rtype) for an operator previously determined to be
527 * mergejoinable. Optionally, fetches the regproc ids of these
528 * operators, as well as their operator OIDs.
531 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
532 RegProcedure *ltproc, RegProcedure *gtproc)
535 Form_pg_operator optup;
538 * Get the declared comparison operators of the operator.
540 tp = SearchSysCache(OPEROID,
541 ObjectIdGetDatum(opno),
543 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
544 elog(ERROR, "cache lookup failed for operator %u", opno);
545 optup = (Form_pg_operator) GETSTRUCT(tp);
546 *ltop = optup->oprltcmpop;
547 *gtop = optup->oprgtcmpop;
550 /* Check < op provided */
551 if (!OidIsValid(*ltop))
552 elog(ERROR, "mergejoin operator %u has no matching < operator",
555 *ltproc = get_opcode(*ltop);
557 /* Check > op provided */
558 if (!OidIsValid(*gtop))
559 elog(ERROR, "mergejoin operator %u has no matching > operator",
562 *gtproc = get_opcode(*gtop);
568 * Returns true if the operator is hashjoinable.
571 op_hashjoinable(Oid opno)
576 tp = SearchSysCache(OPEROID,
577 ObjectIdGetDatum(opno),
579 if (HeapTupleIsValid(tp))
581 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
583 result = optup->oprcanhash;
592 * Get the proisstrict flag for the operator's underlying function.
597 RegProcedure funcid = get_opcode(opno);
599 if (funcid == (RegProcedure) InvalidOid)
600 elog(ERROR, "operator %u does not exist", opno);
602 return func_strict((Oid) funcid);
608 * Get the provolatile flag for the operator's underlying function.
611 op_volatile(Oid opno)
613 RegProcedure funcid = get_opcode(opno);
615 if (funcid == (RegProcedure) InvalidOid)
616 elog(ERROR, "operator %u does not exist", opno);
618 return func_volatile((Oid) funcid);
624 * Returns the corresponding commutator of an operator.
627 get_commutator(Oid opno)
631 tp = SearchSysCache(OPEROID,
632 ObjectIdGetDatum(opno),
634 if (HeapTupleIsValid(tp))
636 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
639 result = optup->oprcom;
650 * Returns the corresponding negator of an operator.
653 get_negator(Oid opno)
657 tp = SearchSysCache(OPEROID,
658 ObjectIdGetDatum(opno),
660 if (HeapTupleIsValid(tp))
662 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
665 result = optup->oprnegate;
676 * Returns procedure id for computing selectivity of an operator.
679 get_oprrest(Oid opno)
683 tp = SearchSysCache(OPEROID,
684 ObjectIdGetDatum(opno),
686 if (HeapTupleIsValid(tp))
688 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
691 result = optup->oprrest;
696 return (RegProcedure) InvalidOid;
702 * Returns procedure id for computing selectivity of a join.
705 get_oprjoin(Oid opno)
709 tp = SearchSysCache(OPEROID,
710 ObjectIdGetDatum(opno),
712 if (HeapTupleIsValid(tp))
714 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
717 result = optup->oprjoin;
722 return (RegProcedure) InvalidOid;
725 /* ---------- FUNCTION CACHE ---------- */
729 * returns the name of the function with the given funcid
731 * Note: returns a palloc'd copy of the string, or NULL if no such function.
734 get_func_name(Oid funcid)
738 tp = SearchSysCache(PROCOID,
739 ObjectIdGetDatum(funcid),
741 if (HeapTupleIsValid(tp))
743 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
746 result = pstrdup(NameStr(functup->proname));
756 * Given procedure id, return the function's result type.
759 get_func_rettype(Oid funcid)
764 tp = SearchSysCache(PROCOID,
765 ObjectIdGetDatum(funcid),
767 if (!HeapTupleIsValid(tp))
768 elog(ERROR, "cache lookup failed for function %u", funcid);
770 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
777 * Given procedure id, return the function's argument and result types.
778 * (The return value is the result type.)
780 * argtypes must point to a vector of size FUNC_MAX_ARGS.
783 get_func_signature(Oid funcid, Oid *argtypes, int *nargs)
786 Form_pg_proc procstruct;
789 tp = SearchSysCache(PROCOID,
790 ObjectIdGetDatum(funcid),
792 if (!HeapTupleIsValid(tp))
793 elog(ERROR, "cache lookup failed for function %u", funcid);
795 procstruct = (Form_pg_proc) GETSTRUCT(tp);
797 result = procstruct->prorettype;
798 memcpy(argtypes, procstruct->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
799 *nargs = (int) procstruct->pronargs;
807 * Given procedure id, return the function's proretset flag.
810 get_func_retset(Oid funcid)
815 tp = SearchSysCache(PROCOID,
816 ObjectIdGetDatum(funcid),
818 if (!HeapTupleIsValid(tp))
819 elog(ERROR, "cache lookup failed for function %u", funcid);
821 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
828 * Given procedure id, return the function's proisstrict flag.
831 func_strict(Oid funcid)
836 tp = SearchSysCache(PROCOID,
837 ObjectIdGetDatum(funcid),
839 if (!HeapTupleIsValid(tp))
840 elog(ERROR, "cache lookup failed for function %u", funcid);
842 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
849 * Given procedure id, return the function's provolatile flag.
852 func_volatile(Oid funcid)
857 tp = SearchSysCache(PROCOID,
858 ObjectIdGetDatum(funcid),
860 if (!HeapTupleIsValid(tp))
861 elog(ERROR, "cache lookup failed for function %u", funcid);
863 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
868 /* ---------- RELATION CACHE ---------- */
872 * Given name and namespace of a relation, look up the OID.
874 * Returns InvalidOid if there is no such relation.
877 get_relname_relid(const char *relname, Oid relnamespace)
879 return GetSysCacheOid(RELNAMENSP,
880 PointerGetDatum(relname),
881 ObjectIdGetDatum(relnamespace),
886 * get_system_catalog_relid
887 * Get the OID of a system catalog identified by name.
890 get_system_catalog_relid(const char *catname)
894 relid = GetSysCacheOid(RELNAMENSP,
895 PointerGetDatum(catname),
896 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
898 if (!OidIsValid(relid))
899 elog(ERROR, "cache lookup failed for system relation %s", catname);
908 * Returns the number of attributes for a given relation.
911 get_relnatts(Oid relid)
915 tp = SearchSysCache(RELOID,
916 ObjectIdGetDatum(relid),
918 if (HeapTupleIsValid(tp))
920 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
923 result = reltup->relnatts;
928 return InvalidAttrNumber;
934 * Returns the name of a given relation.
936 * Returns a palloc'd copy of the string, or NULL if no such relation.
938 * NOTE: since relation name is not unique, be wary of code that uses this
939 * for anything except preparing error messages.
942 get_rel_name(Oid relid)
946 tp = SearchSysCache(RELOID,
947 ObjectIdGetDatum(relid),
949 if (HeapTupleIsValid(tp))
951 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
954 result = pstrdup(NameStr(reltup->relname));
965 * Returns the pg_namespace OID associated with a given relation.
968 get_rel_namespace(Oid relid)
972 tp = SearchSysCache(RELOID,
973 ObjectIdGetDatum(relid),
975 if (HeapTupleIsValid(tp))
977 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
980 result = reltup->relnamespace;
991 * Returns the pg_type OID associated with a given relation.
993 * Note: not all pg_class entries have associated pg_type OIDs; so be
994 * careful to check for InvalidOid result.
997 get_rel_type_id(Oid relid)
1001 tp = SearchSysCache(RELOID,
1002 ObjectIdGetDatum(relid),
1004 if (HeapTupleIsValid(tp))
1006 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1009 result = reltup->reltype;
1010 ReleaseSysCache(tp);
1020 * Returns the relkind associated with a given relation.
1023 get_rel_relkind(Oid relid)
1027 tp = SearchSysCache(RELOID,
1028 ObjectIdGetDatum(relid),
1030 if (HeapTupleIsValid(tp))
1032 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1035 result = reltup->relkind;
1036 ReleaseSysCache(tp);
1044 /* ---------- TYPE CACHE ---------- */
1049 * Given the type OID, determine whether the type is defined
1050 * (if not, it's only a shell).
1053 get_typisdefined(Oid typid)
1057 tp = SearchSysCache(TYPEOID,
1058 ObjectIdGetDatum(typid),
1060 if (HeapTupleIsValid(tp))
1062 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1065 result = typtup->typisdefined;
1066 ReleaseSysCache(tp);
1076 * Given the type OID, return the length of the type.
1079 get_typlen(Oid typid)
1083 tp = SearchSysCache(TYPEOID,
1084 ObjectIdGetDatum(typid),
1086 if (HeapTupleIsValid(tp))
1088 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1091 result = typtup->typlen;
1092 ReleaseSysCache(tp);
1102 * Given the type OID, determine whether the type is returned by value or
1103 * not. Returns true if by value, false if by reference.
1106 get_typbyval(Oid typid)
1110 tp = SearchSysCache(TYPEOID,
1111 ObjectIdGetDatum(typid),
1113 if (HeapTupleIsValid(tp))
1115 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1118 result = typtup->typbyval;
1119 ReleaseSysCache(tp);
1129 * A two-fer: given the type OID, return both typlen and typbyval.
1131 * Since both pieces of info are needed to know how to copy a Datum,
1132 * many places need both. Might as well get them with one cache lookup
1133 * instead of two. Also, this routine raises an error instead of
1134 * returning a bogus value when given a bad type OID.
1137 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1140 Form_pg_type typtup;
1142 tp = SearchSysCache(TYPEOID,
1143 ObjectIdGetDatum(typid),
1145 if (!HeapTupleIsValid(tp))
1146 elog(ERROR, "cache lookup failed for type %u", typid);
1147 typtup = (Form_pg_type) GETSTRUCT(tp);
1148 *typlen = typtup->typlen;
1149 *typbyval = typtup->typbyval;
1150 ReleaseSysCache(tp);
1154 * get_typlenbyvalalign
1156 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1159 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1163 Form_pg_type typtup;
1165 tp = SearchSysCache(TYPEOID,
1166 ObjectIdGetDatum(typid),
1168 if (!HeapTupleIsValid(tp))
1169 elog(ERROR, "cache lookup failed for type %u", typid);
1170 typtup = (Form_pg_type) GETSTRUCT(tp);
1171 *typlen = typtup->typlen;
1172 *typbyval = typtup->typbyval;
1173 *typalign = typtup->typalign;
1174 ReleaseSysCache(tp);
1179 * Given a pg_type row, select the type OID to pass to I/O functions
1181 * Formerly, all I/O functions were passed pg_type.typelem as their second
1182 * parameter, but we now have a more complex rule about what to pass.
1183 * This knowledge is intended to be centralized here --- direct references
1184 * to typelem elsewhere in the code are wrong, if they are associated with
1185 * I/O calls and not with actual subscripting operations! (But see
1186 * bootstrap.c, which can't conveniently use this routine.)
1189 getTypeIOParam(HeapTuple typeTuple)
1191 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1194 * Composite types get their own OID as parameter; array types get
1195 * their typelem as parameter; everybody else gets zero.
1197 if (typeStruct->typtype == 'c')
1198 return HeapTupleGetOid(typeTuple);
1200 return typeStruct->typelem;
1206 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1207 * typdelim, typioparam, and IO function OID. The IO function
1208 * returned is controlled by IOFuncSelector
1211 get_type_io_data(Oid typid,
1212 IOFuncSelector which_func,
1220 HeapTuple typeTuple;
1221 Form_pg_type typeStruct;
1223 typeTuple = SearchSysCache(TYPEOID,
1224 ObjectIdGetDatum(typid),
1226 if (!HeapTupleIsValid(typeTuple))
1227 elog(ERROR, "cache lookup failed for type %u", typid);
1228 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1230 *typlen = typeStruct->typlen;
1231 *typbyval = typeStruct->typbyval;
1232 *typalign = typeStruct->typalign;
1233 *typdelim = typeStruct->typdelim;
1234 *typioparam = getTypeIOParam(typeTuple);
1238 *func = typeStruct->typinput;
1241 *func = typeStruct->typoutput;
1243 case IOFunc_receive:
1244 *func = typeStruct->typreceive;
1247 *func = typeStruct->typsend;
1250 ReleaseSysCache(typeTuple);
1255 get_typalign(Oid typid)
1259 tp = SearchSysCache(TYPEOID,
1260 ObjectIdGetDatum(typid),
1262 if (HeapTupleIsValid(tp))
1264 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1267 result = typtup->typalign;
1268 ReleaseSysCache(tp);
1277 get_typstorage(Oid typid)
1281 tp = SearchSysCache(TYPEOID,
1282 ObjectIdGetDatum(typid),
1284 if (HeapTupleIsValid(tp))
1286 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1289 result = typtup->typstorage;
1290 ReleaseSysCache(tp);
1300 * Given the type OID, return the typtypmod field (domain's typmod
1304 get_typtypmod(Oid typid)
1308 tp = SearchSysCache(TYPEOID,
1309 ObjectIdGetDatum(typid),
1311 if (HeapTupleIsValid(tp))
1313 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1316 result = typtup->typtypmod;
1317 ReleaseSysCache(tp);
1326 * Given a type OID, return the type's default value, if any.
1328 * The result is a palloc'd expression node tree, or NULL if there
1329 * is no defined default for the datatype.
1331 * NB: caller should be prepared to coerce result to correct datatype;
1332 * the returned expression tree might produce something of the wrong type.
1335 get_typdefault(Oid typid)
1337 HeapTuple typeTuple;
1343 typeTuple = SearchSysCache(TYPEOID,
1344 ObjectIdGetDatum(typid),
1346 if (!HeapTupleIsValid(typeTuple))
1347 elog(ERROR, "cache lookup failed for type %u", typid);
1348 type = (Form_pg_type) GETSTRUCT(typeTuple);
1351 * typdefault and typdefaultbin are potentially null, so don't try to
1352 * access 'em as struct fields. Must do it the hard way with
1355 datum = SysCacheGetAttr(TYPEOID,
1357 Anum_pg_type_typdefaultbin,
1362 /* We have an expression default */
1363 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1368 /* Perhaps we have a plain literal default */
1369 datum = SysCacheGetAttr(TYPEOID,
1371 Anum_pg_type_typdefault,
1376 char *strDefaultVal;
1378 /* Convert text datum to C string */
1379 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1381 /* Convert C string to a value of the given type */
1382 datum = OidFunctionCall3(type->typinput,
1383 CStringGetDatum(strDefaultVal),
1384 ObjectIdGetDatum(getTypeIOParam(typeTuple)),
1386 /* Build a Const node containing the value */
1387 expr = (Node *) makeConst(typid,
1392 pfree(strDefaultVal);
1401 ReleaseSysCache(typeTuple);
1408 * If the given type is a domain, return its base type;
1409 * otherwise return the type's own OID.
1412 getBaseType(Oid typid)
1415 * We loop to find the bottom base type in a stack of domains.
1420 Form_pg_type typTup;
1422 tup = SearchSysCache(TYPEOID,
1423 ObjectIdGetDatum(typid),
1425 if (!HeapTupleIsValid(tup))
1426 elog(ERROR, "cache lookup failed for type %u", typid);
1427 typTup = (Form_pg_type) GETSTRUCT(tup);
1428 if (typTup->typtype != 'd')
1430 /* Not a domain, so done */
1431 ReleaseSysCache(tup);
1435 typid = typTup->typbasetype;
1436 ReleaseSysCache(tup);
1445 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1446 * estimate the average width of values of the type. This is used by
1447 * the planner, which doesn't require absolutely correct results;
1448 * it's OK (and expected) to guess if we don't know for sure.
1451 get_typavgwidth(Oid typid, int32 typmod)
1453 int typlen = get_typlen(typid);
1457 * Easy if it's a fixed-width type
1463 * type_maximum_size knows the encoding of typmod for some datatypes;
1464 * don't duplicate that knowledge here.
1466 maxwidth = type_maximum_size(typid, typmod);
1470 * For BPCHAR, the max width is also the only width. Otherwise we
1471 * need to guess about the typical data width given the max. A
1472 * sliding scale for percentage of max width seems reasonable.
1474 if (typid == BPCHAROID)
1477 return maxwidth; /* assume full width */
1478 if (maxwidth < 1000)
1479 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1482 * Beyond 1000, assume we're looking at something like
1483 * "varchar(10000)" where the limit isn't actually reached often,
1484 * and use a fixed estimate.
1486 return 32 + (1000 - 32) / 2;
1490 * Ooops, we have no idea ... wild guess time.
1498 * Given the type OID, find if it is a basic type, a complex type, etc.
1499 * It returns the null char if the cache lookup fails...
1502 get_typtype(Oid typid)
1506 tp = SearchSysCache(TYPEOID,
1507 ObjectIdGetDatum(typid),
1509 if (HeapTupleIsValid(tp))
1511 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1514 result = typtup->typtype;
1515 ReleaseSysCache(tp);
1525 * Given the type OID, get the typrelid (InvalidOid if not a complex
1529 get_typ_typrelid(Oid typid)
1533 tp = SearchSysCache(TYPEOID,
1534 ObjectIdGetDatum(typid),
1536 if (HeapTupleIsValid(tp))
1538 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1541 result = typtup->typrelid;
1542 ReleaseSysCache(tp);
1552 * Given the type OID, get the typelem (InvalidOid if not an array type).
1554 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
1555 * returned if the input is a fixed-length array type.
1558 get_element_type(Oid typid)
1562 tp = SearchSysCache(TYPEOID,
1563 ObjectIdGetDatum(typid),
1565 if (HeapTupleIsValid(tp))
1567 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1570 if (typtup->typlen == -1)
1571 result = typtup->typelem;
1573 result = InvalidOid;
1574 ReleaseSysCache(tp);
1584 * Given the type OID, get the corresponding array type.
1585 * Returns InvalidOid if no array type can be found.
1587 * NB: this only considers varlena arrays to be true arrays.
1590 get_array_type(Oid typid)
1594 tp = SearchSysCache(TYPEOID,
1595 ObjectIdGetDatum(typid),
1597 if (HeapTupleIsValid(tp))
1599 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1600 char *array_typename;
1603 array_typename = makeArrayTypeName(NameStr(typtup->typname));
1604 namespaceId = typtup->typnamespace;
1605 ReleaseSysCache(tp);
1607 tp = SearchSysCache(TYPENAMENSP,
1608 PointerGetDatum(array_typename),
1609 ObjectIdGetDatum(namespaceId),
1612 pfree(array_typename);
1614 if (HeapTupleIsValid(tp))
1618 typtup = (Form_pg_type) GETSTRUCT(tp);
1619 if (typtup->typlen == -1 && typtup->typelem == typid)
1620 result = HeapTupleGetOid(tp);
1622 result = InvalidOid;
1623 ReleaseSysCache(tp);
1633 * Get info needed for converting values of a type to internal form
1636 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
1638 HeapTuple typeTuple;
1641 typeTuple = SearchSysCache(TYPEOID,
1642 ObjectIdGetDatum(type),
1644 if (!HeapTupleIsValid(typeTuple))
1645 elog(ERROR, "cache lookup failed for type %u", type);
1646 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1648 if (!pt->typisdefined)
1650 (errcode(ERRCODE_UNDEFINED_OBJECT),
1651 errmsg("type %s is only a shell",
1652 format_type_be(type))));
1653 if (!OidIsValid(pt->typinput))
1655 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1656 errmsg("no input function available for type %s",
1657 format_type_be(type))));
1659 *typInput = pt->typinput;
1660 *typIOParam = getTypeIOParam(typeTuple);
1662 ReleaseSysCache(typeTuple);
1668 * Get info needed for printing values of a type
1671 getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typIOParam,
1674 HeapTuple typeTuple;
1677 typeTuple = SearchSysCache(TYPEOID,
1678 ObjectIdGetDatum(type),
1680 if (!HeapTupleIsValid(typeTuple))
1681 elog(ERROR, "cache lookup failed for type %u", type);
1682 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1684 if (!pt->typisdefined)
1686 (errcode(ERRCODE_UNDEFINED_OBJECT),
1687 errmsg("type %s is only a shell",
1688 format_type_be(type))));
1689 if (!OidIsValid(pt->typoutput))
1691 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1692 errmsg("no output function available for type %s",
1693 format_type_be(type))));
1695 *typOutput = pt->typoutput;
1696 *typIOParam = getTypeIOParam(typeTuple);
1697 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1699 ReleaseSysCache(typeTuple);
1703 * getTypeBinaryInputInfo
1705 * Get info needed for binary input of values of a type
1708 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
1710 HeapTuple typeTuple;
1713 typeTuple = SearchSysCache(TYPEOID,
1714 ObjectIdGetDatum(type),
1716 if (!HeapTupleIsValid(typeTuple))
1717 elog(ERROR, "cache lookup failed for type %u", type);
1718 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1720 if (!pt->typisdefined)
1722 (errcode(ERRCODE_UNDEFINED_OBJECT),
1723 errmsg("type %s is only a shell",
1724 format_type_be(type))));
1725 if (!OidIsValid(pt->typreceive))
1727 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1728 errmsg("no binary input function available for type %s",
1729 format_type_be(type))));
1731 *typReceive = pt->typreceive;
1732 *typIOParam = getTypeIOParam(typeTuple);
1734 ReleaseSysCache(typeTuple);
1738 * getTypeBinaryOutputInfo
1740 * Get info needed for binary output of values of a type
1743 getTypeBinaryOutputInfo(Oid type, Oid *typSend, Oid *typIOParam,
1746 HeapTuple typeTuple;
1749 typeTuple = SearchSysCache(TYPEOID,
1750 ObjectIdGetDatum(type),
1752 if (!HeapTupleIsValid(typeTuple))
1753 elog(ERROR, "cache lookup failed for type %u", type);
1754 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1756 if (!pt->typisdefined)
1758 (errcode(ERRCODE_UNDEFINED_OBJECT),
1759 errmsg("type %s is only a shell",
1760 format_type_be(type))));
1761 if (!OidIsValid(pt->typsend))
1763 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1764 errmsg("no binary output function available for type %s",
1765 format_type_be(type))));
1767 *typSend = pt->typsend;
1768 *typIOParam = getTypeIOParam(typeTuple);
1769 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1771 ReleaseSysCache(typeTuple);
1775 /* ---------- STATISTICS CACHE ---------- */
1780 * Given the table and attribute number of a column, get the average
1781 * width of entries in the column. Return zero if no data available.
1784 get_attavgwidth(Oid relid, AttrNumber attnum)
1788 tp = SearchSysCache(STATRELATT,
1789 ObjectIdGetDatum(relid),
1790 Int16GetDatum(attnum),
1792 if (HeapTupleIsValid(tp))
1794 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1796 ReleaseSysCache(tp);
1806 * Extract the contents of a "slot" of a pg_statistic tuple.
1807 * Returns TRUE if requested slot type was found, else FALSE.
1809 * Unlike other routines in this file, this takes a pointer to an
1810 * already-looked-up tuple in the pg_statistic cache. We do this since
1811 * most callers will want to extract more than one value from the cache
1812 * entry, and we don't want to repeat the cache lookup unnecessarily.
1814 * statstuple: pg_statistics tuple to be examined.
1815 * atttype: type OID of attribute.
1816 * atttypmod: typmod of attribute.
1817 * reqkind: STAKIND code for desired statistics slot kind.
1818 * reqop: STAOP value wanted, or InvalidOid if don't care.
1819 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1820 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1822 * If assigned, values and numbers are set to point to palloc'd arrays.
1823 * If the attribute type is pass-by-reference, the values referenced by
1824 * the values array are themselves palloc'd. The palloc'd stuff can be
1825 * freed by calling free_attstatsslot.
1828 get_attstatsslot(HeapTuple statstuple,
1829 Oid atttype, int32 atttypmod,
1830 int reqkind, Oid reqop,
1831 Datum **values, int *nvalues,
1832 float4 **numbers, int *nnumbers)
1834 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1839 ArrayType *statarray;
1841 HeapTuple typeTuple;
1842 Form_pg_type typeForm;
1844 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1846 if ((&stats->stakind1)[i] == reqkind &&
1847 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1850 if (i >= STATISTIC_NUM_SLOTS)
1851 return false; /* not there */
1855 val = SysCacheGetAttr(STATRELATT, statstuple,
1856 Anum_pg_statistic_stavalues1 + i,
1859 elog(ERROR, "stavalues is null");
1860 statarray = DatumGetArrayTypeP(val);
1862 /* Need to get info about the array element type */
1863 typeTuple = SearchSysCache(TYPEOID,
1864 ObjectIdGetDatum(atttype),
1866 if (!HeapTupleIsValid(typeTuple))
1867 elog(ERROR, "cache lookup failed for type %u", atttype);
1868 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1870 /* Deconstruct array into Datum elements */
1871 deconstruct_array(statarray,
1879 * If the element type is pass-by-reference, we now have a bunch
1880 * of Datums that are pointers into the syscache value. Copy them
1881 * to avoid problems if syscache decides to drop the entry.
1883 if (!typeForm->typbyval)
1885 for (j = 0; j < *nvalues; j++)
1887 (*values)[j] = datumCopy((*values)[j],
1893 ReleaseSysCache(typeTuple);
1896 * Free statarray if it's a detoasted copy.
1898 if ((Pointer) statarray != DatumGetPointer(val))
1904 val = SysCacheGetAttr(STATRELATT, statstuple,
1905 Anum_pg_statistic_stanumbers1 + i,
1908 elog(ERROR, "stanumbers is null");
1909 statarray = DatumGetArrayTypeP(val);
1912 * We expect the array to be a 1-D float4 array; verify that. We
1913 * don't need to use deconstruct_array() since the array data is
1914 * just going to look like a C array of float4 values.
1916 narrayelem = ARR_DIMS(statarray)[0];
1917 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1918 ARR_ELEMTYPE(statarray) != FLOAT4OID)
1919 elog(ERROR, "stanumbers is not a 1-D float4 array");
1920 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1921 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1922 *nnumbers = narrayelem;
1925 * Free statarray if it's a detoasted copy.
1927 if ((Pointer) statarray != DatumGetPointer(val))
1935 free_attstatsslot(Oid atttype,
1936 Datum *values, int nvalues,
1937 float4 *numbers, int nnumbers)
1941 if (!get_typbyval(atttype))
1945 for (i = 0; i < nvalues; i++)
1946 pfree(DatumGetPointer(values[i]));
1954 /* ---------- PG_NAMESPACE CACHE ---------- */
1957 * get_namespace_name
1958 * Returns the name of a given namespace
1960 * Returns a palloc'd copy of the string, or NULL if no such namespace.
1963 get_namespace_name(Oid nspid)
1967 tp = SearchSysCache(NAMESPACEOID,
1968 ObjectIdGetDatum(nspid),
1970 if (HeapTupleIsValid(tp))
1972 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
1975 result = pstrdup(NameStr(nsptup->nspname));
1976 ReleaseSysCache(tp);
1983 /* ---------- PG_SHADOW CACHE ---------- */
1988 * Given a user name, look up the user's sysid.
1989 * Raises an error if no such user (rather than returning zero,
1990 * which might possibly be a valid usesysid).
1992 * Note: the type of usesysid is currently int4, but may change to Oid
1993 * someday. It'd be reasonable to return zero on failure if we were
1997 get_usesysid(const char *username)
2002 userTup = SearchSysCache(SHADOWNAME,
2003 PointerGetDatum(username),
2005 if (!HeapTupleIsValid(userTup))
2007 (errcode(ERRCODE_UNDEFINED_OBJECT),
2008 errmsg("user \"%s\" does not exist", username)));
2010 result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
2012 ReleaseSysCache(userTup);