1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2005, 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.126 2005/06/28 05:09:01 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_statistic.h"
28 #include "catalog/pg_type.h"
29 #include "nodes/makefuncs.h"
30 #include "utils/array.h"
31 #include "utils/builtins.h"
32 #include "utils/catcache.h"
33 #include "utils/datum.h"
34 #include "utils/lsyscache.h"
35 #include "utils/syscache.h"
38 /* ---------- AMOP CACHES ---------- */
43 * Return t iff operator 'opno' is in operator class 'opclass'.
46 op_in_opclass(Oid opno, Oid opclass)
48 return SearchSysCacheExists(AMOPOPID,
49 ObjectIdGetDatum(opno),
50 ObjectIdGetDatum(opclass),
55 * get_op_opclass_strategy
57 * Get the operator's strategy number within the specified opclass,
58 * or 0 if it's not a member of the opclass.
61 get_op_opclass_strategy(Oid opno, Oid opclass)
64 Form_pg_amop amop_tup;
67 tp = SearchSysCache(AMOPOPID,
68 ObjectIdGetDatum(opno),
69 ObjectIdGetDatum(opclass),
71 if (!HeapTupleIsValid(tp))
73 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
74 result = amop_tup->amopstrategy;
80 * get_op_opclass_properties
82 * Get the operator's strategy number, subtype, and recheck (lossy) flag
83 * within the specified opclass.
85 * Caller should already have verified that opno is a member of opclass,
86 * therefore we raise an error if the tuple is not found.
89 get_op_opclass_properties(Oid opno, Oid opclass,
90 int *strategy, Oid *subtype, bool *recheck)
93 Form_pg_amop amop_tup;
95 tp = SearchSysCache(AMOPOPID,
96 ObjectIdGetDatum(opno),
97 ObjectIdGetDatum(opclass),
99 if (!HeapTupleIsValid(tp))
100 elog(ERROR, "operator %u is not a member of opclass %u",
102 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
103 *strategy = amop_tup->amopstrategy;
104 *subtype = amop_tup->amopsubtype;
105 *recheck = amop_tup->amopreqcheck;
111 * Get the OID of the operator that implements the specified strategy
112 * with the specified subtype for the specified opclass.
114 * Returns InvalidOid if there is no pg_amop entry for the given keys.
117 get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
120 Form_pg_amop amop_tup;
123 tp = SearchSysCache(AMOPSTRATEGY,
124 ObjectIdGetDatum(opclass),
125 ObjectIdGetDatum(subtype),
126 Int16GetDatum(strategy),
128 if (!HeapTupleIsValid(tp))
130 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
131 result = amop_tup->amopopr;
137 * get_op_hash_function
138 * Get the OID of the datatype-specific hash function associated with
139 * a hashable equality operator.
141 * Returns InvalidOid if no hash function can be found. (This indicates
142 * that the operator should not have been marked oprcanhash.)
145 get_op_hash_function(Oid opno)
149 Oid opclass = InvalidOid;
152 * Search pg_amop to see if the target operator is registered as the
153 * "=" operator of any hash opclass. If the operator is registered in
154 * multiple opclasses, assume we can use the associated hash function
157 catlist = SearchSysCacheList(AMOPOPID, 1,
158 ObjectIdGetDatum(opno),
161 for (i = 0; i < catlist->n_members; i++)
163 HeapTuple tuple = &catlist->members[i]->tuple;
164 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
166 if (aform->amopstrategy == HTEqualStrategyNumber &&
167 opclass_is_hash(aform->amopclaid))
169 opclass = aform->amopclaid;
174 ReleaseSysCacheList(catlist);
176 if (OidIsValid(opclass))
178 /* Found a suitable opclass, get its default hash support function */
179 return get_opclass_proc(opclass, InvalidOid, HASHPROC);
182 /* Didn't find a match... */
187 /* ---------- AMPROC CACHES ---------- */
191 * Get the OID of the specified support function
192 * for the specified opclass and subtype.
194 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
197 get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
200 Form_pg_amproc amproc_tup;
203 tp = SearchSysCache(AMPROCNUM,
204 ObjectIdGetDatum(opclass),
205 ObjectIdGetDatum(subtype),
206 Int16GetDatum(procnum),
208 if (!HeapTupleIsValid(tp))
210 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
211 result = amproc_tup->amproc;
217 /* ---------- ATTRIBUTE CACHES ---------- */
221 * Given the relation id and the attribute number,
222 * return the "attname" field from the attribute relation.
224 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
227 get_attname(Oid relid, AttrNumber attnum)
231 tp = SearchSysCache(ATTNUM,
232 ObjectIdGetDatum(relid),
233 Int16GetDatum(attnum),
235 if (HeapTupleIsValid(tp))
237 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
240 result = pstrdup(NameStr(att_tup->attname));
249 * get_relid_attribute_name
251 * Same as above routine get_attname(), except that error
252 * is handled by elog() instead of returning NULL.
255 get_relid_attribute_name(Oid relid, AttrNumber attnum)
259 attname = get_attname(relid, attnum);
261 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
269 * Given the relation id and the attribute name,
270 * return the "attnum" field from the attribute relation.
272 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
275 get_attnum(Oid relid, const char *attname)
279 tp = SearchSysCacheAttName(relid, attname);
280 if (HeapTupleIsValid(tp))
282 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
285 result = att_tup->attnum;
290 return InvalidAttrNumber;
296 * Given the relation OID and the attribute number with the relation,
297 * return the attribute type OID.
300 get_atttype(Oid relid, AttrNumber attnum)
304 tp = SearchSysCache(ATTNUM,
305 ObjectIdGetDatum(relid),
306 Int16GetDatum(attnum),
308 if (HeapTupleIsValid(tp))
310 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
313 result = att_tup->atttypid;
324 * Given the relation id and the attribute number,
325 * return the "atttypmod" field from the attribute relation.
328 get_atttypmod(Oid relid, AttrNumber attnum)
332 tp = SearchSysCache(ATTNUM,
333 ObjectIdGetDatum(relid),
334 Int16GetDatum(attnum),
336 if (HeapTupleIsValid(tp))
338 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
341 result = att_tup->atttypmod;
352 * A two-fer: given the relation id and the attribute number,
353 * fetch both type OID and atttypmod in a single cache lookup.
355 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
356 * raises an error if it can't obtain the information.
359 get_atttypetypmod(Oid relid, AttrNumber attnum,
360 Oid *typid, int32 *typmod)
363 Form_pg_attribute att_tup;
365 tp = SearchSysCache(ATTNUM,
366 ObjectIdGetDatum(relid),
367 Int16GetDatum(attnum),
369 if (!HeapTupleIsValid(tp))
370 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
372 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
374 *typid = att_tup->atttypid;
375 *typmod = att_tup->atttypmod;
379 /* ---------- INDEX CACHE ---------- */
381 /* watch this space...
384 /* ---------- OPCLASS CACHE ---------- */
389 * Returns TRUE iff the specified opclass is associated with the
390 * btree index access method.
393 opclass_is_btree(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 == BTREE_AM_OID);
414 * Returns TRUE iff the specified opclass is associated with the
415 * hash index access method.
418 opclass_is_hash(Oid opclass)
421 Form_pg_opclass cla_tup;
424 tp = SearchSysCache(CLAOID,
425 ObjectIdGetDatum(opclass),
427 if (!HeapTupleIsValid(tp))
428 elog(ERROR, "cache lookup failed for opclass %u", opclass);
429 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
431 result = (cla_tup->opcamid == HASH_AM_OID);
436 /* ---------- OPERATOR CACHE ---------- */
441 * Returns the regproc id of the routine used to implement an
442 * operator given the operator oid.
449 tp = SearchSysCache(OPEROID,
450 ObjectIdGetDatum(opno),
452 if (HeapTupleIsValid(tp))
454 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
457 result = optup->oprcode;
462 return (RegProcedure) InvalidOid;
467 * returns the name of the operator with the given opno
469 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
476 tp = SearchSysCache(OPEROID,
477 ObjectIdGetDatum(opno),
479 if (HeapTupleIsValid(tp))
481 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
484 result = pstrdup(NameStr(optup->oprname));
495 * Returns the left and right input datatypes for an operator
496 * (InvalidOid if not relevant).
499 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
502 Form_pg_operator optup;
504 tp = SearchSysCache(OPEROID,
505 ObjectIdGetDatum(opno),
507 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
508 elog(ERROR, "cache lookup failed for operator %u", opno);
509 optup = (Form_pg_operator) GETSTRUCT(tp);
510 *lefttype = optup->oprleft;
511 *righttype = optup->oprright;
518 * Returns the left and right sort operators corresponding to a
519 * mergejoinable operator, or false if the operator is not mergejoinable.
522 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
527 tp = SearchSysCache(OPEROID,
528 ObjectIdGetDatum(opno),
530 if (HeapTupleIsValid(tp))
532 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
534 if (optup->oprlsortop &&
537 *leftOp = optup->oprlsortop;
538 *rightOp = optup->oprrsortop;
547 * op_mergejoin_crossops
549 * Returns the cross-type comparison operators (ltype "<" rtype and
550 * ltype ">" rtype) for an operator previously determined to be
551 * mergejoinable. Optionally, fetches the regproc ids of these
552 * operators, as well as their operator OIDs.
555 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
556 RegProcedure *ltproc, RegProcedure *gtproc)
559 Form_pg_operator optup;
562 * Get the declared comparison operators of the operator.
564 tp = SearchSysCache(OPEROID,
565 ObjectIdGetDatum(opno),
567 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
568 elog(ERROR, "cache lookup failed for operator %u", opno);
569 optup = (Form_pg_operator) GETSTRUCT(tp);
570 *ltop = optup->oprltcmpop;
571 *gtop = optup->oprgtcmpop;
574 /* Check < op provided */
575 if (!OidIsValid(*ltop))
576 elog(ERROR, "mergejoin operator %u has no matching < operator",
579 *ltproc = get_opcode(*ltop);
581 /* Check > op provided */
582 if (!OidIsValid(*gtop))
583 elog(ERROR, "mergejoin operator %u has no matching > operator",
586 *gtproc = get_opcode(*gtop);
592 * Returns true if the operator is hashjoinable.
595 op_hashjoinable(Oid opno)
600 tp = SearchSysCache(OPEROID,
601 ObjectIdGetDatum(opno),
603 if (HeapTupleIsValid(tp))
605 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
607 result = optup->oprcanhash;
616 * Get the proisstrict flag for the operator's underlying function.
621 RegProcedure funcid = get_opcode(opno);
623 if (funcid == (RegProcedure) InvalidOid)
624 elog(ERROR, "operator %u does not exist", opno);
626 return func_strict((Oid) funcid);
632 * Get the provolatile flag for the operator's underlying function.
635 op_volatile(Oid opno)
637 RegProcedure funcid = get_opcode(opno);
639 if (funcid == (RegProcedure) InvalidOid)
640 elog(ERROR, "operator %u does not exist", opno);
642 return func_volatile((Oid) funcid);
648 * Returns the corresponding commutator of an operator.
651 get_commutator(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->oprcom;
674 * Returns the corresponding negator of an operator.
677 get_negator(Oid opno)
681 tp = SearchSysCache(OPEROID,
682 ObjectIdGetDatum(opno),
684 if (HeapTupleIsValid(tp))
686 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
689 result = optup->oprnegate;
700 * Returns procedure id for computing selectivity of an operator.
703 get_oprrest(Oid opno)
707 tp = SearchSysCache(OPEROID,
708 ObjectIdGetDatum(opno),
710 if (HeapTupleIsValid(tp))
712 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
715 result = optup->oprrest;
720 return (RegProcedure) InvalidOid;
726 * Returns procedure id for computing selectivity of a join.
729 get_oprjoin(Oid opno)
733 tp = SearchSysCache(OPEROID,
734 ObjectIdGetDatum(opno),
736 if (HeapTupleIsValid(tp))
738 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
741 result = optup->oprjoin;
746 return (RegProcedure) InvalidOid;
749 /* ---------- FUNCTION CACHE ---------- */
753 * returns the name of the function with the given funcid
755 * Note: returns a palloc'd copy of the string, or NULL if no such function.
758 get_func_name(Oid funcid)
762 tp = SearchSysCache(PROCOID,
763 ObjectIdGetDatum(funcid),
765 if (HeapTupleIsValid(tp))
767 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
770 result = pstrdup(NameStr(functup->proname));
780 * Given procedure id, return the function's result type.
783 get_func_rettype(Oid funcid)
788 tp = SearchSysCache(PROCOID,
789 ObjectIdGetDatum(funcid),
791 if (!HeapTupleIsValid(tp))
792 elog(ERROR, "cache lookup failed for function %u", funcid);
794 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
801 * Given procedure id, return the number of arguments.
804 get_func_nargs(Oid funcid)
809 tp = SearchSysCache(PROCOID,
810 ObjectIdGetDatum(funcid),
812 if (!HeapTupleIsValid(tp))
813 elog(ERROR, "cache lookup failed for function %u", funcid);
815 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
822 * Given procedure id, return the function's argument and result types.
823 * (The return value is the result type.)
825 * The arguments are returned as a palloc'd array.
828 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
831 Form_pg_proc procstruct;
834 tp = SearchSysCache(PROCOID,
835 ObjectIdGetDatum(funcid),
837 if (!HeapTupleIsValid(tp))
838 elog(ERROR, "cache lookup failed for function %u", funcid);
840 procstruct = (Form_pg_proc) GETSTRUCT(tp);
842 result = procstruct->prorettype;
843 *nargs = (int) procstruct->pronargs;
844 Assert(*nargs == procstruct->proargtypes.dim1);
845 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
846 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
854 * Given procedure id, return the function's proretset flag.
857 get_func_retset(Oid funcid)
862 tp = SearchSysCache(PROCOID,
863 ObjectIdGetDatum(funcid),
865 if (!HeapTupleIsValid(tp))
866 elog(ERROR, "cache lookup failed for function %u", funcid);
868 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
875 * Given procedure id, return the function's proisstrict flag.
878 func_strict(Oid funcid)
883 tp = SearchSysCache(PROCOID,
884 ObjectIdGetDatum(funcid),
886 if (!HeapTupleIsValid(tp))
887 elog(ERROR, "cache lookup failed for function %u", funcid);
889 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
896 * Given procedure id, return the function's provolatile flag.
899 func_volatile(Oid funcid)
904 tp = SearchSysCache(PROCOID,
905 ObjectIdGetDatum(funcid),
907 if (!HeapTupleIsValid(tp))
908 elog(ERROR, "cache lookup failed for function %u", funcid);
910 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
915 /* ---------- RELATION CACHE ---------- */
919 * Given name and namespace of a relation, look up the OID.
921 * Returns InvalidOid if there is no such relation.
924 get_relname_relid(const char *relname, Oid relnamespace)
926 return GetSysCacheOid(RELNAMENSP,
927 PointerGetDatum(relname),
928 ObjectIdGetDatum(relnamespace),
936 * Returns the number of attributes for a given relation.
939 get_relnatts(Oid relid)
943 tp = SearchSysCache(RELOID,
944 ObjectIdGetDatum(relid),
946 if (HeapTupleIsValid(tp))
948 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
951 result = reltup->relnatts;
956 return InvalidAttrNumber;
962 * Returns the name of a given relation.
964 * Returns a palloc'd copy of the string, or NULL if no such relation.
966 * NOTE: since relation name is not unique, be wary of code that uses this
967 * for anything except preparing error messages.
970 get_rel_name(Oid relid)
974 tp = SearchSysCache(RELOID,
975 ObjectIdGetDatum(relid),
977 if (HeapTupleIsValid(tp))
979 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
982 result = pstrdup(NameStr(reltup->relname));
993 * Returns the pg_namespace OID associated with a given relation.
996 get_rel_namespace(Oid relid)
1000 tp = SearchSysCache(RELOID,
1001 ObjectIdGetDatum(relid),
1003 if (HeapTupleIsValid(tp))
1005 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1008 result = reltup->relnamespace;
1009 ReleaseSysCache(tp);
1019 * Returns the pg_type OID associated with a given relation.
1021 * Note: not all pg_class entries have associated pg_type OIDs; so be
1022 * careful to check for InvalidOid result.
1025 get_rel_type_id(Oid relid)
1029 tp = SearchSysCache(RELOID,
1030 ObjectIdGetDatum(relid),
1032 if (HeapTupleIsValid(tp))
1034 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1037 result = reltup->reltype;
1038 ReleaseSysCache(tp);
1048 * Returns the relkind associated with a given relation.
1051 get_rel_relkind(Oid relid)
1055 tp = SearchSysCache(RELOID,
1056 ObjectIdGetDatum(relid),
1058 if (HeapTupleIsValid(tp))
1060 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1063 result = reltup->relkind;
1064 ReleaseSysCache(tp);
1072 /* ---------- TYPE CACHE ---------- */
1077 * Given the type OID, determine whether the type is defined
1078 * (if not, it's only a shell).
1081 get_typisdefined(Oid typid)
1085 tp = SearchSysCache(TYPEOID,
1086 ObjectIdGetDatum(typid),
1088 if (HeapTupleIsValid(tp))
1090 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1093 result = typtup->typisdefined;
1094 ReleaseSysCache(tp);
1104 * Given the type OID, return the length of the type.
1107 get_typlen(Oid typid)
1111 tp = SearchSysCache(TYPEOID,
1112 ObjectIdGetDatum(typid),
1114 if (HeapTupleIsValid(tp))
1116 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1119 result = typtup->typlen;
1120 ReleaseSysCache(tp);
1130 * Given the type OID, determine whether the type is returned by value or
1131 * not. Returns true if by value, false if by reference.
1134 get_typbyval(Oid typid)
1138 tp = SearchSysCache(TYPEOID,
1139 ObjectIdGetDatum(typid),
1141 if (HeapTupleIsValid(tp))
1143 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1146 result = typtup->typbyval;
1147 ReleaseSysCache(tp);
1157 * A two-fer: given the type OID, return both typlen and typbyval.
1159 * Since both pieces of info are needed to know how to copy a Datum,
1160 * many places need both. Might as well get them with one cache lookup
1161 * instead of two. Also, this routine raises an error instead of
1162 * returning a bogus value when given a bad type OID.
1165 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1168 Form_pg_type typtup;
1170 tp = SearchSysCache(TYPEOID,
1171 ObjectIdGetDatum(typid),
1173 if (!HeapTupleIsValid(tp))
1174 elog(ERROR, "cache lookup failed for type %u", typid);
1175 typtup = (Form_pg_type) GETSTRUCT(tp);
1176 *typlen = typtup->typlen;
1177 *typbyval = typtup->typbyval;
1178 ReleaseSysCache(tp);
1182 * get_typlenbyvalalign
1184 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1187 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1191 Form_pg_type typtup;
1193 tp = SearchSysCache(TYPEOID,
1194 ObjectIdGetDatum(typid),
1196 if (!HeapTupleIsValid(tp))
1197 elog(ERROR, "cache lookup failed for type %u", typid);
1198 typtup = (Form_pg_type) GETSTRUCT(tp);
1199 *typlen = typtup->typlen;
1200 *typbyval = typtup->typbyval;
1201 *typalign = typtup->typalign;
1202 ReleaseSysCache(tp);
1207 * Given a pg_type row, select the type OID to pass to I/O functions
1209 * Formerly, all I/O functions were passed pg_type.typelem as their second
1210 * parameter, but we now have a more complex rule about what to pass.
1211 * This knowledge is intended to be centralized here --- direct references
1212 * to typelem elsewhere in the code are wrong, if they are associated with
1213 * I/O calls and not with actual subscripting operations! (But see
1214 * bootstrap.c, which can't conveniently use this routine.)
1216 * As of PostgreSQL 8.1, output functions receive only the value itself
1217 * and not any auxiliary parameters, so the name of this routine is now
1218 * a bit of a misnomer ... it should be getTypeInputParam.
1221 getTypeIOParam(HeapTuple typeTuple)
1223 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1226 * Composite types get their own OID as parameter; array types get
1227 * their typelem as parameter; everybody else gets zero.
1229 if (typeStruct->typtype == 'c')
1230 return HeapTupleGetOid(typeTuple);
1232 return typeStruct->typelem;
1238 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1239 * typdelim, typioparam, and IO function OID. The IO function
1240 * returned is controlled by IOFuncSelector
1243 get_type_io_data(Oid typid,
1244 IOFuncSelector which_func,
1252 HeapTuple typeTuple;
1253 Form_pg_type typeStruct;
1255 typeTuple = SearchSysCache(TYPEOID,
1256 ObjectIdGetDatum(typid),
1258 if (!HeapTupleIsValid(typeTuple))
1259 elog(ERROR, "cache lookup failed for type %u", typid);
1260 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1262 *typlen = typeStruct->typlen;
1263 *typbyval = typeStruct->typbyval;
1264 *typalign = typeStruct->typalign;
1265 *typdelim = typeStruct->typdelim;
1266 *typioparam = getTypeIOParam(typeTuple);
1270 *func = typeStruct->typinput;
1273 *func = typeStruct->typoutput;
1275 case IOFunc_receive:
1276 *func = typeStruct->typreceive;
1279 *func = typeStruct->typsend;
1282 ReleaseSysCache(typeTuple);
1287 get_typalign(Oid typid)
1291 tp = SearchSysCache(TYPEOID,
1292 ObjectIdGetDatum(typid),
1294 if (HeapTupleIsValid(tp))
1296 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1299 result = typtup->typalign;
1300 ReleaseSysCache(tp);
1309 get_typstorage(Oid typid)
1313 tp = SearchSysCache(TYPEOID,
1314 ObjectIdGetDatum(typid),
1316 if (HeapTupleIsValid(tp))
1318 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1321 result = typtup->typstorage;
1322 ReleaseSysCache(tp);
1332 * Given the type OID, return the typtypmod field (domain's typmod
1336 get_typtypmod(Oid typid)
1340 tp = SearchSysCache(TYPEOID,
1341 ObjectIdGetDatum(typid),
1343 if (HeapTupleIsValid(tp))
1345 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1348 result = typtup->typtypmod;
1349 ReleaseSysCache(tp);
1358 * Given a type OID, return the type's default value, if any.
1360 * The result is a palloc'd expression node tree, or NULL if there
1361 * is no defined default for the datatype.
1363 * NB: caller should be prepared to coerce result to correct datatype;
1364 * the returned expression tree might produce something of the wrong type.
1367 get_typdefault(Oid typid)
1369 HeapTuple typeTuple;
1375 typeTuple = SearchSysCache(TYPEOID,
1376 ObjectIdGetDatum(typid),
1378 if (!HeapTupleIsValid(typeTuple))
1379 elog(ERROR, "cache lookup failed for type %u", typid);
1380 type = (Form_pg_type) GETSTRUCT(typeTuple);
1383 * typdefault and typdefaultbin are potentially null, so don't try to
1384 * access 'em as struct fields. Must do it the hard way with
1387 datum = SysCacheGetAttr(TYPEOID,
1389 Anum_pg_type_typdefaultbin,
1394 /* We have an expression default */
1395 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1400 /* Perhaps we have a plain literal default */
1401 datum = SysCacheGetAttr(TYPEOID,
1403 Anum_pg_type_typdefault,
1408 char *strDefaultVal;
1410 /* Convert text datum to C string */
1411 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1413 /* Convert C string to a value of the given type */
1414 datum = OidFunctionCall3(type->typinput,
1415 CStringGetDatum(strDefaultVal),
1416 ObjectIdGetDatum(getTypeIOParam(typeTuple)),
1418 /* Build a Const node containing the value */
1419 expr = (Node *) makeConst(typid,
1424 pfree(strDefaultVal);
1433 ReleaseSysCache(typeTuple);
1440 * If the given type is a domain, return its base type;
1441 * otherwise return the type's own OID.
1444 getBaseType(Oid typid)
1447 * We loop to find the bottom base type in a stack of domains.
1452 Form_pg_type typTup;
1454 tup = SearchSysCache(TYPEOID,
1455 ObjectIdGetDatum(typid),
1457 if (!HeapTupleIsValid(tup))
1458 elog(ERROR, "cache lookup failed for type %u", typid);
1459 typTup = (Form_pg_type) GETSTRUCT(tup);
1460 if (typTup->typtype != 'd')
1462 /* Not a domain, so done */
1463 ReleaseSysCache(tup);
1467 typid = typTup->typbasetype;
1468 ReleaseSysCache(tup);
1477 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1478 * estimate the average width of values of the type. This is used by
1479 * the planner, which doesn't require absolutely correct results;
1480 * it's OK (and expected) to guess if we don't know for sure.
1483 get_typavgwidth(Oid typid, int32 typmod)
1485 int typlen = get_typlen(typid);
1489 * Easy if it's a fixed-width type
1495 * type_maximum_size knows the encoding of typmod for some datatypes;
1496 * don't duplicate that knowledge here.
1498 maxwidth = type_maximum_size(typid, typmod);
1502 * For BPCHAR, the max width is also the only width. Otherwise we
1503 * need to guess about the typical data width given the max. A
1504 * sliding scale for percentage of max width seems reasonable.
1506 if (typid == BPCHAROID)
1509 return maxwidth; /* assume full width */
1510 if (maxwidth < 1000)
1511 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1514 * Beyond 1000, assume we're looking at something like
1515 * "varchar(10000)" where the limit isn't actually reached often,
1516 * and use a fixed estimate.
1518 return 32 + (1000 - 32) / 2;
1522 * Ooops, we have no idea ... wild guess time.
1530 * Given the type OID, find if it is a basic type, a complex type, etc.
1531 * It returns the null char if the cache lookup fails...
1534 get_typtype(Oid typid)
1538 tp = SearchSysCache(TYPEOID,
1539 ObjectIdGetDatum(typid),
1541 if (HeapTupleIsValid(tp))
1543 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1546 result = typtup->typtype;
1547 ReleaseSysCache(tp);
1557 * Given the type OID, get the typrelid (InvalidOid if not a complex
1561 get_typ_typrelid(Oid typid)
1565 tp = SearchSysCache(TYPEOID,
1566 ObjectIdGetDatum(typid),
1568 if (HeapTupleIsValid(tp))
1570 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1573 result = typtup->typrelid;
1574 ReleaseSysCache(tp);
1584 * Given the type OID, get the typelem (InvalidOid if not an array type).
1586 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
1587 * returned if the input is a fixed-length array type.
1590 get_element_type(Oid typid)
1594 tp = SearchSysCache(TYPEOID,
1595 ObjectIdGetDatum(typid),
1597 if (HeapTupleIsValid(tp))
1599 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1602 if (typtup->typlen == -1)
1603 result = typtup->typelem;
1605 result = InvalidOid;
1606 ReleaseSysCache(tp);
1616 * Given the type OID, get the corresponding array type.
1617 * Returns InvalidOid if no array type can be found.
1619 * NB: this only considers varlena arrays to be true arrays.
1622 get_array_type(Oid typid)
1626 tp = SearchSysCache(TYPEOID,
1627 ObjectIdGetDatum(typid),
1629 if (HeapTupleIsValid(tp))
1631 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1632 char *array_typename;
1635 array_typename = makeArrayTypeName(NameStr(typtup->typname));
1636 namespaceId = typtup->typnamespace;
1637 ReleaseSysCache(tp);
1639 tp = SearchSysCache(TYPENAMENSP,
1640 PointerGetDatum(array_typename),
1641 ObjectIdGetDatum(namespaceId),
1644 pfree(array_typename);
1646 if (HeapTupleIsValid(tp))
1650 typtup = (Form_pg_type) GETSTRUCT(tp);
1651 if (typtup->typlen == -1 && typtup->typelem == typid)
1652 result = HeapTupleGetOid(tp);
1654 result = InvalidOid;
1655 ReleaseSysCache(tp);
1665 * Get info needed for converting values of a type to internal form
1668 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
1670 HeapTuple typeTuple;
1673 typeTuple = SearchSysCache(TYPEOID,
1674 ObjectIdGetDatum(type),
1676 if (!HeapTupleIsValid(typeTuple))
1677 elog(ERROR, "cache lookup failed for type %u", type);
1678 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1680 if (!pt->typisdefined)
1682 (errcode(ERRCODE_UNDEFINED_OBJECT),
1683 errmsg("type %s is only a shell",
1684 format_type_be(type))));
1685 if (!OidIsValid(pt->typinput))
1687 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1688 errmsg("no input function available for type %s",
1689 format_type_be(type))));
1691 *typInput = pt->typinput;
1692 *typIOParam = getTypeIOParam(typeTuple);
1694 ReleaseSysCache(typeTuple);
1700 * Get info needed for printing values of a type
1703 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
1705 HeapTuple typeTuple;
1708 typeTuple = SearchSysCache(TYPEOID,
1709 ObjectIdGetDatum(type),
1711 if (!HeapTupleIsValid(typeTuple))
1712 elog(ERROR, "cache lookup failed for type %u", type);
1713 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1715 if (!pt->typisdefined)
1717 (errcode(ERRCODE_UNDEFINED_OBJECT),
1718 errmsg("type %s is only a shell",
1719 format_type_be(type))));
1720 if (!OidIsValid(pt->typoutput))
1722 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1723 errmsg("no output function available for type %s",
1724 format_type_be(type))));
1726 *typOutput = pt->typoutput;
1727 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1729 ReleaseSysCache(typeTuple);
1733 * getTypeBinaryInputInfo
1735 * Get info needed for binary input of values of a type
1738 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
1740 HeapTuple typeTuple;
1743 typeTuple = SearchSysCache(TYPEOID,
1744 ObjectIdGetDatum(type),
1746 if (!HeapTupleIsValid(typeTuple))
1747 elog(ERROR, "cache lookup failed for type %u", type);
1748 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1750 if (!pt->typisdefined)
1752 (errcode(ERRCODE_UNDEFINED_OBJECT),
1753 errmsg("type %s is only a shell",
1754 format_type_be(type))));
1755 if (!OidIsValid(pt->typreceive))
1757 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1758 errmsg("no binary input function available for type %s",
1759 format_type_be(type))));
1761 *typReceive = pt->typreceive;
1762 *typIOParam = getTypeIOParam(typeTuple);
1764 ReleaseSysCache(typeTuple);
1768 * getTypeBinaryOutputInfo
1770 * Get info needed for binary output of values of a type
1773 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
1775 HeapTuple typeTuple;
1778 typeTuple = SearchSysCache(TYPEOID,
1779 ObjectIdGetDatum(type),
1781 if (!HeapTupleIsValid(typeTuple))
1782 elog(ERROR, "cache lookup failed for type %u", type);
1783 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1785 if (!pt->typisdefined)
1787 (errcode(ERRCODE_UNDEFINED_OBJECT),
1788 errmsg("type %s is only a shell",
1789 format_type_be(type))));
1790 if (!OidIsValid(pt->typsend))
1792 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1793 errmsg("no binary output function available for type %s",
1794 format_type_be(type))));
1796 *typSend = pt->typsend;
1797 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1799 ReleaseSysCache(typeTuple);
1803 /* ---------- STATISTICS CACHE ---------- */
1808 * Given the table and attribute number of a column, get the average
1809 * width of entries in the column. Return zero if no data available.
1812 get_attavgwidth(Oid relid, AttrNumber attnum)
1816 tp = SearchSysCache(STATRELATT,
1817 ObjectIdGetDatum(relid),
1818 Int16GetDatum(attnum),
1820 if (HeapTupleIsValid(tp))
1822 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1824 ReleaseSysCache(tp);
1834 * Extract the contents of a "slot" of a pg_statistic tuple.
1835 * Returns TRUE if requested slot type was found, else FALSE.
1837 * Unlike other routines in this file, this takes a pointer to an
1838 * already-looked-up tuple in the pg_statistic cache. We do this since
1839 * most callers will want to extract more than one value from the cache
1840 * entry, and we don't want to repeat the cache lookup unnecessarily.
1842 * statstuple: pg_statistics tuple to be examined.
1843 * atttype: type OID of attribute.
1844 * atttypmod: typmod of attribute.
1845 * reqkind: STAKIND code for desired statistics slot kind.
1846 * reqop: STAOP value wanted, or InvalidOid if don't care.
1847 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1848 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1850 * If assigned, values and numbers are set to point to palloc'd arrays.
1851 * If the attribute type is pass-by-reference, the values referenced by
1852 * the values array are themselves palloc'd. The palloc'd stuff can be
1853 * freed by calling free_attstatsslot.
1856 get_attstatsslot(HeapTuple statstuple,
1857 Oid atttype, int32 atttypmod,
1858 int reqkind, Oid reqop,
1859 Datum **values, int *nvalues,
1860 float4 **numbers, int *nnumbers)
1862 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1867 ArrayType *statarray;
1869 HeapTuple typeTuple;
1870 Form_pg_type typeForm;
1872 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1874 if ((&stats->stakind1)[i] == reqkind &&
1875 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1878 if (i >= STATISTIC_NUM_SLOTS)
1879 return false; /* not there */
1883 val = SysCacheGetAttr(STATRELATT, statstuple,
1884 Anum_pg_statistic_stavalues1 + i,
1887 elog(ERROR, "stavalues is null");
1888 statarray = DatumGetArrayTypeP(val);
1890 /* Need to get info about the array element type */
1891 typeTuple = SearchSysCache(TYPEOID,
1892 ObjectIdGetDatum(atttype),
1894 if (!HeapTupleIsValid(typeTuple))
1895 elog(ERROR, "cache lookup failed for type %u", atttype);
1896 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1898 /* Deconstruct array into Datum elements */
1899 deconstruct_array(statarray,
1907 * If the element type is pass-by-reference, we now have a bunch
1908 * of Datums that are pointers into the syscache value. Copy them
1909 * to avoid problems if syscache decides to drop the entry.
1911 if (!typeForm->typbyval)
1913 for (j = 0; j < *nvalues; j++)
1915 (*values)[j] = datumCopy((*values)[j],
1921 ReleaseSysCache(typeTuple);
1924 * Free statarray if it's a detoasted copy.
1926 if ((Pointer) statarray != DatumGetPointer(val))
1932 val = SysCacheGetAttr(STATRELATT, statstuple,
1933 Anum_pg_statistic_stanumbers1 + i,
1936 elog(ERROR, "stanumbers is null");
1937 statarray = DatumGetArrayTypeP(val);
1940 * We expect the array to be a 1-D float4 array; verify that. We
1941 * don't need to use deconstruct_array() since the array data is
1942 * just going to look like a C array of float4 values.
1944 narrayelem = ARR_DIMS(statarray)[0];
1945 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1946 ARR_ELEMTYPE(statarray) != FLOAT4OID)
1947 elog(ERROR, "stanumbers is not a 1-D float4 array");
1948 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1949 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1950 *nnumbers = narrayelem;
1953 * Free statarray if it's a detoasted copy.
1955 if ((Pointer) statarray != DatumGetPointer(val))
1963 free_attstatsslot(Oid atttype,
1964 Datum *values, int nvalues,
1965 float4 *numbers, int nnumbers)
1969 if (!get_typbyval(atttype))
1973 for (i = 0; i < nvalues; i++)
1974 pfree(DatumGetPointer(values[i]));
1982 /* ---------- PG_NAMESPACE CACHE ---------- */
1985 * get_namespace_name
1986 * Returns the name of a given namespace
1988 * Returns a palloc'd copy of the string, or NULL if no such namespace.
1991 get_namespace_name(Oid nspid)
1995 tp = SearchSysCache(NAMESPACEOID,
1996 ObjectIdGetDatum(nspid),
1998 if (HeapTupleIsValid(tp))
2000 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2003 result = pstrdup(NameStr(nsptup->nspname));
2004 ReleaseSysCache(tp);
2011 /* ---------- PG_AUTHID CACHE ---------- */
2015 * Given a role name, look up the role's OID.
2016 * Returns InvalidOid if no such role.
2019 get_roleid(const char *rolname)
2021 return GetSysCacheOid(AUTHNAME,
2022 PointerGetDatum(rolname),
2027 * get_roleid_checked
2028 * Given a role name, look up the role's OID.
2029 * ereports if no such role.
2032 get_roleid_checked(const char *rolname)
2036 roleid = get_roleid(rolname);
2037 if (!OidIsValid(roleid))
2039 (errcode(ERRCODE_UNDEFINED_OBJECT),
2040 errmsg("role \"%s\" does not exist", rolname)));