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.122 2005/03/31 22:46:14 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_group.h"
29 #include "catalog/pg_statistic.h"
30 #include "catalog/pg_type.h"
31 #include "nodes/makefuncs.h"
32 #include "utils/array.h"
33 #include "utils/builtins.h"
34 #include "utils/catcache.h"
35 #include "utils/datum.h"
36 #include "utils/lsyscache.h"
37 #include "utils/syscache.h"
40 /* ---------- AMOP CACHES ---------- */
45 * Return t iff operator 'opno' is in operator class 'opclass'.
48 op_in_opclass(Oid opno, Oid opclass)
50 return SearchSysCacheExists(AMOPOPID,
51 ObjectIdGetDatum(opno),
52 ObjectIdGetDatum(opclass),
57 * get_op_opclass_properties
59 * Get the operator's strategy number, subtype, and recheck (lossy) flag
60 * within the specified opclass.
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 get_op_opclass_properties(Oid opno, Oid opclass,
67 int *strategy, Oid *subtype, bool *recheck)
70 Form_pg_amop amop_tup;
72 tp = SearchSysCache(AMOPOPID,
73 ObjectIdGetDatum(opno),
74 ObjectIdGetDatum(opclass),
76 if (!HeapTupleIsValid(tp))
77 elog(ERROR, "operator %u is not a member of opclass %u",
79 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
80 *strategy = amop_tup->amopstrategy;
81 *subtype = amop_tup->amopsubtype;
82 *recheck = amop_tup->amopreqcheck;
88 * Get the OID of the operator that implements the specified strategy
89 * with the specified subtype for the specified opclass.
91 * Returns InvalidOid if there is no pg_amop entry for the given keys.
94 get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
97 Form_pg_amop amop_tup;
100 tp = SearchSysCache(AMOPSTRATEGY,
101 ObjectIdGetDatum(opclass),
102 ObjectIdGetDatum(subtype),
103 Int16GetDatum(strategy),
105 if (!HeapTupleIsValid(tp))
107 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
108 result = amop_tup->amopopr;
114 * get_op_hash_function
115 * Get the OID of the datatype-specific hash function associated with
116 * a hashable equality operator.
118 * Returns InvalidOid if no hash function can be found. (This indicates
119 * that the operator should not have been marked oprcanhash.)
122 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++)
140 HeapTuple tuple = &catlist->members[i]->tuple;
141 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
143 if (aform->amopstrategy == HTEqualStrategyNumber &&
144 opclass_is_hash(aform->amopclaid))
146 opclass = aform->amopclaid;
151 ReleaseSysCacheList(catlist);
153 if (OidIsValid(opclass))
155 /* Found a suitable opclass, get its default hash support function */
156 return get_opclass_proc(opclass, InvalidOid, HASHPROC);
159 /* Didn't find a match... */
164 /* ---------- AMPROC CACHES ---------- */
168 * Get the OID of the specified support function
169 * for the specified opclass and subtype.
171 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
174 get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
177 Form_pg_amproc amproc_tup;
180 tp = SearchSysCache(AMPROCNUM,
181 ObjectIdGetDatum(opclass),
182 ObjectIdGetDatum(subtype),
183 Int16GetDatum(procnum),
185 if (!HeapTupleIsValid(tp))
187 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
188 result = amproc_tup->amproc;
194 /* ---------- ATTRIBUTE CACHES ---------- */
198 * Given the relation id and the attribute number,
199 * return the "attname" field from the attribute relation.
201 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
204 get_attname(Oid relid, AttrNumber attnum)
208 tp = SearchSysCache(ATTNUM,
209 ObjectIdGetDatum(relid),
210 Int16GetDatum(attnum),
212 if (HeapTupleIsValid(tp))
214 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
217 result = pstrdup(NameStr(att_tup->attname));
226 * get_relid_attribute_name
228 * Same as above routine get_attname(), except that error
229 * is handled by elog() instead of returning NULL.
232 get_relid_attribute_name(Oid relid, AttrNumber attnum)
236 attname = get_attname(relid, attnum);
238 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
246 * Given the relation id and the attribute name,
247 * return the "attnum" field from the attribute relation.
249 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
252 get_attnum(Oid relid, const char *attname)
256 tp = SearchSysCacheAttName(relid, attname);
257 if (HeapTupleIsValid(tp))
259 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
262 result = att_tup->attnum;
267 return InvalidAttrNumber;
273 * Given the relation OID and the attribute number with the relation,
274 * return the attribute type OID.
277 get_atttype(Oid relid, AttrNumber attnum)
281 tp = SearchSysCache(ATTNUM,
282 ObjectIdGetDatum(relid),
283 Int16GetDatum(attnum),
285 if (HeapTupleIsValid(tp))
287 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
290 result = att_tup->atttypid;
301 * Given the relation id and the attribute number,
302 * return the "atttypmod" field from the attribute relation.
305 get_atttypmod(Oid relid, AttrNumber attnum)
309 tp = SearchSysCache(ATTNUM,
310 ObjectIdGetDatum(relid),
311 Int16GetDatum(attnum),
313 if (HeapTupleIsValid(tp))
315 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
318 result = att_tup->atttypmod;
329 * A two-fer: given the relation id and the attribute number,
330 * fetch both type OID and atttypmod in a single cache lookup.
332 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
333 * raises an error if it can't obtain the information.
336 get_atttypetypmod(Oid relid, AttrNumber attnum,
337 Oid *typid, int32 *typmod)
340 Form_pg_attribute att_tup;
342 tp = SearchSysCache(ATTNUM,
343 ObjectIdGetDatum(relid),
344 Int16GetDatum(attnum),
346 if (!HeapTupleIsValid(tp))
347 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
349 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
351 *typid = att_tup->atttypid;
352 *typmod = att_tup->atttypmod;
356 /* ---------- INDEX CACHE ---------- */
358 /* watch this space...
361 /* ---------- OPCLASS CACHE ---------- */
366 * Returns TRUE iff the specified opclass is associated with the
367 * btree index access method.
370 opclass_is_btree(Oid opclass)
373 Form_pg_opclass cla_tup;
376 tp = SearchSysCache(CLAOID,
377 ObjectIdGetDatum(opclass),
379 if (!HeapTupleIsValid(tp))
380 elog(ERROR, "cache lookup failed for opclass %u", opclass);
381 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
383 result = (cla_tup->opcamid == BTREE_AM_OID);
391 * Returns TRUE iff the specified opclass is associated with the
392 * hash index access method.
395 opclass_is_hash(Oid opclass)
398 Form_pg_opclass cla_tup;
401 tp = SearchSysCache(CLAOID,
402 ObjectIdGetDatum(opclass),
404 if (!HeapTupleIsValid(tp))
405 elog(ERROR, "cache lookup failed for opclass %u", opclass);
406 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
408 result = (cla_tup->opcamid == HASH_AM_OID);
413 /* ---------- OPERATOR CACHE ---------- */
418 * Returns the regproc id of the routine used to implement an
419 * operator given the operator oid.
426 tp = SearchSysCache(OPEROID,
427 ObjectIdGetDatum(opno),
429 if (HeapTupleIsValid(tp))
431 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
434 result = optup->oprcode;
439 return (RegProcedure) InvalidOid;
444 * returns the name of the operator with the given opno
446 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
453 tp = SearchSysCache(OPEROID,
454 ObjectIdGetDatum(opno),
456 if (HeapTupleIsValid(tp))
458 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
461 result = pstrdup(NameStr(optup->oprname));
472 * Returns the left and right input datatypes for an operator
473 * (InvalidOid if not relevant).
476 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
479 Form_pg_operator optup;
481 tp = SearchSysCache(OPEROID,
482 ObjectIdGetDatum(opno),
484 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
485 elog(ERROR, "cache lookup failed for operator %u", opno);
486 optup = (Form_pg_operator) GETSTRUCT(tp);
487 *lefttype = optup->oprleft;
488 *righttype = optup->oprright;
495 * Returns the left and right sort operators corresponding to a
496 * mergejoinable operator, or false if the operator is not mergejoinable.
499 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
504 tp = SearchSysCache(OPEROID,
505 ObjectIdGetDatum(opno),
507 if (HeapTupleIsValid(tp))
509 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
511 if (optup->oprlsortop &&
514 *leftOp = optup->oprlsortop;
515 *rightOp = optup->oprrsortop;
524 * op_mergejoin_crossops
526 * Returns the cross-type comparison operators (ltype "<" rtype and
527 * ltype ">" rtype) for an operator previously determined to be
528 * mergejoinable. Optionally, fetches the regproc ids of these
529 * operators, as well as their operator OIDs.
532 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
533 RegProcedure *ltproc, RegProcedure *gtproc)
536 Form_pg_operator optup;
539 * Get the declared comparison operators of the operator.
541 tp = SearchSysCache(OPEROID,
542 ObjectIdGetDatum(opno),
544 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
545 elog(ERROR, "cache lookup failed for operator %u", opno);
546 optup = (Form_pg_operator) GETSTRUCT(tp);
547 *ltop = optup->oprltcmpop;
548 *gtop = optup->oprgtcmpop;
551 /* Check < op provided */
552 if (!OidIsValid(*ltop))
553 elog(ERROR, "mergejoin operator %u has no matching < operator",
556 *ltproc = get_opcode(*ltop);
558 /* Check > op provided */
559 if (!OidIsValid(*gtop))
560 elog(ERROR, "mergejoin operator %u has no matching > operator",
563 *gtproc = get_opcode(*gtop);
569 * Returns true if the operator is hashjoinable.
572 op_hashjoinable(Oid opno)
577 tp = SearchSysCache(OPEROID,
578 ObjectIdGetDatum(opno),
580 if (HeapTupleIsValid(tp))
582 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
584 result = optup->oprcanhash;
593 * Get the proisstrict flag for the operator's underlying function.
598 RegProcedure funcid = get_opcode(opno);
600 if (funcid == (RegProcedure) InvalidOid)
601 elog(ERROR, "operator %u does not exist", opno);
603 return func_strict((Oid) funcid);
609 * Get the provolatile flag for the operator's underlying function.
612 op_volatile(Oid opno)
614 RegProcedure funcid = get_opcode(opno);
616 if (funcid == (RegProcedure) InvalidOid)
617 elog(ERROR, "operator %u does not exist", opno);
619 return func_volatile((Oid) funcid);
625 * Returns the corresponding commutator of an operator.
628 get_commutator(Oid opno)
632 tp = SearchSysCache(OPEROID,
633 ObjectIdGetDatum(opno),
635 if (HeapTupleIsValid(tp))
637 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
640 result = optup->oprcom;
651 * Returns the corresponding negator of an operator.
654 get_negator(Oid opno)
658 tp = SearchSysCache(OPEROID,
659 ObjectIdGetDatum(opno),
661 if (HeapTupleIsValid(tp))
663 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
666 result = optup->oprnegate;
677 * Returns procedure id for computing selectivity of an operator.
680 get_oprrest(Oid opno)
684 tp = SearchSysCache(OPEROID,
685 ObjectIdGetDatum(opno),
687 if (HeapTupleIsValid(tp))
689 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
692 result = optup->oprrest;
697 return (RegProcedure) InvalidOid;
703 * Returns procedure id for computing selectivity of a join.
706 get_oprjoin(Oid opno)
710 tp = SearchSysCache(OPEROID,
711 ObjectIdGetDatum(opno),
713 if (HeapTupleIsValid(tp))
715 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
718 result = optup->oprjoin;
723 return (RegProcedure) InvalidOid;
726 /* ---------- FUNCTION CACHE ---------- */
730 * returns the name of the function with the given funcid
732 * Note: returns a palloc'd copy of the string, or NULL if no such function.
735 get_func_name(Oid funcid)
739 tp = SearchSysCache(PROCOID,
740 ObjectIdGetDatum(funcid),
742 if (HeapTupleIsValid(tp))
744 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
747 result = pstrdup(NameStr(functup->proname));
757 * Given procedure id, return the function's result type.
760 get_func_rettype(Oid funcid)
765 tp = SearchSysCache(PROCOID,
766 ObjectIdGetDatum(funcid),
768 if (!HeapTupleIsValid(tp))
769 elog(ERROR, "cache lookup failed for function %u", funcid);
771 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
778 * Given procedure id, return the number of arguments.
781 get_func_nargs(Oid funcid)
786 tp = SearchSysCache(PROCOID,
787 ObjectIdGetDatum(funcid),
789 if (!HeapTupleIsValid(tp))
790 elog(ERROR, "cache lookup failed for function %u", funcid);
792 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
799 * Given procedure id, return the function's argument and result types.
800 * (The return value is the result type.)
802 * The arguments are returned as a palloc'd array.
805 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
808 Form_pg_proc procstruct;
811 tp = SearchSysCache(PROCOID,
812 ObjectIdGetDatum(funcid),
814 if (!HeapTupleIsValid(tp))
815 elog(ERROR, "cache lookup failed for function %u", funcid);
817 procstruct = (Form_pg_proc) GETSTRUCT(tp);
819 result = procstruct->prorettype;
820 *nargs = (int) procstruct->pronargs;
821 Assert(*nargs == procstruct->proargtypes.dim1);
822 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
823 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
831 * Given procedure id, return the function's proretset flag.
834 get_func_retset(Oid funcid)
839 tp = SearchSysCache(PROCOID,
840 ObjectIdGetDatum(funcid),
842 if (!HeapTupleIsValid(tp))
843 elog(ERROR, "cache lookup failed for function %u", funcid);
845 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
852 * Given procedure id, return the function's proisstrict flag.
855 func_strict(Oid funcid)
860 tp = SearchSysCache(PROCOID,
861 ObjectIdGetDatum(funcid),
863 if (!HeapTupleIsValid(tp))
864 elog(ERROR, "cache lookup failed for function %u", funcid);
866 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
873 * Given procedure id, return the function's provolatile flag.
876 func_volatile(Oid funcid)
881 tp = SearchSysCache(PROCOID,
882 ObjectIdGetDatum(funcid),
884 if (!HeapTupleIsValid(tp))
885 elog(ERROR, "cache lookup failed for function %u", funcid);
887 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
892 /* ---------- RELATION CACHE ---------- */
896 * Given name and namespace of a relation, look up the OID.
898 * Returns InvalidOid if there is no such relation.
901 get_relname_relid(const char *relname, Oid relnamespace)
903 return GetSysCacheOid(RELNAMENSP,
904 PointerGetDatum(relname),
905 ObjectIdGetDatum(relnamespace),
910 * get_system_catalog_relid
911 * Get the OID of a system catalog identified by name.
914 get_system_catalog_relid(const char *catname)
918 relid = GetSysCacheOid(RELNAMENSP,
919 PointerGetDatum(catname),
920 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
922 if (!OidIsValid(relid))
923 elog(ERROR, "cache lookup failed for system relation %s", catname);
932 * Returns the number of attributes for a given relation.
935 get_relnatts(Oid relid)
939 tp = SearchSysCache(RELOID,
940 ObjectIdGetDatum(relid),
942 if (HeapTupleIsValid(tp))
944 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
947 result = reltup->relnatts;
952 return InvalidAttrNumber;
958 * Returns the name of a given relation.
960 * Returns a palloc'd copy of the string, or NULL if no such relation.
962 * NOTE: since relation name is not unique, be wary of code that uses this
963 * for anything except preparing error messages.
966 get_rel_name(Oid relid)
970 tp = SearchSysCache(RELOID,
971 ObjectIdGetDatum(relid),
973 if (HeapTupleIsValid(tp))
975 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
978 result = pstrdup(NameStr(reltup->relname));
989 * Returns the pg_namespace OID associated with a given relation.
992 get_rel_namespace(Oid relid)
996 tp = SearchSysCache(RELOID,
997 ObjectIdGetDatum(relid),
999 if (HeapTupleIsValid(tp))
1001 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1004 result = reltup->relnamespace;
1005 ReleaseSysCache(tp);
1015 * Returns the pg_type OID associated with a given relation.
1017 * Note: not all pg_class entries have associated pg_type OIDs; so be
1018 * careful to check for InvalidOid result.
1021 get_rel_type_id(Oid relid)
1025 tp = SearchSysCache(RELOID,
1026 ObjectIdGetDatum(relid),
1028 if (HeapTupleIsValid(tp))
1030 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1033 result = reltup->reltype;
1034 ReleaseSysCache(tp);
1044 * Returns the relkind associated with a given relation.
1047 get_rel_relkind(Oid relid)
1051 tp = SearchSysCache(RELOID,
1052 ObjectIdGetDatum(relid),
1054 if (HeapTupleIsValid(tp))
1056 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1059 result = reltup->relkind;
1060 ReleaseSysCache(tp);
1068 /* ---------- TYPE CACHE ---------- */
1073 * Given the type OID, determine whether the type is defined
1074 * (if not, it's only a shell).
1077 get_typisdefined(Oid typid)
1081 tp = SearchSysCache(TYPEOID,
1082 ObjectIdGetDatum(typid),
1084 if (HeapTupleIsValid(tp))
1086 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1089 result = typtup->typisdefined;
1090 ReleaseSysCache(tp);
1100 * Given the type OID, return the length of the type.
1103 get_typlen(Oid typid)
1107 tp = SearchSysCache(TYPEOID,
1108 ObjectIdGetDatum(typid),
1110 if (HeapTupleIsValid(tp))
1112 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1115 result = typtup->typlen;
1116 ReleaseSysCache(tp);
1126 * Given the type OID, determine whether the type is returned by value or
1127 * not. Returns true if by value, false if by reference.
1130 get_typbyval(Oid typid)
1134 tp = SearchSysCache(TYPEOID,
1135 ObjectIdGetDatum(typid),
1137 if (HeapTupleIsValid(tp))
1139 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1142 result = typtup->typbyval;
1143 ReleaseSysCache(tp);
1153 * A two-fer: given the type OID, return both typlen and typbyval.
1155 * Since both pieces of info are needed to know how to copy a Datum,
1156 * many places need both. Might as well get them with one cache lookup
1157 * instead of two. Also, this routine raises an error instead of
1158 * returning a bogus value when given a bad type OID.
1161 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1164 Form_pg_type typtup;
1166 tp = SearchSysCache(TYPEOID,
1167 ObjectIdGetDatum(typid),
1169 if (!HeapTupleIsValid(tp))
1170 elog(ERROR, "cache lookup failed for type %u", typid);
1171 typtup = (Form_pg_type) GETSTRUCT(tp);
1172 *typlen = typtup->typlen;
1173 *typbyval = typtup->typbyval;
1174 ReleaseSysCache(tp);
1178 * get_typlenbyvalalign
1180 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1183 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1187 Form_pg_type typtup;
1189 tp = SearchSysCache(TYPEOID,
1190 ObjectIdGetDatum(typid),
1192 if (!HeapTupleIsValid(tp))
1193 elog(ERROR, "cache lookup failed for type %u", typid);
1194 typtup = (Form_pg_type) GETSTRUCT(tp);
1195 *typlen = typtup->typlen;
1196 *typbyval = typtup->typbyval;
1197 *typalign = typtup->typalign;
1198 ReleaseSysCache(tp);
1203 * Given a pg_type row, select the type OID to pass to I/O functions
1205 * Formerly, all I/O functions were passed pg_type.typelem as their second
1206 * parameter, but we now have a more complex rule about what to pass.
1207 * This knowledge is intended to be centralized here --- direct references
1208 * to typelem elsewhere in the code are wrong, if they are associated with
1209 * I/O calls and not with actual subscripting operations! (But see
1210 * bootstrap.c, which can't conveniently use this routine.)
1213 getTypeIOParam(HeapTuple typeTuple)
1215 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1218 * Composite types get their own OID as parameter; array types get
1219 * their typelem as parameter; everybody else gets zero.
1221 if (typeStruct->typtype == 'c')
1222 return HeapTupleGetOid(typeTuple);
1224 return typeStruct->typelem;
1230 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1231 * typdelim, typioparam, and IO function OID. The IO function
1232 * returned is controlled by IOFuncSelector
1235 get_type_io_data(Oid typid,
1236 IOFuncSelector which_func,
1244 HeapTuple typeTuple;
1245 Form_pg_type typeStruct;
1247 typeTuple = SearchSysCache(TYPEOID,
1248 ObjectIdGetDatum(typid),
1250 if (!HeapTupleIsValid(typeTuple))
1251 elog(ERROR, "cache lookup failed for type %u", typid);
1252 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1254 *typlen = typeStruct->typlen;
1255 *typbyval = typeStruct->typbyval;
1256 *typalign = typeStruct->typalign;
1257 *typdelim = typeStruct->typdelim;
1258 *typioparam = getTypeIOParam(typeTuple);
1262 *func = typeStruct->typinput;
1265 *func = typeStruct->typoutput;
1267 case IOFunc_receive:
1268 *func = typeStruct->typreceive;
1271 *func = typeStruct->typsend;
1274 ReleaseSysCache(typeTuple);
1279 get_typalign(Oid typid)
1283 tp = SearchSysCache(TYPEOID,
1284 ObjectIdGetDatum(typid),
1286 if (HeapTupleIsValid(tp))
1288 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1291 result = typtup->typalign;
1292 ReleaseSysCache(tp);
1301 get_typstorage(Oid typid)
1305 tp = SearchSysCache(TYPEOID,
1306 ObjectIdGetDatum(typid),
1308 if (HeapTupleIsValid(tp))
1310 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1313 result = typtup->typstorage;
1314 ReleaseSysCache(tp);
1324 * Given the type OID, return the typtypmod field (domain's typmod
1328 get_typtypmod(Oid typid)
1332 tp = SearchSysCache(TYPEOID,
1333 ObjectIdGetDatum(typid),
1335 if (HeapTupleIsValid(tp))
1337 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1340 result = typtup->typtypmod;
1341 ReleaseSysCache(tp);
1350 * Given a type OID, return the type's default value, if any.
1352 * The result is a palloc'd expression node tree, or NULL if there
1353 * is no defined default for the datatype.
1355 * NB: caller should be prepared to coerce result to correct datatype;
1356 * the returned expression tree might produce something of the wrong type.
1359 get_typdefault(Oid typid)
1361 HeapTuple typeTuple;
1367 typeTuple = SearchSysCache(TYPEOID,
1368 ObjectIdGetDatum(typid),
1370 if (!HeapTupleIsValid(typeTuple))
1371 elog(ERROR, "cache lookup failed for type %u", typid);
1372 type = (Form_pg_type) GETSTRUCT(typeTuple);
1375 * typdefault and typdefaultbin are potentially null, so don't try to
1376 * access 'em as struct fields. Must do it the hard way with
1379 datum = SysCacheGetAttr(TYPEOID,
1381 Anum_pg_type_typdefaultbin,
1386 /* We have an expression default */
1387 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1392 /* Perhaps we have a plain literal default */
1393 datum = SysCacheGetAttr(TYPEOID,
1395 Anum_pg_type_typdefault,
1400 char *strDefaultVal;
1402 /* Convert text datum to C string */
1403 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1405 /* Convert C string to a value of the given type */
1406 datum = OidFunctionCall3(type->typinput,
1407 CStringGetDatum(strDefaultVal),
1408 ObjectIdGetDatum(getTypeIOParam(typeTuple)),
1410 /* Build a Const node containing the value */
1411 expr = (Node *) makeConst(typid,
1416 pfree(strDefaultVal);
1425 ReleaseSysCache(typeTuple);
1432 * If the given type is a domain, return its base type;
1433 * otherwise return the type's own OID.
1436 getBaseType(Oid typid)
1439 * We loop to find the bottom base type in a stack of domains.
1444 Form_pg_type typTup;
1446 tup = SearchSysCache(TYPEOID,
1447 ObjectIdGetDatum(typid),
1449 if (!HeapTupleIsValid(tup))
1450 elog(ERROR, "cache lookup failed for type %u", typid);
1451 typTup = (Form_pg_type) GETSTRUCT(tup);
1452 if (typTup->typtype != 'd')
1454 /* Not a domain, so done */
1455 ReleaseSysCache(tup);
1459 typid = typTup->typbasetype;
1460 ReleaseSysCache(tup);
1469 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1470 * estimate the average width of values of the type. This is used by
1471 * the planner, which doesn't require absolutely correct results;
1472 * it's OK (and expected) to guess if we don't know for sure.
1475 get_typavgwidth(Oid typid, int32 typmod)
1477 int typlen = get_typlen(typid);
1481 * Easy if it's a fixed-width type
1487 * type_maximum_size knows the encoding of typmod for some datatypes;
1488 * don't duplicate that knowledge here.
1490 maxwidth = type_maximum_size(typid, typmod);
1494 * For BPCHAR, the max width is also the only width. Otherwise we
1495 * need to guess about the typical data width given the max. A
1496 * sliding scale for percentage of max width seems reasonable.
1498 if (typid == BPCHAROID)
1501 return maxwidth; /* assume full width */
1502 if (maxwidth < 1000)
1503 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1506 * Beyond 1000, assume we're looking at something like
1507 * "varchar(10000)" where the limit isn't actually reached often,
1508 * and use a fixed estimate.
1510 return 32 + (1000 - 32) / 2;
1514 * Ooops, we have no idea ... wild guess time.
1522 * Given the type OID, find if it is a basic type, a complex type, etc.
1523 * It returns the null char if the cache lookup fails...
1526 get_typtype(Oid typid)
1530 tp = SearchSysCache(TYPEOID,
1531 ObjectIdGetDatum(typid),
1533 if (HeapTupleIsValid(tp))
1535 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1538 result = typtup->typtype;
1539 ReleaseSysCache(tp);
1549 * Given the type OID, get the typrelid (InvalidOid if not a complex
1553 get_typ_typrelid(Oid typid)
1557 tp = SearchSysCache(TYPEOID,
1558 ObjectIdGetDatum(typid),
1560 if (HeapTupleIsValid(tp))
1562 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1565 result = typtup->typrelid;
1566 ReleaseSysCache(tp);
1576 * Given the type OID, get the typelem (InvalidOid if not an array type).
1578 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
1579 * returned if the input is a fixed-length array type.
1582 get_element_type(Oid typid)
1586 tp = SearchSysCache(TYPEOID,
1587 ObjectIdGetDatum(typid),
1589 if (HeapTupleIsValid(tp))
1591 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1594 if (typtup->typlen == -1)
1595 result = typtup->typelem;
1597 result = InvalidOid;
1598 ReleaseSysCache(tp);
1608 * Given the type OID, get the corresponding array type.
1609 * Returns InvalidOid if no array type can be found.
1611 * NB: this only considers varlena arrays to be true arrays.
1614 get_array_type(Oid typid)
1618 tp = SearchSysCache(TYPEOID,
1619 ObjectIdGetDatum(typid),
1621 if (HeapTupleIsValid(tp))
1623 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1624 char *array_typename;
1627 array_typename = makeArrayTypeName(NameStr(typtup->typname));
1628 namespaceId = typtup->typnamespace;
1629 ReleaseSysCache(tp);
1631 tp = SearchSysCache(TYPENAMENSP,
1632 PointerGetDatum(array_typename),
1633 ObjectIdGetDatum(namespaceId),
1636 pfree(array_typename);
1638 if (HeapTupleIsValid(tp))
1642 typtup = (Form_pg_type) GETSTRUCT(tp);
1643 if (typtup->typlen == -1 && typtup->typelem == typid)
1644 result = HeapTupleGetOid(tp);
1646 result = InvalidOid;
1647 ReleaseSysCache(tp);
1657 * Get info needed for converting values of a type to internal form
1660 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
1662 HeapTuple typeTuple;
1665 typeTuple = SearchSysCache(TYPEOID,
1666 ObjectIdGetDatum(type),
1668 if (!HeapTupleIsValid(typeTuple))
1669 elog(ERROR, "cache lookup failed for type %u", type);
1670 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1672 if (!pt->typisdefined)
1674 (errcode(ERRCODE_UNDEFINED_OBJECT),
1675 errmsg("type %s is only a shell",
1676 format_type_be(type))));
1677 if (!OidIsValid(pt->typinput))
1679 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1680 errmsg("no input function available for type %s",
1681 format_type_be(type))));
1683 *typInput = pt->typinput;
1684 *typIOParam = getTypeIOParam(typeTuple);
1686 ReleaseSysCache(typeTuple);
1692 * Get info needed for printing values of a type
1695 getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typIOParam,
1698 HeapTuple typeTuple;
1701 typeTuple = SearchSysCache(TYPEOID,
1702 ObjectIdGetDatum(type),
1704 if (!HeapTupleIsValid(typeTuple))
1705 elog(ERROR, "cache lookup failed for type %u", type);
1706 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1708 if (!pt->typisdefined)
1710 (errcode(ERRCODE_UNDEFINED_OBJECT),
1711 errmsg("type %s is only a shell",
1712 format_type_be(type))));
1713 if (!OidIsValid(pt->typoutput))
1715 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1716 errmsg("no output function available for type %s",
1717 format_type_be(type))));
1719 *typOutput = pt->typoutput;
1720 *typIOParam = getTypeIOParam(typeTuple);
1721 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1723 ReleaseSysCache(typeTuple);
1727 * getTypeBinaryInputInfo
1729 * Get info needed for binary input of values of a type
1732 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
1734 HeapTuple typeTuple;
1737 typeTuple = SearchSysCache(TYPEOID,
1738 ObjectIdGetDatum(type),
1740 if (!HeapTupleIsValid(typeTuple))
1741 elog(ERROR, "cache lookup failed for type %u", type);
1742 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1744 if (!pt->typisdefined)
1746 (errcode(ERRCODE_UNDEFINED_OBJECT),
1747 errmsg("type %s is only a shell",
1748 format_type_be(type))));
1749 if (!OidIsValid(pt->typreceive))
1751 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1752 errmsg("no binary input function available for type %s",
1753 format_type_be(type))));
1755 *typReceive = pt->typreceive;
1756 *typIOParam = getTypeIOParam(typeTuple);
1758 ReleaseSysCache(typeTuple);
1762 * getTypeBinaryOutputInfo
1764 * Get info needed for binary output of values of a type
1767 getTypeBinaryOutputInfo(Oid type, Oid *typSend, Oid *typIOParam,
1770 HeapTuple typeTuple;
1773 typeTuple = SearchSysCache(TYPEOID,
1774 ObjectIdGetDatum(type),
1776 if (!HeapTupleIsValid(typeTuple))
1777 elog(ERROR, "cache lookup failed for type %u", type);
1778 pt = (Form_pg_type) GETSTRUCT(typeTuple);
1780 if (!pt->typisdefined)
1782 (errcode(ERRCODE_UNDEFINED_OBJECT),
1783 errmsg("type %s is only a shell",
1784 format_type_be(type))));
1785 if (!OidIsValid(pt->typsend))
1787 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1788 errmsg("no binary output function available for type %s",
1789 format_type_be(type))));
1791 *typSend = pt->typsend;
1792 *typIOParam = getTypeIOParam(typeTuple);
1793 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1795 ReleaseSysCache(typeTuple);
1799 /* ---------- STATISTICS CACHE ---------- */
1804 * Given the table and attribute number of a column, get the average
1805 * width of entries in the column. Return zero if no data available.
1808 get_attavgwidth(Oid relid, AttrNumber attnum)
1812 tp = SearchSysCache(STATRELATT,
1813 ObjectIdGetDatum(relid),
1814 Int16GetDatum(attnum),
1816 if (HeapTupleIsValid(tp))
1818 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1820 ReleaseSysCache(tp);
1830 * Extract the contents of a "slot" of a pg_statistic tuple.
1831 * Returns TRUE if requested slot type was found, else FALSE.
1833 * Unlike other routines in this file, this takes a pointer to an
1834 * already-looked-up tuple in the pg_statistic cache. We do this since
1835 * most callers will want to extract more than one value from the cache
1836 * entry, and we don't want to repeat the cache lookup unnecessarily.
1838 * statstuple: pg_statistics tuple to be examined.
1839 * atttype: type OID of attribute.
1840 * atttypmod: typmod of attribute.
1841 * reqkind: STAKIND code for desired statistics slot kind.
1842 * reqop: STAOP value wanted, or InvalidOid if don't care.
1843 * values, nvalues: if not NULL, the slot's stavalues are extracted.
1844 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1846 * If assigned, values and numbers are set to point to palloc'd arrays.
1847 * If the attribute type is pass-by-reference, the values referenced by
1848 * the values array are themselves palloc'd. The palloc'd stuff can be
1849 * freed by calling free_attstatsslot.
1852 get_attstatsslot(HeapTuple statstuple,
1853 Oid atttype, int32 atttypmod,
1854 int reqkind, Oid reqop,
1855 Datum **values, int *nvalues,
1856 float4 **numbers, int *nnumbers)
1858 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1863 ArrayType *statarray;
1865 HeapTuple typeTuple;
1866 Form_pg_type typeForm;
1868 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1870 if ((&stats->stakind1)[i] == reqkind &&
1871 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1874 if (i >= STATISTIC_NUM_SLOTS)
1875 return false; /* not there */
1879 val = SysCacheGetAttr(STATRELATT, statstuple,
1880 Anum_pg_statistic_stavalues1 + i,
1883 elog(ERROR, "stavalues is null");
1884 statarray = DatumGetArrayTypeP(val);
1886 /* Need to get info about the array element type */
1887 typeTuple = SearchSysCache(TYPEOID,
1888 ObjectIdGetDatum(atttype),
1890 if (!HeapTupleIsValid(typeTuple))
1891 elog(ERROR, "cache lookup failed for type %u", atttype);
1892 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1894 /* Deconstruct array into Datum elements */
1895 deconstruct_array(statarray,
1903 * If the element type is pass-by-reference, we now have a bunch
1904 * of Datums that are pointers into the syscache value. Copy them
1905 * to avoid problems if syscache decides to drop the entry.
1907 if (!typeForm->typbyval)
1909 for (j = 0; j < *nvalues; j++)
1911 (*values)[j] = datumCopy((*values)[j],
1917 ReleaseSysCache(typeTuple);
1920 * Free statarray if it's a detoasted copy.
1922 if ((Pointer) statarray != DatumGetPointer(val))
1928 val = SysCacheGetAttr(STATRELATT, statstuple,
1929 Anum_pg_statistic_stanumbers1 + i,
1932 elog(ERROR, "stanumbers is null");
1933 statarray = DatumGetArrayTypeP(val);
1936 * We expect the array to be a 1-D float4 array; verify that. We
1937 * don't need to use deconstruct_array() since the array data is
1938 * just going to look like a C array of float4 values.
1940 narrayelem = ARR_DIMS(statarray)[0];
1941 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1942 ARR_ELEMTYPE(statarray) != FLOAT4OID)
1943 elog(ERROR, "stanumbers is not a 1-D float4 array");
1944 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1945 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1946 *nnumbers = narrayelem;
1949 * Free statarray if it's a detoasted copy.
1951 if ((Pointer) statarray != DatumGetPointer(val))
1959 free_attstatsslot(Oid atttype,
1960 Datum *values, int nvalues,
1961 float4 *numbers, int nnumbers)
1965 if (!get_typbyval(atttype))
1969 for (i = 0; i < nvalues; i++)
1970 pfree(DatumGetPointer(values[i]));
1978 /* ---------- PG_NAMESPACE CACHE ---------- */
1981 * get_namespace_name
1982 * Returns the name of a given namespace
1984 * Returns a palloc'd copy of the string, or NULL if no such namespace.
1987 get_namespace_name(Oid nspid)
1991 tp = SearchSysCache(NAMESPACEOID,
1992 ObjectIdGetDatum(nspid),
1994 if (HeapTupleIsValid(tp))
1996 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
1999 result = pstrdup(NameStr(nsptup->nspname));
2000 ReleaseSysCache(tp);
2007 /* ---------- PG_SHADOW CACHE ---------- */
2012 * Given a user name, look up the user's sysid.
2013 * Raises an error if no such user (rather than returning zero,
2014 * which might possibly be a valid usesysid).
2016 * Note: the type of usesysid is currently int4, but may change to Oid
2017 * someday. It'd be reasonable to return zero on failure if we were
2021 get_usesysid(const char *username)
2026 userTup = SearchSysCache(SHADOWNAME,
2027 PointerGetDatum(username),
2029 if (!HeapTupleIsValid(userTup))
2031 (errcode(ERRCODE_UNDEFINED_OBJECT),
2032 errmsg("user \"%s\" does not exist", username)));
2034 userId = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
2036 ReleaseSysCache(userTup);
2044 * Given a group name, look up the group's sysid.
2045 * Raises an error if no such group (rather than returning zero,
2046 * which might possibly be a valid grosysid).
2050 get_grosysid(char *groname)
2055 groupTup = SearchSysCache(GRONAME,
2056 PointerGetDatum(groname),
2058 if (!HeapTupleIsValid(groupTup))
2060 (errcode(ERRCODE_UNDEFINED_OBJECT),
2061 errmsg("group \"%s\" does not exist", groname)));
2063 groupId = ((Form_pg_group) GETSTRUCT(groupTup))->grosysid;
2065 ReleaseSysCache(groupTup);