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.98 2003/06/25 03:56:31 momjian 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, "op_requires_recheck: op %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)
126 Oid opclass = InvalidOid;
129 * Search pg_amop to see if the target operator is registered as the "="
130 * operator of any hash opclass. If the operator is registered in
131 * multiple opclasses, assume we can use the associated hash function
134 catlist = SearchSysCacheList(AMOPOPID, 1,
135 ObjectIdGetDatum(opno),
138 for (i = 0; i < catlist->n_members; i++)
142 tuple = &catlist->members[i]->tuple;
143 aform = (Form_pg_amop) GETSTRUCT(tuple);
145 if (aform->amopstrategy == HTEqualStrategyNumber &&
146 opclass_is_hash(aform->amopclaid))
148 opclass = aform->amopclaid;
153 ReleaseSysCacheList(catlist);
155 if (OidIsValid(opclass))
157 /* Found a suitable opclass, get its hash support function */
158 tuple = SearchSysCache(AMPROCNUM,
159 ObjectIdGetDatum(opclass),
160 Int16GetDatum(HASHPROC),
162 if (HeapTupleIsValid(tuple))
164 Form_pg_amproc aform = (Form_pg_amproc) GETSTRUCT(tuple);
167 result = aform->amproc;
168 ReleaseSysCache(tuple);
169 Assert(RegProcedureIsValid(result));
174 /* Didn't find a match... */
179 /* ---------- ATTRIBUTE CACHES ---------- */
184 * Given the relation id and the attribute number,
185 * return the "attname" field from the attribute relation.
187 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
190 get_attname(Oid relid, AttrNumber attnum)
194 tp = SearchSysCache(ATTNUM,
195 ObjectIdGetDatum(relid),
196 Int16GetDatum(attnum),
198 if (HeapTupleIsValid(tp))
200 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
203 result = pstrdup(NameStr(att_tup->attname));
214 * Given the relation id and the attribute name,
215 * return the "attnum" field from the attribute relation.
217 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
220 get_attnum(Oid relid, const char *attname)
224 tp = SearchSysCacheAttName(relid, attname);
225 if (HeapTupleIsValid(tp))
227 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
230 result = att_tup->attnum;
235 return InvalidAttrNumber;
241 * Given the relation OID and the attribute number with the relation,
242 * return the attribute type OID.
245 get_atttype(Oid relid, AttrNumber attnum)
249 tp = SearchSysCache(ATTNUM,
250 ObjectIdGetDatum(relid),
251 Int16GetDatum(attnum),
253 if (HeapTupleIsValid(tp))
255 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
258 result = att_tup->atttypid;
269 * Given the relation id and the attribute number,
270 * return the "atttypmod" field from the attribute relation.
273 get_atttypmod(Oid relid, AttrNumber attnum)
277 tp = SearchSysCache(ATTNUM,
278 ObjectIdGetDatum(relid),
279 Int16GetDatum(attnum),
281 if (HeapTupleIsValid(tp))
283 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
286 result = att_tup->atttypmod;
297 * A two-fer: given the relation id and the attribute number,
298 * fetch both type OID and atttypmod in a single cache lookup.
300 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
301 * raises an error if it can't obtain the information.
304 get_atttypetypmod(Oid relid, AttrNumber attnum,
305 Oid *typid, int32 *typmod)
308 Form_pg_attribute att_tup;
310 tp = SearchSysCache(ATTNUM,
311 ObjectIdGetDatum(relid),
312 Int16GetDatum(attnum),
314 if (!HeapTupleIsValid(tp))
315 elog(ERROR, "cache lookup failed for relation %u attribute %d",
317 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
319 *typid = att_tup->atttypid;
320 *typmod = att_tup->atttypmod;
324 /* ---------- INDEX CACHE ---------- */
326 /* watch this space...
329 /* ---------- OPCLASS CACHE ---------- */
334 * Returns TRUE iff the specified opclass is associated with the
335 * btree index access method.
338 opclass_is_btree(Oid opclass)
341 Form_pg_opclass cla_tup;
344 tp = SearchSysCache(CLAOID,
345 ObjectIdGetDatum(opclass),
347 if (!HeapTupleIsValid(tp))
348 elog(ERROR, "cache lookup failed for opclass %u", opclass);
349 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
351 result = (cla_tup->opcamid == BTREE_AM_OID);
359 * Returns TRUE iff the specified opclass is associated with the
360 * hash index access method.
363 opclass_is_hash(Oid opclass)
366 Form_pg_opclass cla_tup;
369 tp = SearchSysCache(CLAOID,
370 ObjectIdGetDatum(opclass),
372 if (!HeapTupleIsValid(tp))
373 elog(ERROR, "cache lookup failed for opclass %u", opclass);
374 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
376 result = (cla_tup->opcamid == HASH_AM_OID);
381 /* ---------- OPERATOR CACHE ---------- */
386 * Returns the regproc id of the routine used to implement an
387 * operator given the operator oid.
394 tp = SearchSysCache(OPEROID,
395 ObjectIdGetDatum(opno),
397 if (HeapTupleIsValid(tp))
399 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
402 result = optup->oprcode;
407 return (RegProcedure) InvalidOid;
412 * returns the name of the operator with the given opno
414 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
421 tp = SearchSysCache(OPEROID,
422 ObjectIdGetDatum(opno),
424 if (HeapTupleIsValid(tp))
426 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
429 result = pstrdup(NameStr(optup->oprname));
440 * Returns the left and right sort operators corresponding to a
441 * mergejoinable operator, or false if the operator is not mergejoinable.
444 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
449 tp = SearchSysCache(OPEROID,
450 ObjectIdGetDatum(opno),
452 if (HeapTupleIsValid(tp))
454 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
456 if (optup->oprlsortop &&
459 *leftOp = optup->oprlsortop;
460 *rightOp = optup->oprrsortop;
469 * op_mergejoin_crossops
471 * Returns the cross-type comparison operators (ltype "<" rtype and
472 * ltype ">" rtype) for an operator previously determined to be
473 * mergejoinable. Optionally, fetches the regproc ids of these
474 * operators, as well as their operator OIDs.
477 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
478 RegProcedure *ltproc, RegProcedure *gtproc)
481 Form_pg_operator optup;
484 * Get the declared comparison operators of the operator.
486 tp = SearchSysCache(OPEROID,
487 ObjectIdGetDatum(opno),
489 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
490 elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
491 optup = (Form_pg_operator) GETSTRUCT(tp);
492 *ltop = optup->oprltcmpop;
493 *gtop = optup->oprgtcmpop;
496 /* Check < op provided */
497 if (!OidIsValid(*ltop))
498 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
501 *ltproc = get_opcode(*ltop);
503 /* Check > op provided */
504 if (!OidIsValid(*gtop))
505 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
508 *gtproc = get_opcode(*gtop);
514 * Returns true if the operator is hashjoinable.
517 op_hashjoinable(Oid opno)
522 tp = SearchSysCache(OPEROID,
523 ObjectIdGetDatum(opno),
525 if (HeapTupleIsValid(tp))
527 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
529 result = optup->oprcanhash;
538 * Get the proisstrict flag for the operator's underlying function.
543 RegProcedure funcid = get_opcode(opno);
545 if (funcid == (RegProcedure) InvalidOid)
546 elog(ERROR, "Operator OID %u does not exist", opno);
548 return func_strict((Oid) funcid);
554 * Get the provolatile flag for the operator's underlying function.
557 op_volatile(Oid opno)
559 RegProcedure funcid = get_opcode(opno);
561 if (funcid == (RegProcedure) InvalidOid)
562 elog(ERROR, "Operator OID %u does not exist", opno);
564 return func_volatile((Oid) funcid);
570 * Returns the corresponding commutator of an operator.
573 get_commutator(Oid opno)
577 tp = SearchSysCache(OPEROID,
578 ObjectIdGetDatum(opno),
580 if (HeapTupleIsValid(tp))
582 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
585 result = optup->oprcom;
596 * Returns the corresponding negator of an operator.
599 get_negator(Oid opno)
603 tp = SearchSysCache(OPEROID,
604 ObjectIdGetDatum(opno),
606 if (HeapTupleIsValid(tp))
608 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
611 result = optup->oprnegate;
622 * Returns procedure id for computing selectivity of an operator.
625 get_oprrest(Oid opno)
629 tp = SearchSysCache(OPEROID,
630 ObjectIdGetDatum(opno),
632 if (HeapTupleIsValid(tp))
634 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
637 result = optup->oprrest;
642 return (RegProcedure) InvalidOid;
648 * Returns procedure id for computing selectivity of a join.
651 get_oprjoin(Oid opno)
655 tp = SearchSysCache(OPEROID,
656 ObjectIdGetDatum(opno),
658 if (HeapTupleIsValid(tp))
660 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
663 result = optup->oprjoin;
668 return (RegProcedure) InvalidOid;
671 /* ---------- FUNCTION CACHE ---------- */
675 * returns the name of the function with the given funcid
677 * Note: returns a palloc'd copy of the string, or NULL if no such function.
680 get_func_name(Oid funcid)
684 tp = SearchSysCache(PROCOID,
685 ObjectIdGetDatum(funcid),
687 if (HeapTupleIsValid(tp))
689 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
692 result = pstrdup(NameStr(functup->proname));
702 * Given procedure id, return the function's result type.
705 get_func_rettype(Oid funcid)
710 tp = SearchSysCache(PROCOID,
711 ObjectIdGetDatum(funcid),
713 if (!HeapTupleIsValid(tp))
714 elog(ERROR, "Function OID %u does not exist", funcid);
716 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
723 * Given procedure id, return the function's argument types.
724 * Also pass back the number of arguments.
727 get_func_argtypes(Oid funcid, int *nargs)
730 Form_pg_proc procstruct;
734 tp = SearchSysCache(PROCOID,
735 ObjectIdGetDatum(funcid),
737 if (!HeapTupleIsValid(tp))
738 elog(ERROR, "Function OID %u does not exist", funcid);
740 procstruct = (Form_pg_proc) GETSTRUCT(tp);
741 *nargs = (int) procstruct->pronargs;
745 result = (Oid *) palloc(*nargs * sizeof(Oid));
747 for (i = 0; i < *nargs; i++)
748 result[i] = procstruct->proargtypes[i];
757 * Given procedure id, return the function's proretset flag.
760 get_func_retset(Oid funcid)
765 tp = SearchSysCache(PROCOID,
766 ObjectIdGetDatum(funcid),
768 if (!HeapTupleIsValid(tp))
769 elog(ERROR, "Function OID %u does not exist", funcid);
771 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
778 * Given procedure id, return the function's proisstrict flag.
781 func_strict(Oid funcid)
786 tp = SearchSysCache(PROCOID,
787 ObjectIdGetDatum(funcid),
789 if (!HeapTupleIsValid(tp))
790 elog(ERROR, "Function OID %u does not exist", funcid);
792 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
799 * Given procedure id, return the function's provolatile flag.
802 func_volatile(Oid funcid)
807 tp = SearchSysCache(PROCOID,
808 ObjectIdGetDatum(funcid),
810 if (!HeapTupleIsValid(tp))
811 elog(ERROR, "Function OID %u does not exist", funcid);
813 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
818 /* ---------- RELATION CACHE ---------- */
822 * Given name and namespace of a relation, look up the OID.
824 * Returns InvalidOid if there is no such relation.
827 get_relname_relid(const char *relname, Oid relnamespace)
829 return GetSysCacheOid(RELNAMENSP,
830 PointerGetDatum(relname),
831 ObjectIdGetDatum(relnamespace),
836 * get_system_catalog_relid
837 * Get the OID of a system catalog identified by name.
840 get_system_catalog_relid(const char *catname)
844 relid = GetSysCacheOid(RELNAMENSP,
845 PointerGetDatum(catname),
846 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
848 if (!OidIsValid(relid))
849 elog(ERROR, "get_system_catalog_relid: cannot find %s", catname);
858 * Returns the number of attributes for a given relation.
861 get_relnatts(Oid relid)
865 tp = SearchSysCache(RELOID,
866 ObjectIdGetDatum(relid),
868 if (HeapTupleIsValid(tp))
870 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
873 result = reltup->relnatts;
878 return InvalidAttrNumber;
884 * Returns the name of a given relation.
886 * Returns a palloc'd copy of the string, or NULL if no such relation.
888 * NOTE: since relation name is not unique, be wary of code that uses this
889 * for anything except preparing error messages.
892 get_rel_name(Oid relid)
896 tp = SearchSysCache(RELOID,
897 ObjectIdGetDatum(relid),
899 if (HeapTupleIsValid(tp))
901 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
904 result = pstrdup(NameStr(reltup->relname));
915 * Returns the pg_namespace OID associated with a given relation.
918 get_rel_namespace(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 = reltup->relnamespace;
941 * Returns the pg_type OID associated with a given relation.
943 * Note: not all pg_class entries have associated pg_type OIDs; so be
944 * careful to check for InvalidOid result.
947 get_rel_type_id(Oid relid)
951 tp = SearchSysCache(RELOID,
952 ObjectIdGetDatum(relid),
954 if (HeapTupleIsValid(tp))
956 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
959 result = reltup->reltype;
970 * Returns the relkind associated with a given relation.
973 get_rel_relkind(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->relkind;
994 /* ---------- TYPE CACHE ---------- */
999 * Given the type OID, determine whether the type is defined
1000 * (if not, it's only a shell).
1003 get_typisdefined(Oid typid)
1007 tp = SearchSysCache(TYPEOID,
1008 ObjectIdGetDatum(typid),
1010 if (HeapTupleIsValid(tp))
1012 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1015 result = typtup->typisdefined;
1016 ReleaseSysCache(tp);
1026 * Given the type OID, return the length of the type.
1029 get_typlen(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->typlen;
1042 ReleaseSysCache(tp);
1052 * Given the type OID, determine whether the type is returned by value or
1053 * not. Returns true if by value, false if by reference.
1056 get_typbyval(Oid typid)
1060 tp = SearchSysCache(TYPEOID,
1061 ObjectIdGetDatum(typid),
1063 if (HeapTupleIsValid(tp))
1065 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1068 result = typtup->typbyval;
1069 ReleaseSysCache(tp);
1079 * A two-fer: given the type OID, return both typlen and typbyval.
1081 * Since both pieces of info are needed to know how to copy a Datum,
1082 * many places need both. Might as well get them with one cache lookup
1083 * instead of two. Also, this routine raises an error instead of
1084 * returning a bogus value when given a bad type OID.
1087 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1090 Form_pg_type typtup;
1092 tp = SearchSysCache(TYPEOID,
1093 ObjectIdGetDatum(typid),
1095 if (!HeapTupleIsValid(tp))
1096 elog(ERROR, "cache lookup failed for type %u", typid);
1097 typtup = (Form_pg_type) GETSTRUCT(tp);
1098 *typlen = typtup->typlen;
1099 *typbyval = typtup->typbyval;
1100 ReleaseSysCache(tp);
1104 * get_typlenbyvalalign
1106 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1109 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1113 Form_pg_type typtup;
1115 tp = SearchSysCache(TYPEOID,
1116 ObjectIdGetDatum(typid),
1118 if (!HeapTupleIsValid(tp))
1119 elog(ERROR, "cache lookup failed for type %u", typid);
1120 typtup = (Form_pg_type) GETSTRUCT(tp);
1121 *typlen = typtup->typlen;
1122 *typbyval = typtup->typbyval;
1123 *typalign = typtup->typalign;
1124 ReleaseSysCache(tp);
1130 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1131 * typdelim, typelem, IO function Oid. The IO function
1132 * returned is controlled by IOFuncSelector
1135 get_type_metadata(Oid element_type,
1136 IOFuncSelector which_func,
1144 HeapTuple typeTuple;
1145 Form_pg_type typeStruct;
1147 typeTuple = SearchSysCache(TYPEOID,
1148 ObjectIdGetDatum(element_type),
1150 if (!HeapTupleIsValid(typeTuple))
1151 elog(ERROR, "cache lookup failed for type %u", element_type);
1152 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1154 *typlen = typeStruct->typlen;
1155 *typbyval = typeStruct->typbyval;
1156 *typdelim = typeStruct->typdelim;
1157 *typelem = typeStruct->typelem;
1158 *typalign = typeStruct->typalign;
1162 *proc = typeStruct->typinput;
1165 *proc = typeStruct->typoutput;
1167 case IOFunc_receive:
1168 *proc = typeStruct->typreceive;
1171 *proc = typeStruct->typsend;
1174 ReleaseSysCache(typeTuple);
1179 get_typalign(Oid typid)
1183 tp = SearchSysCache(TYPEOID,
1184 ObjectIdGetDatum(typid),
1186 if (HeapTupleIsValid(tp))
1188 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1191 result = typtup->typalign;
1192 ReleaseSysCache(tp);
1201 get_typstorage(Oid typid)
1205 tp = SearchSysCache(TYPEOID,
1206 ObjectIdGetDatum(typid),
1208 if (HeapTupleIsValid(tp))
1210 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1213 result = typtup->typstorage;
1214 ReleaseSysCache(tp);
1224 * Given the type OID, return the typtypmod field (domain's typmod
1228 get_typtypmod(Oid typid)
1232 tp = SearchSysCache(TYPEOID,
1233 ObjectIdGetDatum(typid),
1235 if (HeapTupleIsValid(tp))
1237 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1240 result = typtup->typtypmod;
1241 ReleaseSysCache(tp);
1250 * Given a type OID, return the type's default value, if any.
1252 * The result is a palloc'd expression node tree, or NULL if there
1253 * is no defined default for the datatype.
1255 * NB: caller should be prepared to coerce result to correct datatype;
1256 * the returned expression tree might produce something of the wrong type.
1259 get_typdefault(Oid typid)
1261 HeapTuple typeTuple;
1267 typeTuple = SearchSysCache(TYPEOID,
1268 ObjectIdGetDatum(typid),
1270 if (!HeapTupleIsValid(typeTuple))
1271 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
1272 type = (Form_pg_type) GETSTRUCT(typeTuple);
1275 * typdefault and typdefaultbin are potentially null, so don't try to
1276 * access 'em as struct fields. Must do it the hard way with
1279 datum = SysCacheGetAttr(TYPEOID,
1281 Anum_pg_type_typdefaultbin,
1286 /* We have an expression default */
1287 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1292 /* Perhaps we have a plain literal default */
1293 datum = SysCacheGetAttr(TYPEOID,
1295 Anum_pg_type_typdefault,
1300 char *strDefaultVal;
1302 /* Convert text datum to C string */
1303 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1305 /* Convert C string to a value of the given type */
1306 datum = OidFunctionCall3(type->typinput,
1307 CStringGetDatum(strDefaultVal),
1308 ObjectIdGetDatum(type->typelem),
1310 /* Build a Const node containing the value */
1311 expr = (Node *) makeConst(typid,
1316 pfree(strDefaultVal);
1325 ReleaseSysCache(typeTuple);
1332 * If the given type is a domain, return its base type;
1333 * otherwise return the type's own OID.
1336 getBaseType(Oid typid)
1339 * We loop to find the bottom base type in a stack of domains.
1344 Form_pg_type typTup;
1346 tup = SearchSysCache(TYPEOID,
1347 ObjectIdGetDatum(typid),
1349 if (!HeapTupleIsValid(tup))
1350 elog(ERROR, "getBaseType: failed to lookup type %u", typid);
1351 typTup = (Form_pg_type) GETSTRUCT(tup);
1352 if (typTup->typtype != 'd')
1354 /* Not a domain, so done */
1355 ReleaseSysCache(tup);
1359 typid = typTup->typbasetype;
1360 ReleaseSysCache(tup);
1369 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1370 * estimate the average width of values of the type. This is used by
1371 * the planner, which doesn't require absolutely correct results;
1372 * it's OK (and expected) to guess if we don't know for sure.
1375 get_typavgwidth(Oid typid, int32 typmod)
1377 int typlen = get_typlen(typid);
1381 * Easy if it's a fixed-width type
1387 * type_maximum_size knows the encoding of typmod for some datatypes;
1388 * don't duplicate that knowledge here.
1390 maxwidth = type_maximum_size(typid, typmod);
1394 * For BPCHAR, the max width is also the only width. Otherwise we
1395 * need to guess about the typical data width given the max. A
1396 * sliding scale for percentage of max width seems reasonable.
1398 if (typid == BPCHAROID)
1401 return maxwidth; /* assume full width */
1402 if (maxwidth < 1000)
1403 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1406 * Beyond 1000, assume we're looking at something like
1407 * "varchar(10000)" where the limit isn't actually reached often,
1408 * and use a fixed estimate.
1410 return 32 + (1000 - 32) / 2;
1414 * Ooops, we have no idea ... wild guess time.
1422 * Given the type OID, find if it is a basic type, a complex type, etc.
1423 * It returns the null char if the cache lookup fails...
1426 get_typtype(Oid typid)
1430 tp = SearchSysCache(TYPEOID,
1431 ObjectIdGetDatum(typid),
1433 if (HeapTupleIsValid(tp))
1435 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1438 result = typtup->typtype;
1439 ReleaseSysCache(tp);
1448 * Returns the name of a given type.
1450 * Returns a palloc'd copy of the string, or NULL if no such relation.
1452 * NOTE: since type name is not unique, be wary of code that uses this
1453 * for anything except preparing error messages.
1456 get_typname(Oid typid)
1460 tp = SearchSysCache(TYPEOID,
1461 ObjectIdGetDatum(typid),
1463 if (HeapTupleIsValid(tp))
1465 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1468 result = pstrdup(NameStr(typtup->typname));
1469 ReleaseSysCache(tp);
1480 * Given the type OID, get the typrelid (InvalidOid if not a complex
1484 get_typ_typrelid(Oid typid)
1488 tp = SearchSysCache(TYPEOID,
1489 ObjectIdGetDatum(typid),
1491 if (HeapTupleIsValid(tp))
1493 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1496 result = typtup->typrelid;
1497 ReleaseSysCache(tp);
1507 * Given the type OID, get the typelem (InvalidOid if not an array type).
1509 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
1510 * returned if the input is a fixed-length array type.
1513 get_element_type(Oid typid)
1517 tp = SearchSysCache(TYPEOID,
1518 ObjectIdGetDatum(typid),
1520 if (HeapTupleIsValid(tp))
1522 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1525 if (typtup->typlen == -1)
1526 result = typtup->typelem;
1528 result = InvalidOid;
1529 ReleaseSysCache(tp);
1539 * Given the type OID, get the corresponding array type.
1540 * Returns InvalidOid if no array type can be found.
1542 * NB: this only considers varlena arrays to be true arrays.
1545 get_array_type(Oid typid)
1549 tp = SearchSysCache(TYPEOID,
1550 ObjectIdGetDatum(typid),
1552 if (HeapTupleIsValid(tp))
1554 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1555 char *array_typename;
1558 array_typename = makeArrayTypeName(NameStr(typtup->typname));
1559 namespaceId = typtup->typnamespace;
1560 ReleaseSysCache(tp);
1562 tp = SearchSysCache(TYPENAMENSP,
1563 PointerGetDatum(array_typename),
1564 ObjectIdGetDatum(namespaceId),
1567 pfree(array_typename);
1569 if (HeapTupleIsValid(tp))
1573 typtup = (Form_pg_type) GETSTRUCT(tp);
1574 if (typtup->typlen == -1 && typtup->typelem == typid)
1575 result = HeapTupleGetOid(tp);
1577 result = InvalidOid;
1578 ReleaseSysCache(tp);
1588 * Get info needed for converting values of a type to internal form
1591 getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem)
1593 HeapTuple typeTuple;
1596 typeTuple = SearchSysCache(TYPEOID,
1597 ObjectIdGetDatum(type),
1599 if (!HeapTupleIsValid(typeTuple))
1600 elog(ERROR, "Cache lookup of type %u failed", type);
1601 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1603 if (!pt->typisdefined)
1604 elog(ERROR, "Type %s is only a shell",
1605 format_type_be(type));
1606 if (!OidIsValid(pt->typinput))
1607 elog(ERROR, "No input function available for type %s",
1608 format_type_be(type));
1610 *typInput = pt->typinput;
1611 *typElem = pt->typelem;
1613 ReleaseSysCache(typeTuple);
1619 * Get info needed for printing values of a type
1622 getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
1625 HeapTuple typeTuple;
1628 typeTuple = SearchSysCache(TYPEOID,
1629 ObjectIdGetDatum(type),
1631 if (!HeapTupleIsValid(typeTuple))
1632 elog(ERROR, "Cache lookup of type %u failed", type);
1633 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1635 if (!pt->typisdefined)
1636 elog(ERROR, "Type %s is only a shell",
1637 format_type_be(type));
1638 if (!OidIsValid(pt->typoutput))
1639 elog(ERROR, "No output function available for type %s",
1640 format_type_be(type));
1642 *typOutput = pt->typoutput;
1643 *typElem = pt->typelem;
1644 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1646 ReleaseSysCache(typeTuple);
1650 * getTypeBinaryInputInfo
1652 * Get info needed for binary input of values of a type
1655 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typElem)
1657 HeapTuple typeTuple;
1660 typeTuple = SearchSysCache(TYPEOID,
1661 ObjectIdGetDatum(type),
1663 if (!HeapTupleIsValid(typeTuple))
1664 elog(ERROR, "Cache lookup of type %u failed", type);
1665 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1667 if (!pt->typisdefined)
1668 elog(ERROR, "Type %s is only a shell",
1669 format_type_be(type));
1670 if (!OidIsValid(pt->typreceive))
1671 elog(ERROR, "No binary input function available for type %s",
1672 format_type_be(type));
1674 *typReceive = pt->typreceive;
1675 *typElem = pt->typelem;
1677 ReleaseSysCache(typeTuple);
1681 * getTypeBinaryOutputInfo
1683 * Get info needed for binary output of values of a type
1686 getTypeBinaryOutputInfo(Oid type, Oid *typSend, Oid *typElem,
1689 HeapTuple typeTuple;
1692 typeTuple = SearchSysCache(TYPEOID,
1693 ObjectIdGetDatum(type),
1695 if (!HeapTupleIsValid(typeTuple))
1696 elog(ERROR, "Cache lookup of type %u failed", type);
1697 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1699 if (!pt->typisdefined)
1700 elog(ERROR, "Type %s is only a shell",
1701 format_type_be(type));
1702 if (!OidIsValid(pt->typsend))
1703 elog(ERROR, "No binary output function available for type %s",
1704 format_type_be(type));
1706 *typSend = pt->typsend;
1707 *typElem = pt->typelem;
1708 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1710 ReleaseSysCache(typeTuple);
1714 /* ---------- STATISTICS CACHE ---------- */
1719 * Given the table and attribute number of a column, get the average
1720 * width of entries in the column. Return zero if no data available.
1723 get_attavgwidth(Oid relid, AttrNumber attnum)
1727 tp = SearchSysCache(STATRELATT,
1728 ObjectIdGetDatum(relid),
1729 Int16GetDatum(attnum),
1731 if (HeapTupleIsValid(tp))
1733 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1735 ReleaseSysCache(tp);
1745 * Extract the contents of a "slot" of a pg_statistic tuple.
1746 * Returns TRUE if requested slot type was found, else FALSE.
1748 * Unlike other routines in this file, this takes a pointer to an
1749 * already-looked-up tuple in the pg_statistic cache. We do this since
1750 * most callers will want to extract more than one value from the cache
1751 * entry, and we don't want to repeat the cache lookup unnecessarily.
1753 * statstuple: pg_statistics tuple to be examined.
1754 * atttype: type OID of attribute.
1755 * atttypmod: typmod of attribute.
1756 * reqkind: STAKIND code for desired statistics slot kind.
1757 * reqop: STAOP value wanted, or InvalidOid if don't care.
1758 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1759 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1761 * If assigned, values and numbers are set to point to palloc'd arrays.
1762 * If the attribute type is pass-by-reference, the values referenced by
1763 * the values array are themselves palloc'd. The palloc'd stuff can be
1764 * freed by calling free_attstatsslot.
1767 get_attstatsslot(HeapTuple statstuple,
1768 Oid atttype, int32 atttypmod,
1769 int reqkind, Oid reqop,
1770 Datum **values, int *nvalues,
1771 float4 **numbers, int *nnumbers)
1773 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1778 ArrayType *statarray;
1780 HeapTuple typeTuple;
1781 Form_pg_type typeForm;
1783 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1785 if ((&stats->stakind1)[i] == reqkind &&
1786 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1789 if (i >= STATISTIC_NUM_SLOTS)
1790 return false; /* not there */
1794 val = SysCacheGetAttr(STATRELATT, statstuple,
1795 Anum_pg_statistic_stavalues1 + i,
1798 elog(ERROR, "get_attstatsslot: stavalues is null");
1799 statarray = DatumGetArrayTypeP(val);
1801 /* Need to get info about the array element type */
1802 typeTuple = SearchSysCache(TYPEOID,
1803 ObjectIdGetDatum(atttype),
1805 if (!HeapTupleIsValid(typeTuple))
1806 elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u",
1808 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1810 /* Deconstruct array into Datum elements */
1811 deconstruct_array(statarray,
1819 * If the element type is pass-by-reference, we now have a bunch
1820 * of Datums that are pointers into the syscache value. Copy them
1821 * to avoid problems if syscache decides to drop the entry.
1823 if (!typeForm->typbyval)
1825 for (j = 0; j < *nvalues; j++)
1827 (*values)[j] = datumCopy((*values)[j],
1833 ReleaseSysCache(typeTuple);
1836 * Free statarray if it's a detoasted copy.
1838 if ((Pointer) statarray != DatumGetPointer(val))
1844 val = SysCacheGetAttr(STATRELATT, statstuple,
1845 Anum_pg_statistic_stanumbers1 + i,
1848 elog(ERROR, "get_attstatsslot: stanumbers is null");
1849 statarray = DatumGetArrayTypeP(val);
1852 * We expect the array to be a 1-D float4 array; verify that. We
1853 * don't need to use deconstruct_array() since the array data is
1854 * just going to look like a C array of float4 values.
1856 narrayelem = ARR_DIMS(statarray)[0];
1857 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1858 ARR_ELEMTYPE(statarray) != FLOAT4OID)
1859 elog(ERROR, "get_attstatsslot: stanumbers is not a 1-D float4 array");
1860 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1861 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1862 *nnumbers = narrayelem;
1865 * Free statarray if it's a detoasted copy.
1867 if ((Pointer) statarray != DatumGetPointer(val))
1875 free_attstatsslot(Oid atttype,
1876 Datum *values, int nvalues,
1877 float4 *numbers, int nnumbers)
1881 if (!get_typbyval(atttype))
1885 for (i = 0; i < nvalues; i++)
1886 pfree(DatumGetPointer(values[i]));
1894 /* ---------- PG_NAMESPACE CACHE ---------- */
1897 * get_namespace_name
1898 * Returns the name of a given namespace
1900 * Returns a palloc'd copy of the string, or NULL if no such namespace.
1903 get_namespace_name(Oid nspid)
1907 tp = SearchSysCache(NAMESPACEOID,
1908 ObjectIdGetDatum(nspid),
1910 if (HeapTupleIsValid(tp))
1912 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
1915 result = pstrdup(NameStr(nsptup->nspname));
1916 ReleaseSysCache(tp);
1923 /* ---------- PG_SHADOW CACHE ---------- */
1928 * Given a user name, look up the user's sysid.
1929 * Raises an error if no such user (rather than returning zero,
1930 * which might possibly be a valid usesysid).
1932 * Note: the type of usesysid is currently int4, but may change to Oid
1933 * someday. It'd be reasonable to return zero on failure if we were
1937 get_usesysid(const char *username)
1942 userTup = SearchSysCache(SHADOWNAME,
1943 PointerGetDatum(username),
1945 if (!HeapTupleIsValid(userTup))
1946 elog(ERROR, "user \"%s\" does not exist", username);
1948 result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
1950 ReleaseSysCache(userTup);