1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2007, 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.145 2007/01/21 00:57:15 tgl Exp $
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
18 #include "access/hash.h"
19 #include "access/nbtree.h"
20 #include "bootstrap/bootstrap.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 "miscadmin.h"
30 #include "nodes/makefuncs.h"
31 #include "utils/array.h"
32 #include "utils/builtins.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 family 'opfamily'.
46 op_in_opfamily(Oid opno, Oid opfamily)
48 return SearchSysCacheExists(AMOPOPID,
49 ObjectIdGetDatum(opno),
50 ObjectIdGetDatum(opfamily),
55 * get_op_opfamily_strategy
57 * Get the operator's strategy number within the specified opfamily,
58 * or 0 if it's not a member of the opfamily.
61 get_op_opfamily_strategy(Oid opno, Oid opfamily)
64 Form_pg_amop amop_tup;
67 tp = SearchSysCache(AMOPOPID,
68 ObjectIdGetDatum(opno),
69 ObjectIdGetDatum(opfamily),
71 if (!HeapTupleIsValid(tp))
73 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
74 result = amop_tup->amopstrategy;
80 * get_op_opfamily_properties
82 * Get the operator's strategy number, input types, and recheck (lossy)
83 * flag within the specified opfamily.
85 * Caller should already have verified that opno is a member of opfamily,
86 * therefore we raise an error if the tuple is not found.
89 get_op_opfamily_properties(Oid opno, Oid opfamily,
96 Form_pg_amop amop_tup;
98 tp = SearchSysCache(AMOPOPID,
99 ObjectIdGetDatum(opno),
100 ObjectIdGetDatum(opfamily),
102 if (!HeapTupleIsValid(tp))
103 elog(ERROR, "operator %u is not a member of opfamily %u",
105 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
106 *strategy = amop_tup->amopstrategy;
107 *lefttype = amop_tup->amoplefttype;
108 *righttype = amop_tup->amoprighttype;
109 *recheck = amop_tup->amopreqcheck;
114 * get_opfamily_member
115 * Get the OID of the operator that implements the specified strategy
116 * with the specified datatypes for the specified opfamily.
118 * Returns InvalidOid if there is no pg_amop entry for the given keys.
121 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
125 Form_pg_amop amop_tup;
128 tp = SearchSysCache(AMOPSTRATEGY,
129 ObjectIdGetDatum(opfamily),
130 ObjectIdGetDatum(lefttype),
131 ObjectIdGetDatum(righttype),
132 Int16GetDatum(strategy));
133 if (!HeapTupleIsValid(tp))
135 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
136 result = amop_tup->amopopr;
142 * get_ordering_op_properties
143 * Given the OID of an ordering operator (a btree "<" or ">" operator),
144 * determine its opfamily, its declared input datatype, and its
145 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
147 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
148 * (This indicates that the operator is not a valid ordering operator.)
150 * Note: the operator could be registered in multiple families, for example
151 * if someone were to build a "reverse sort" opfamily. This would result in
152 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
153 * or NULLS LAST, as well as inefficient planning due to failure to match up
154 * pathkeys that should be the same. So we want a determinate result here.
155 * Because of the way the syscache search works, we'll use the interpretation
156 * associated with the opfamily with smallest OID, which is probably
157 * determinate enough. Since there is no longer any particularly good reason
158 * to build reverse-sort opfamilies, it doesn't seem worth expending any
159 * additional effort on ensuring consistency.
162 get_ordering_op_properties(Oid opno,
163 Oid *opfamily, Oid *opcintype, int16 *strategy)
169 /* ensure outputs are initialized on failure */
170 *opfamily = InvalidOid;
171 *opcintype = InvalidOid;
175 * Search pg_amop to see if the target operator is registered as the "<"
176 * or ">" operator of any btree opfamily.
178 catlist = SearchSysCacheList(AMOPOPID, 1,
179 ObjectIdGetDatum(opno),
182 for (i = 0; i < catlist->n_members; i++)
184 HeapTuple tuple = &catlist->members[i]->tuple;
185 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
188 if (aform->amopmethod != BTREE_AM_OID)
191 if (aform->amopstrategy == BTLessStrategyNumber ||
192 aform->amopstrategy == BTGreaterStrategyNumber)
194 /* Found it ... should have consistent input types */
195 if (aform->amoplefttype == aform->amoprighttype)
197 /* Found a suitable opfamily, return info */
198 *opfamily = aform->amopfamily;
199 *opcintype = aform->amoplefttype;
200 *strategy = aform->amopstrategy;
207 ReleaseSysCacheList(catlist);
213 * get_compare_function_for_ordering_op
214 * Get the OID of the datatype-specific btree comparison function
215 * associated with an ordering operator (a "<" or ">" operator).
217 * *cmpfunc receives the comparison function OID.
218 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
219 * (indicating the comparison result must be negated before use).
221 * Returns TRUE if successful, FALSE if no btree function can be found.
222 * (This indicates that the operator is not a valid ordering operator.)
225 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
231 /* Find the operator in pg_amop */
232 if (get_ordering_op_properties(opno,
233 &opfamily, &opcintype, &strategy))
235 /* Found a suitable opfamily, get matching support function */
236 *cmpfunc = get_opfamily_proc(opfamily,
240 if (!OidIsValid(*cmpfunc)) /* should not happen */
241 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
242 BTORDER_PROC, opcintype, opcintype, opfamily);
243 *reverse = (strategy == BTGreaterStrategyNumber);
247 /* ensure outputs are set on failure */
248 *cmpfunc = InvalidOid;
254 * get_equality_op_for_ordering_op
255 * Get the OID of the datatype-specific btree equality operator
256 * associated with an ordering operator (a "<" or ">" operator).
258 * Returns InvalidOid if no matching equality operator can be found.
259 * (This indicates that the operator is not a valid ordering operator.)
262 get_equality_op_for_ordering_op(Oid opno)
264 Oid result = InvalidOid;
269 /* Find the operator in pg_amop */
270 if (get_ordering_op_properties(opno,
271 &opfamily, &opcintype, &strategy))
273 /* Found a suitable opfamily, get matching equality operator */
274 result = get_opfamily_member(opfamily,
277 BTEqualStrategyNumber);
284 * get_ordering_op_for_equality_op
285 * Get the OID of a datatype-specific btree ordering operator
286 * associated with an equality operator. (If there are multiple
287 * possibilities, assume any one will do.)
289 * This function is used when we have to sort data before unique-ifying,
290 * and don't much care which sorting op is used as long as it's compatible
291 * with the intended equality operator. Since we need a sorting operator,
292 * it should be single-data-type even if the given operator is cross-type.
293 * The caller specifies whether to find an op for the LHS or RHS data type.
295 * Returns InvalidOid if no matching ordering operator can be found.
298 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
300 Oid result = InvalidOid;
305 * Search pg_amop to see if the target operator is registered as the "="
306 * operator of any btree opfamily.
308 catlist = SearchSysCacheList(AMOPOPID, 1,
309 ObjectIdGetDatum(opno),
312 for (i = 0; i < catlist->n_members; i++)
314 HeapTuple tuple = &catlist->members[i]->tuple;
315 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
318 if (aform->amopmethod != BTREE_AM_OID)
321 if (aform->amopstrategy == BTEqualStrategyNumber)
323 /* Found a suitable opfamily, get matching ordering operator */
326 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
327 result = get_opfamily_member(aform->amopfamily,
329 BTLessStrategyNumber);
330 if (OidIsValid(result))
332 /* failure probably shouldn't happen, but keep looking if so */
336 ReleaseSysCacheList(catlist);
342 * get_mergejoin_opfamilies
343 * Given a putatively mergejoinable operator, return a list of the OIDs
344 * of the btree opfamilies in which it represents equality.
346 * It is possible (though at present unusual) for an operator to be equality
347 * in more than one opfamily, hence the result is a list. This also lets us
348 * return NIL if the operator is not found in any opfamilies.
350 * The planner currently uses simple equal() tests to compare the lists
351 * returned by this function, which makes the list order relevant, though
352 * strictly speaking it should not be. Because of the way syscache list
353 * searches are handled, in normal operation the result will be sorted by OID
354 * so everything works fine. If running with system index usage disabled,
355 * the result ordering is unspecified and hence the planner might fail to
356 * recognize optimization opportunities ... but that's hardly a scenario in
357 * which performance is good anyway, so there's no point in expending code
358 * or cycles here to guarantee the ordering in that case.
361 get_mergejoin_opfamilies(Oid opno)
368 * Search pg_amop to see if the target operator is registered as the "="
369 * operator of any btree opfamily.
371 catlist = SearchSysCacheList(AMOPOPID, 1,
372 ObjectIdGetDatum(opno),
375 for (i = 0; i < catlist->n_members; i++)
377 HeapTuple tuple = &catlist->members[i]->tuple;
378 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
380 /* must be btree equality */
381 if (aform->amopmethod == BTREE_AM_OID &&
382 aform->amopstrategy == BTEqualStrategyNumber)
383 result = lappend_oid(result, aform->amopfamily);
386 ReleaseSysCacheList(catlist);
392 * get_compatible_hash_operator
393 * Get the OID of a hash equality operator compatible with the given
394 * operator, but operating on its LHS or RHS datatype as specified.
396 * If the given operator is not cross-type, the result should be the same
397 * operator, but in cross-type situations it is different.
399 * Returns InvalidOid if no compatible operator can be found. (This indicates
400 * that the operator should not have been marked oprcanhash.)
403 get_compatible_hash_operator(Oid opno, bool use_lhs_type)
405 Oid result = InvalidOid;
410 * Search pg_amop to see if the target operator is registered as the "="
411 * operator of any hash opfamily. If the operator is registered in
412 * multiple opfamilies, assume we can use any one.
414 catlist = SearchSysCacheList(AMOPOPID, 1,
415 ObjectIdGetDatum(opno),
418 for (i = 0; i < catlist->n_members; i++)
420 HeapTuple tuple = &catlist->members[i]->tuple;
421 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
423 if (aform->amopmethod == HASH_AM_OID &&
424 aform->amopstrategy == HTEqualStrategyNumber)
426 /* Found a suitable opfamily, get matching single-type operator */
429 /* No extra lookup needed if given operator is single-type */
430 if (aform->amoplefttype == aform->amoprighttype)
435 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
436 result = get_opfamily_member(aform->amopfamily,
438 HTEqualStrategyNumber);
439 if (OidIsValid(result))
441 /* failure probably shouldn't happen, but keep looking if so */
445 ReleaseSysCacheList(catlist);
451 * get_op_hash_function
452 * Get the OID of the datatype-specific hash function associated with
453 * a hashable equality operator.
455 * XXX API needs to be generalized for the case of different left and right
458 * Returns InvalidOid if no hash function can be found. (This indicates
459 * that the operator should not have been marked oprcanhash.)
462 get_op_hash_function(Oid opno)
464 Oid result = InvalidOid;
469 * Search pg_amop to see if the target operator is registered as the "="
470 * operator of any hash opfamily. If the operator is registered in
471 * multiple opfamilies, assume we can use the associated hash function from
474 catlist = SearchSysCacheList(AMOPOPID, 1,
475 ObjectIdGetDatum(opno),
478 for (i = 0; i < catlist->n_members; i++)
480 HeapTuple tuple = &catlist->members[i]->tuple;
481 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
483 if (aform->amopmethod == HASH_AM_OID &&
484 aform->amopstrategy == HTEqualStrategyNumber)
486 /* Found a suitable opfamily, get matching hash support function */
487 result = get_opfamily_proc(aform->amopfamily,
489 aform->amoprighttype,
495 ReleaseSysCacheList(catlist);
501 * get_op_btree_interpretation
502 * Given an operator's OID, find out which btree opfamilies it belongs to,
503 * and what strategy number it has within each one. The results are
504 * returned as an OID list and a parallel integer list.
506 * In addition to the normal btree operators, we consider a <> operator to be
507 * a "member" of an opfamily if its negator is an equality operator of the
508 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
511 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
521 * Find all the pg_amop entries containing the operator.
523 catlist = SearchSysCacheList(AMOPOPID, 1,
524 ObjectIdGetDatum(opno),
528 * If we can't find any opfamily containing the op, perhaps it is a <>
529 * operator. See if it has a negator that is in an opfamily.
532 if (catlist->n_members == 0)
534 Oid op_negator = get_negator(opno);
536 if (OidIsValid(op_negator))
539 ReleaseSysCacheList(catlist);
540 catlist = SearchSysCacheList(AMOPOPID, 1,
541 ObjectIdGetDatum(op_negator),
546 /* Now search the opfamilies */
547 for (i = 0; i < catlist->n_members; i++)
549 HeapTuple op_tuple = &catlist->members[i]->tuple;
550 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
552 StrategyNumber op_strategy;
555 if (op_form->amopmethod != BTREE_AM_OID)
558 /* Get the operator's btree strategy number */
559 opfamily_id = op_form->amopfamily;
560 op_strategy = (StrategyNumber) op_form->amopstrategy;
561 Assert(op_strategy >= 1 && op_strategy <= 5);
565 /* Only consider negators that are = */
566 if (op_strategy != BTEqualStrategyNumber)
568 op_strategy = ROWCOMPARE_NE;
571 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
572 *opstrats = lappend_int(*opstrats, op_strategy);
575 ReleaseSysCacheList(catlist);
579 * ops_in_same_btree_opfamily
580 * Return TRUE if there exists a btree opfamily containing both operators.
581 * (This implies that they have compatible notions of equality.)
584 ops_in_same_btree_opfamily(Oid opno1, Oid opno2)
591 * We search through all the pg_amop entries for opno1.
593 catlist = SearchSysCacheList(AMOPOPID, 1,
594 ObjectIdGetDatum(opno1),
596 for (i = 0; i < catlist->n_members; i++)
598 HeapTuple op_tuple = &catlist->members[i]->tuple;
599 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
602 if (op_form->amopmethod != BTREE_AM_OID)
605 if (op_in_opfamily(opno2, op_form->amopfamily))
612 ReleaseSysCacheList(catlist);
618 /* ---------- AMPROC CACHES ---------- */
622 * Get the OID of the specified support function
623 * for the specified opfamily and datatypes.
625 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
628 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
631 Form_pg_amproc amproc_tup;
634 tp = SearchSysCache(AMPROCNUM,
635 ObjectIdGetDatum(opfamily),
636 ObjectIdGetDatum(lefttype),
637 ObjectIdGetDatum(righttype),
638 Int16GetDatum(procnum));
639 if (!HeapTupleIsValid(tp))
641 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
642 result = amproc_tup->amproc;
648 /* ---------- ATTRIBUTE CACHES ---------- */
652 * Given the relation id and the attribute number,
653 * return the "attname" field from the attribute relation.
655 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
658 get_attname(Oid relid, AttrNumber attnum)
662 tp = SearchSysCache(ATTNUM,
663 ObjectIdGetDatum(relid),
664 Int16GetDatum(attnum),
666 if (HeapTupleIsValid(tp))
668 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
671 result = pstrdup(NameStr(att_tup->attname));
680 * get_relid_attribute_name
682 * Same as above routine get_attname(), except that error
683 * is handled by elog() instead of returning NULL.
686 get_relid_attribute_name(Oid relid, AttrNumber attnum)
690 attname = get_attname(relid, attnum);
692 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
700 * Given the relation id and the attribute name,
701 * return the "attnum" field from the attribute relation.
703 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
706 get_attnum(Oid relid, const char *attname)
710 tp = SearchSysCacheAttName(relid, attname);
711 if (HeapTupleIsValid(tp))
713 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
716 result = att_tup->attnum;
721 return InvalidAttrNumber;
727 * Given the relation OID and the attribute number with the relation,
728 * return the attribute type OID.
731 get_atttype(Oid relid, AttrNumber attnum)
735 tp = SearchSysCache(ATTNUM,
736 ObjectIdGetDatum(relid),
737 Int16GetDatum(attnum),
739 if (HeapTupleIsValid(tp))
741 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
744 result = att_tup->atttypid;
755 * Given the relation id and the attribute number,
756 * return the "atttypmod" field from the attribute relation.
759 get_atttypmod(Oid relid, AttrNumber attnum)
763 tp = SearchSysCache(ATTNUM,
764 ObjectIdGetDatum(relid),
765 Int16GetDatum(attnum),
767 if (HeapTupleIsValid(tp))
769 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
772 result = att_tup->atttypmod;
783 * A two-fer: given the relation id and the attribute number,
784 * fetch both type OID and atttypmod in a single cache lookup.
786 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
787 * raises an error if it can't obtain the information.
790 get_atttypetypmod(Oid relid, AttrNumber attnum,
791 Oid *typid, int32 *typmod)
794 Form_pg_attribute att_tup;
796 tp = SearchSysCache(ATTNUM,
797 ObjectIdGetDatum(relid),
798 Int16GetDatum(attnum),
800 if (!HeapTupleIsValid(tp))
801 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
803 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
805 *typid = att_tup->atttypid;
806 *typmod = att_tup->atttypmod;
810 /* ---------- INDEX CACHE ---------- */
812 /* watch this space...
815 /* ---------- OPCLASS CACHE ---------- */
820 * Returns the OID of the operator family the opclass belongs to.
823 get_opclass_family(Oid opclass)
826 Form_pg_opclass cla_tup;
829 tp = SearchSysCache(CLAOID,
830 ObjectIdGetDatum(opclass),
832 if (!HeapTupleIsValid(tp))
833 elog(ERROR, "cache lookup failed for opclass %u", opclass);
834 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
836 result = cla_tup->opcfamily;
842 * get_opclass_input_type
844 * Returns the OID of the datatype the opclass indexes.
847 get_opclass_input_type(Oid opclass)
850 Form_pg_opclass cla_tup;
853 tp = SearchSysCache(CLAOID,
854 ObjectIdGetDatum(opclass),
856 if (!HeapTupleIsValid(tp))
857 elog(ERROR, "cache lookup failed for opclass %u", opclass);
858 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
860 result = cla_tup->opcintype;
865 /* ---------- OPERATOR CACHE ---------- */
870 * Returns the regproc id of the routine used to implement an
871 * operator given the operator oid.
878 tp = SearchSysCache(OPEROID,
879 ObjectIdGetDatum(opno),
881 if (HeapTupleIsValid(tp))
883 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
886 result = optup->oprcode;
891 return (RegProcedure) InvalidOid;
896 * returns the name of the operator with the given opno
898 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
905 tp = SearchSysCache(OPEROID,
906 ObjectIdGetDatum(opno),
908 if (HeapTupleIsValid(tp))
910 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
913 result = pstrdup(NameStr(optup->oprname));
924 * Returns the left and right input datatypes for an operator
925 * (InvalidOid if not relevant).
928 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
931 Form_pg_operator optup;
933 tp = SearchSysCache(OPEROID,
934 ObjectIdGetDatum(opno),
936 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
937 elog(ERROR, "cache lookup failed for operator %u", opno);
938 optup = (Form_pg_operator) GETSTRUCT(tp);
939 *lefttype = optup->oprleft;
940 *righttype = optup->oprright;
947 * Returns true if the operator is potentially mergejoinable. (The planner
948 * will fail to find any mergejoin plans unless there are suitable btree
949 * opfamily entries for this operator and associated sortops. The pg_operator
950 * flag is just a hint to tell the planner whether to bother looking.)
953 op_mergejoinable(Oid opno)
958 tp = SearchSysCache(OPEROID,
959 ObjectIdGetDatum(opno),
961 if (HeapTupleIsValid(tp))
963 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
965 result = optup->oprcanmerge;
974 * Returns true if the operator is hashjoinable. (There must be a suitable
975 * hash opfamily entry for this operator if it is so marked.)
978 op_hashjoinable(Oid opno)
983 tp = SearchSysCache(OPEROID,
984 ObjectIdGetDatum(opno),
986 if (HeapTupleIsValid(tp))
988 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
990 result = optup->oprcanhash;
999 * Get the proisstrict flag for the operator's underlying function.
1004 RegProcedure funcid = get_opcode(opno);
1006 if (funcid == (RegProcedure) InvalidOid)
1007 elog(ERROR, "operator %u does not exist", opno);
1009 return func_strict((Oid) funcid);
1015 * Get the provolatile flag for the operator's underlying function.
1018 op_volatile(Oid opno)
1020 RegProcedure funcid = get_opcode(opno);
1022 if (funcid == (RegProcedure) InvalidOid)
1023 elog(ERROR, "operator %u does not exist", opno);
1025 return func_volatile((Oid) funcid);
1031 * Returns the corresponding commutator of an operator.
1034 get_commutator(Oid opno)
1038 tp = SearchSysCache(OPEROID,
1039 ObjectIdGetDatum(opno),
1041 if (HeapTupleIsValid(tp))
1043 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1046 result = optup->oprcom;
1047 ReleaseSysCache(tp);
1057 * Returns the corresponding negator of an operator.
1060 get_negator(Oid opno)
1064 tp = SearchSysCache(OPEROID,
1065 ObjectIdGetDatum(opno),
1067 if (HeapTupleIsValid(tp))
1069 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1072 result = optup->oprnegate;
1073 ReleaseSysCache(tp);
1083 * Returns procedure id for computing selectivity of an operator.
1086 get_oprrest(Oid opno)
1090 tp = SearchSysCache(OPEROID,
1091 ObjectIdGetDatum(opno),
1093 if (HeapTupleIsValid(tp))
1095 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1096 RegProcedure result;
1098 result = optup->oprrest;
1099 ReleaseSysCache(tp);
1103 return (RegProcedure) InvalidOid;
1109 * Returns procedure id for computing selectivity of a join.
1112 get_oprjoin(Oid opno)
1116 tp = SearchSysCache(OPEROID,
1117 ObjectIdGetDatum(opno),
1119 if (HeapTupleIsValid(tp))
1121 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1122 RegProcedure result;
1124 result = optup->oprjoin;
1125 ReleaseSysCache(tp);
1129 return (RegProcedure) InvalidOid;
1132 /* ---------- FUNCTION CACHE ---------- */
1136 * returns the name of the function with the given funcid
1138 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1141 get_func_name(Oid funcid)
1145 tp = SearchSysCache(PROCOID,
1146 ObjectIdGetDatum(funcid),
1148 if (HeapTupleIsValid(tp))
1150 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1153 result = pstrdup(NameStr(functup->proname));
1154 ReleaseSysCache(tp);
1163 * Given procedure id, return the function's result type.
1166 get_func_rettype(Oid funcid)
1171 tp = SearchSysCache(PROCOID,
1172 ObjectIdGetDatum(funcid),
1174 if (!HeapTupleIsValid(tp))
1175 elog(ERROR, "cache lookup failed for function %u", funcid);
1177 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1178 ReleaseSysCache(tp);
1184 * Given procedure id, return the number of arguments.
1187 get_func_nargs(Oid funcid)
1192 tp = SearchSysCache(PROCOID,
1193 ObjectIdGetDatum(funcid),
1195 if (!HeapTupleIsValid(tp))
1196 elog(ERROR, "cache lookup failed for function %u", funcid);
1198 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1199 ReleaseSysCache(tp);
1204 * get_func_signature
1205 * Given procedure id, return the function's argument and result types.
1206 * (The return value is the result type.)
1208 * The arguments are returned as a palloc'd array.
1211 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1214 Form_pg_proc procstruct;
1217 tp = SearchSysCache(PROCOID,
1218 ObjectIdGetDatum(funcid),
1220 if (!HeapTupleIsValid(tp))
1221 elog(ERROR, "cache lookup failed for function %u", funcid);
1223 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1225 result = procstruct->prorettype;
1226 *nargs = (int) procstruct->pronargs;
1227 Assert(*nargs == procstruct->proargtypes.dim1);
1228 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1229 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1231 ReleaseSysCache(tp);
1237 * Given procedure id, return the function's proretset flag.
1240 get_func_retset(Oid funcid)
1245 tp = SearchSysCache(PROCOID,
1246 ObjectIdGetDatum(funcid),
1248 if (!HeapTupleIsValid(tp))
1249 elog(ERROR, "cache lookup failed for function %u", funcid);
1251 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1252 ReleaseSysCache(tp);
1258 * Given procedure id, return the function's proisstrict flag.
1261 func_strict(Oid funcid)
1266 tp = SearchSysCache(PROCOID,
1267 ObjectIdGetDatum(funcid),
1269 if (!HeapTupleIsValid(tp))
1270 elog(ERROR, "cache lookup failed for function %u", funcid);
1272 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1273 ReleaseSysCache(tp);
1279 * Given procedure id, return the function's provolatile flag.
1282 func_volatile(Oid funcid)
1287 tp = SearchSysCache(PROCOID,
1288 ObjectIdGetDatum(funcid),
1290 if (!HeapTupleIsValid(tp))
1291 elog(ERROR, "cache lookup failed for function %u", funcid);
1293 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1294 ReleaseSysCache(tp);
1298 /* ---------- RELATION CACHE ---------- */
1302 * Given name and namespace of a relation, look up the OID.
1304 * Returns InvalidOid if there is no such relation.
1307 get_relname_relid(const char *relname, Oid relnamespace)
1309 return GetSysCacheOid(RELNAMENSP,
1310 PointerGetDatum(relname),
1311 ObjectIdGetDatum(relnamespace),
1319 * Returns the number of attributes for a given relation.
1322 get_relnatts(Oid relid)
1326 tp = SearchSysCache(RELOID,
1327 ObjectIdGetDatum(relid),
1329 if (HeapTupleIsValid(tp))
1331 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1334 result = reltup->relnatts;
1335 ReleaseSysCache(tp);
1339 return InvalidAttrNumber;
1345 * Returns the name of a given relation.
1347 * Returns a palloc'd copy of the string, or NULL if no such relation.
1349 * NOTE: since relation name is not unique, be wary of code that uses this
1350 * for anything except preparing error messages.
1353 get_rel_name(Oid relid)
1357 tp = SearchSysCache(RELOID,
1358 ObjectIdGetDatum(relid),
1360 if (HeapTupleIsValid(tp))
1362 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1365 result = pstrdup(NameStr(reltup->relname));
1366 ReleaseSysCache(tp);
1376 * Returns the pg_namespace OID associated with a given relation.
1379 get_rel_namespace(Oid relid)
1383 tp = SearchSysCache(RELOID,
1384 ObjectIdGetDatum(relid),
1386 if (HeapTupleIsValid(tp))
1388 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1391 result = reltup->relnamespace;
1392 ReleaseSysCache(tp);
1402 * Returns the pg_type OID associated with a given relation.
1404 * Note: not all pg_class entries have associated pg_type OIDs; so be
1405 * careful to check for InvalidOid result.
1408 get_rel_type_id(Oid relid)
1412 tp = SearchSysCache(RELOID,
1413 ObjectIdGetDatum(relid),
1415 if (HeapTupleIsValid(tp))
1417 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1420 result = reltup->reltype;
1421 ReleaseSysCache(tp);
1431 * Returns the relkind associated with a given relation.
1434 get_rel_relkind(Oid relid)
1438 tp = SearchSysCache(RELOID,
1439 ObjectIdGetDatum(relid),
1441 if (HeapTupleIsValid(tp))
1443 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1446 result = reltup->relkind;
1447 ReleaseSysCache(tp);
1455 /* ---------- TYPE CACHE ---------- */
1460 * Given the type OID, determine whether the type is defined
1461 * (if not, it's only a shell).
1464 get_typisdefined(Oid typid)
1468 tp = SearchSysCache(TYPEOID,
1469 ObjectIdGetDatum(typid),
1471 if (HeapTupleIsValid(tp))
1473 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1476 result = typtup->typisdefined;
1477 ReleaseSysCache(tp);
1487 * Given the type OID, return the length of the type.
1490 get_typlen(Oid typid)
1494 tp = SearchSysCache(TYPEOID,
1495 ObjectIdGetDatum(typid),
1497 if (HeapTupleIsValid(tp))
1499 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1502 result = typtup->typlen;
1503 ReleaseSysCache(tp);
1513 * Given the type OID, determine whether the type is returned by value or
1514 * not. Returns true if by value, false if by reference.
1517 get_typbyval(Oid typid)
1521 tp = SearchSysCache(TYPEOID,
1522 ObjectIdGetDatum(typid),
1524 if (HeapTupleIsValid(tp))
1526 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1529 result = typtup->typbyval;
1530 ReleaseSysCache(tp);
1540 * A two-fer: given the type OID, return both typlen and typbyval.
1542 * Since both pieces of info are needed to know how to copy a Datum,
1543 * many places need both. Might as well get them with one cache lookup
1544 * instead of two. Also, this routine raises an error instead of
1545 * returning a bogus value when given a bad type OID.
1548 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1551 Form_pg_type typtup;
1553 tp = SearchSysCache(TYPEOID,
1554 ObjectIdGetDatum(typid),
1556 if (!HeapTupleIsValid(tp))
1557 elog(ERROR, "cache lookup failed for type %u", typid);
1558 typtup = (Form_pg_type) GETSTRUCT(tp);
1559 *typlen = typtup->typlen;
1560 *typbyval = typtup->typbyval;
1561 ReleaseSysCache(tp);
1565 * get_typlenbyvalalign
1567 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1570 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1574 Form_pg_type typtup;
1576 tp = SearchSysCache(TYPEOID,
1577 ObjectIdGetDatum(typid),
1579 if (!HeapTupleIsValid(tp))
1580 elog(ERROR, "cache lookup failed for type %u", typid);
1581 typtup = (Form_pg_type) GETSTRUCT(tp);
1582 *typlen = typtup->typlen;
1583 *typbyval = typtup->typbyval;
1584 *typalign = typtup->typalign;
1585 ReleaseSysCache(tp);
1590 * Given a pg_type row, select the type OID to pass to I/O functions
1592 * Formerly, all I/O functions were passed pg_type.typelem as their second
1593 * parameter, but we now have a more complex rule about what to pass.
1594 * This knowledge is intended to be centralized here --- direct references
1595 * to typelem elsewhere in the code are wrong, if they are associated with
1596 * I/O calls and not with actual subscripting operations! (But see
1597 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1599 * As of PostgreSQL 8.1, output functions receive only the value itself
1600 * and not any auxiliary parameters, so the name of this routine is now
1601 * a bit of a misnomer ... it should be getTypeInputParam.
1604 getTypeIOParam(HeapTuple typeTuple)
1606 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1609 * Array types get their typelem as parameter; everybody else gets their
1610 * own type OID as parameter. (This is a change from 8.0, in which only
1611 * composite types got their own OID as parameter.)
1613 if (OidIsValid(typeStruct->typelem))
1614 return typeStruct->typelem;
1616 return HeapTupleGetOid(typeTuple);
1622 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1623 * typdelim, typioparam, and IO function OID. The IO function
1624 * returned is controlled by IOFuncSelector
1627 get_type_io_data(Oid typid,
1628 IOFuncSelector which_func,
1636 HeapTuple typeTuple;
1637 Form_pg_type typeStruct;
1640 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1641 * use array_in and array_out during bootstrap.
1643 if (IsBootstrapProcessingMode())
1648 boot_get_type_io_data(typid,
1665 elog(ERROR, "binary I/O not supported during bootstrap");
1671 typeTuple = SearchSysCache(TYPEOID,
1672 ObjectIdGetDatum(typid),
1674 if (!HeapTupleIsValid(typeTuple))
1675 elog(ERROR, "cache lookup failed for type %u", typid);
1676 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1678 *typlen = typeStruct->typlen;
1679 *typbyval = typeStruct->typbyval;
1680 *typalign = typeStruct->typalign;
1681 *typdelim = typeStruct->typdelim;
1682 *typioparam = getTypeIOParam(typeTuple);
1686 *func = typeStruct->typinput;
1689 *func = typeStruct->typoutput;
1691 case IOFunc_receive:
1692 *func = typeStruct->typreceive;
1695 *func = typeStruct->typsend;
1698 ReleaseSysCache(typeTuple);
1703 get_typalign(Oid typid)
1707 tp = SearchSysCache(TYPEOID,
1708 ObjectIdGetDatum(typid),
1710 if (HeapTupleIsValid(tp))
1712 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1715 result = typtup->typalign;
1716 ReleaseSysCache(tp);
1725 get_typstorage(Oid typid)
1729 tp = SearchSysCache(TYPEOID,
1730 ObjectIdGetDatum(typid),
1732 if (HeapTupleIsValid(tp))
1734 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1737 result = typtup->typstorage;
1738 ReleaseSysCache(tp);
1747 * Given a type OID, return the type's default value, if any.
1749 * The result is a palloc'd expression node tree, or NULL if there
1750 * is no defined default for the datatype.
1752 * NB: caller should be prepared to coerce result to correct datatype;
1753 * the returned expression tree might produce something of the wrong type.
1756 get_typdefault(Oid typid)
1758 HeapTuple typeTuple;
1764 typeTuple = SearchSysCache(TYPEOID,
1765 ObjectIdGetDatum(typid),
1767 if (!HeapTupleIsValid(typeTuple))
1768 elog(ERROR, "cache lookup failed for type %u", typid);
1769 type = (Form_pg_type) GETSTRUCT(typeTuple);
1772 * typdefault and typdefaultbin are potentially null, so don't try to
1773 * access 'em as struct fields. Must do it the hard way with
1776 datum = SysCacheGetAttr(TYPEOID,
1778 Anum_pg_type_typdefaultbin,
1783 /* We have an expression default */
1784 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1789 /* Perhaps we have a plain literal default */
1790 datum = SysCacheGetAttr(TYPEOID,
1792 Anum_pg_type_typdefault,
1797 char *strDefaultVal;
1799 /* Convert text datum to C string */
1800 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1802 /* Convert C string to a value of the given type */
1803 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
1804 getTypeIOParam(typeTuple), -1);
1805 /* Build a Const node containing the value */
1806 expr = (Node *) makeConst(typid,
1811 pfree(strDefaultVal);
1820 ReleaseSysCache(typeTuple);
1827 * If the given type is a domain, return its base type;
1828 * otherwise return the type's own OID.
1831 getBaseType(Oid typid)
1835 return getBaseTypeAndTypmod(typid, &typmod);
1839 * getBaseTypeAndTypmod
1840 * If the given type is a domain, return its base type and typmod;
1841 * otherwise return the type's own OID, and leave *typmod unchanged.
1843 * Note that the "applied typmod" should be -1 for every domain level
1844 * above the bottommost; therefore, if the passed-in typid is indeed
1845 * a domain, *typmod should be -1.
1848 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
1851 * We loop to find the bottom base type in a stack of domains.
1856 Form_pg_type typTup;
1858 tup = SearchSysCache(TYPEOID,
1859 ObjectIdGetDatum(typid),
1861 if (!HeapTupleIsValid(tup))
1862 elog(ERROR, "cache lookup failed for type %u", typid);
1863 typTup = (Form_pg_type) GETSTRUCT(tup);
1864 if (typTup->typtype != 'd')
1866 /* Not a domain, so done */
1867 ReleaseSysCache(tup);
1871 Assert(*typmod == -1);
1872 typid = typTup->typbasetype;
1873 *typmod = typTup->typtypmod;
1875 ReleaseSysCache(tup);
1884 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
1885 * estimate the average width of values of the type. This is used by
1886 * the planner, which doesn't require absolutely correct results;
1887 * it's OK (and expected) to guess if we don't know for sure.
1890 get_typavgwidth(Oid typid, int32 typmod)
1892 int typlen = get_typlen(typid);
1896 * Easy if it's a fixed-width type
1902 * type_maximum_size knows the encoding of typmod for some datatypes;
1903 * don't duplicate that knowledge here.
1905 maxwidth = type_maximum_size(typid, typmod);
1909 * For BPCHAR, the max width is also the only width. Otherwise we
1910 * need to guess about the typical data width given the max. A sliding
1911 * scale for percentage of max width seems reasonable.
1913 if (typid == BPCHAROID)
1916 return maxwidth; /* assume full width */
1917 if (maxwidth < 1000)
1918 return 32 + (maxwidth - 32) / 2; /* assume 50% */
1921 * Beyond 1000, assume we're looking at something like
1922 * "varchar(10000)" where the limit isn't actually reached often, and
1923 * use a fixed estimate.
1925 return 32 + (1000 - 32) / 2;
1929 * Ooops, we have no idea ... wild guess time.
1937 * Given the type OID, find if it is a basic type, a complex type, etc.
1938 * It returns the null char if the cache lookup fails...
1941 get_typtype(Oid typid)
1945 tp = SearchSysCache(TYPEOID,
1946 ObjectIdGetDatum(typid),
1948 if (HeapTupleIsValid(tp))
1950 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1953 result = typtup->typtype;
1954 ReleaseSysCache(tp);
1964 * Convenience function to determine whether a type OID represents
1965 * a "rowtype" type --- either RECORD or a named composite type.
1968 type_is_rowtype(Oid typid)
1970 return (typid == RECORDOID || get_typtype(typid) == 'c');
1976 * Given the type OID, get the typrelid (InvalidOid if not a complex
1980 get_typ_typrelid(Oid typid)
1984 tp = SearchSysCache(TYPEOID,
1985 ObjectIdGetDatum(typid),
1987 if (HeapTupleIsValid(tp))
1989 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1992 result = typtup->typrelid;
1993 ReleaseSysCache(tp);
2003 * Given the type OID, get the typelem (InvalidOid if not an array type).
2005 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2006 * returned if the input is a fixed-length array type.
2009 get_element_type(Oid typid)
2013 tp = SearchSysCache(TYPEOID,
2014 ObjectIdGetDatum(typid),
2016 if (HeapTupleIsValid(tp))
2018 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2021 if (typtup->typlen == -1)
2022 result = typtup->typelem;
2024 result = InvalidOid;
2025 ReleaseSysCache(tp);
2035 * Given the type OID, get the corresponding array type.
2036 * Returns InvalidOid if no array type can be found.
2038 * NB: this only considers varlena arrays to be true arrays.
2041 get_array_type(Oid typid)
2045 tp = SearchSysCache(TYPEOID,
2046 ObjectIdGetDatum(typid),
2048 if (HeapTupleIsValid(tp))
2050 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2051 char *array_typename;
2054 array_typename = makeArrayTypeName(NameStr(typtup->typname));
2055 namespaceId = typtup->typnamespace;
2056 ReleaseSysCache(tp);
2058 tp = SearchSysCache(TYPENAMENSP,
2059 PointerGetDatum(array_typename),
2060 ObjectIdGetDatum(namespaceId),
2063 pfree(array_typename);
2065 if (HeapTupleIsValid(tp))
2069 typtup = (Form_pg_type) GETSTRUCT(tp);
2070 if (typtup->typlen == -1 && typtup->typelem == typid)
2071 result = HeapTupleGetOid(tp);
2073 result = InvalidOid;
2074 ReleaseSysCache(tp);
2084 * Get info needed for converting values of a type to internal form
2087 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2089 HeapTuple typeTuple;
2092 typeTuple = SearchSysCache(TYPEOID,
2093 ObjectIdGetDatum(type),
2095 if (!HeapTupleIsValid(typeTuple))
2096 elog(ERROR, "cache lookup failed for type %u", type);
2097 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2099 if (!pt->typisdefined)
2101 (errcode(ERRCODE_UNDEFINED_OBJECT),
2102 errmsg("type %s is only a shell",
2103 format_type_be(type))));
2104 if (!OidIsValid(pt->typinput))
2106 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2107 errmsg("no input function available for type %s",
2108 format_type_be(type))));
2110 *typInput = pt->typinput;
2111 *typIOParam = getTypeIOParam(typeTuple);
2113 ReleaseSysCache(typeTuple);
2119 * Get info needed for printing values of a type
2122 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2124 HeapTuple typeTuple;
2127 typeTuple = SearchSysCache(TYPEOID,
2128 ObjectIdGetDatum(type),
2130 if (!HeapTupleIsValid(typeTuple))
2131 elog(ERROR, "cache lookup failed for type %u", type);
2132 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2134 if (!pt->typisdefined)
2136 (errcode(ERRCODE_UNDEFINED_OBJECT),
2137 errmsg("type %s is only a shell",
2138 format_type_be(type))));
2139 if (!OidIsValid(pt->typoutput))
2141 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2142 errmsg("no output function available for type %s",
2143 format_type_be(type))));
2145 *typOutput = pt->typoutput;
2146 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2148 ReleaseSysCache(typeTuple);
2152 * getTypeBinaryInputInfo
2154 * Get info needed for binary input of values of a type
2157 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2159 HeapTuple typeTuple;
2162 typeTuple = SearchSysCache(TYPEOID,
2163 ObjectIdGetDatum(type),
2165 if (!HeapTupleIsValid(typeTuple))
2166 elog(ERROR, "cache lookup failed for type %u", type);
2167 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2169 if (!pt->typisdefined)
2171 (errcode(ERRCODE_UNDEFINED_OBJECT),
2172 errmsg("type %s is only a shell",
2173 format_type_be(type))));
2174 if (!OidIsValid(pt->typreceive))
2176 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2177 errmsg("no binary input function available for type %s",
2178 format_type_be(type))));
2180 *typReceive = pt->typreceive;
2181 *typIOParam = getTypeIOParam(typeTuple);
2183 ReleaseSysCache(typeTuple);
2187 * getTypeBinaryOutputInfo
2189 * Get info needed for binary output of values of a type
2192 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2194 HeapTuple typeTuple;
2197 typeTuple = SearchSysCache(TYPEOID,
2198 ObjectIdGetDatum(type),
2200 if (!HeapTupleIsValid(typeTuple))
2201 elog(ERROR, "cache lookup failed for type %u", type);
2202 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2204 if (!pt->typisdefined)
2206 (errcode(ERRCODE_UNDEFINED_OBJECT),
2207 errmsg("type %s is only a shell",
2208 format_type_be(type))));
2209 if (!OidIsValid(pt->typsend))
2211 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2212 errmsg("no binary output function available for type %s",
2213 format_type_be(type))));
2215 *typSend = pt->typsend;
2216 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2218 ReleaseSysCache(typeTuple);
2224 * Given the type OID, return the type's typmodin procedure, if any.
2227 get_typmodin(Oid typid)
2231 tp = SearchSysCache(TYPEOID,
2232 ObjectIdGetDatum(typid),
2234 if (HeapTupleIsValid(tp))
2236 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2239 result = typtup->typmodin;
2240 ReleaseSysCache(tp);
2251 * Given the type OID, return the type's typmodout procedure, if any.
2254 get_typmodout(Oid typid)
2258 tp = SearchSysCache(TYPEOID,
2259 ObjectIdGetDatum(typid),
2261 if (HeapTupleIsValid(tp))
2263 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2266 result = typtup->typmodout;
2267 ReleaseSysCache(tp);
2273 #endif /* NOT_USED */
2276 /* ---------- STATISTICS CACHE ---------- */
2281 * Given the table and attribute number of a column, get the average
2282 * width of entries in the column. Return zero if no data available.
2285 get_attavgwidth(Oid relid, AttrNumber attnum)
2289 tp = SearchSysCache(STATRELATT,
2290 ObjectIdGetDatum(relid),
2291 Int16GetDatum(attnum),
2293 if (HeapTupleIsValid(tp))
2295 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2297 ReleaseSysCache(tp);
2307 * Extract the contents of a "slot" of a pg_statistic tuple.
2308 * Returns TRUE if requested slot type was found, else FALSE.
2310 * Unlike other routines in this file, this takes a pointer to an
2311 * already-looked-up tuple in the pg_statistic cache. We do this since
2312 * most callers will want to extract more than one value from the cache
2313 * entry, and we don't want to repeat the cache lookup unnecessarily.
2315 * statstuple: pg_statistics tuple to be examined.
2316 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2317 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2318 * reqkind: STAKIND code for desired statistics slot kind.
2319 * reqop: STAOP value wanted, or InvalidOid if don't care.
2320 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2321 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2323 * If assigned, values and numbers are set to point to palloc'd arrays.
2324 * If the attribute type is pass-by-reference, the values referenced by
2325 * the values array are themselves palloc'd. The palloc'd stuff can be
2326 * freed by calling free_attstatsslot.
2329 get_attstatsslot(HeapTuple statstuple,
2330 Oid atttype, int32 atttypmod,
2331 int reqkind, Oid reqop,
2332 Datum **values, int *nvalues,
2333 float4 **numbers, int *nnumbers)
2335 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2340 ArrayType *statarray;
2342 HeapTuple typeTuple;
2343 Form_pg_type typeForm;
2345 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2347 if ((&stats->stakind1)[i] == reqkind &&
2348 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2351 if (i >= STATISTIC_NUM_SLOTS)
2352 return false; /* not there */
2356 val = SysCacheGetAttr(STATRELATT, statstuple,
2357 Anum_pg_statistic_stavalues1 + i,
2360 elog(ERROR, "stavalues is null");
2361 statarray = DatumGetArrayTypeP(val);
2363 /* Need to get info about the array element type */
2364 typeTuple = SearchSysCache(TYPEOID,
2365 ObjectIdGetDatum(atttype),
2367 if (!HeapTupleIsValid(typeTuple))
2368 elog(ERROR, "cache lookup failed for type %u", atttype);
2369 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2371 /* Deconstruct array into Datum elements; NULLs not expected */
2372 deconstruct_array(statarray,
2377 values, NULL, nvalues);
2380 * If the element type is pass-by-reference, we now have a bunch of
2381 * Datums that are pointers into the syscache value. Copy them to
2382 * avoid problems if syscache decides to drop the entry.
2384 if (!typeForm->typbyval)
2386 for (j = 0; j < *nvalues; j++)
2388 (*values)[j] = datumCopy((*values)[j],
2394 ReleaseSysCache(typeTuple);
2397 * Free statarray if it's a detoasted copy.
2399 if ((Pointer) statarray != DatumGetPointer(val))
2405 val = SysCacheGetAttr(STATRELATT, statstuple,
2406 Anum_pg_statistic_stanumbers1 + i,
2409 elog(ERROR, "stanumbers is null");
2410 statarray = DatumGetArrayTypeP(val);
2413 * We expect the array to be a 1-D float4 array; verify that. We don't
2414 * need to use deconstruct_array() since the array data is just going
2415 * to look like a C array of float4 values.
2417 narrayelem = ARR_DIMS(statarray)[0];
2418 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2419 ARR_HASNULL(statarray) ||
2420 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2421 elog(ERROR, "stanumbers is not a 1-D float4 array");
2422 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2423 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2424 *nnumbers = narrayelem;
2427 * Free statarray if it's a detoasted copy.
2429 if ((Pointer) statarray != DatumGetPointer(val))
2438 * Free data allocated by get_attstatsslot
2440 * atttype need be valid only if values != NULL.
2443 free_attstatsslot(Oid atttype,
2444 Datum *values, int nvalues,
2445 float4 *numbers, int nnumbers)
2449 if (!get_typbyval(atttype))
2453 for (i = 0; i < nvalues; i++)
2454 pfree(DatumGetPointer(values[i]));
2462 /* ---------- PG_NAMESPACE CACHE ---------- */
2465 * get_namespace_name
2466 * Returns the name of a given namespace
2468 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2471 get_namespace_name(Oid nspid)
2475 tp = SearchSysCache(NAMESPACEOID,
2476 ObjectIdGetDatum(nspid),
2478 if (HeapTupleIsValid(tp))
2480 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2483 result = pstrdup(NameStr(nsptup->nspname));
2484 ReleaseSysCache(tp);
2491 /* ---------- PG_AUTHID CACHE ---------- */
2495 * Given a role name, look up the role's OID.
2496 * Returns InvalidOid if no such role.
2499 get_roleid(const char *rolname)
2501 return GetSysCacheOid(AUTHNAME,
2502 PointerGetDatum(rolname),
2507 * get_roleid_checked
2508 * Given a role name, look up the role's OID.
2509 * ereports if no such role.
2512 get_roleid_checked(const char *rolname)
2516 roleid = get_roleid(rolname);
2517 if (!OidIsValid(roleid))
2519 (errcode(ERRCODE_UNDEFINED_OBJECT),
2520 errmsg("role \"%s\" does not exist", rolname)));