1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2010, 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.171 2010/07/09 22:57:39 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_constraint.h"
24 #include "catalog/pg_namespace.h"
25 #include "catalog/pg_opclass.h"
26 #include "catalog/pg_operator.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_statistic.h"
29 #include "catalog/pg_type.h"
30 #include "miscadmin.h"
31 #include "nodes/makefuncs.h"
32 #include "utils/array.h"
33 #include "utils/builtins.h"
34 #include "utils/datum.h"
35 #include "utils/lsyscache.h"
36 #include "utils/syscache.h"
38 /* Hook for plugins to get control in get_attavgwidth() */
39 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
42 /* ---------- AMOP CACHES ---------- */
47 * Return t iff operator 'opno' is in operator family 'opfamily'.
50 op_in_opfamily(Oid opno, Oid opfamily)
52 return SearchSysCacheExists2(AMOPOPID,
53 ObjectIdGetDatum(opno),
54 ObjectIdGetDatum(opfamily));
58 * get_op_opfamily_strategy
60 * Get the operator's strategy number within the specified opfamily,
61 * or 0 if it's not a member of the opfamily.
64 get_op_opfamily_strategy(Oid opno, Oid opfamily)
67 Form_pg_amop amop_tup;
70 tp = SearchSysCache2(AMOPOPID,
71 ObjectIdGetDatum(opno),
72 ObjectIdGetDatum(opfamily));
73 if (!HeapTupleIsValid(tp))
75 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
76 result = amop_tup->amopstrategy;
82 * get_op_opfamily_properties
84 * Get the operator's strategy number and declared input data types
85 * within the specified opfamily.
87 * Caller should already have verified that opno is a member of opfamily,
88 * therefore we raise an error if the tuple is not found.
91 get_op_opfamily_properties(Oid opno, Oid opfamily,
97 Form_pg_amop amop_tup;
99 tp = SearchSysCache2(AMOPOPID,
100 ObjectIdGetDatum(opno),
101 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;
113 * get_opfamily_member
114 * Get the OID of the operator that implements the specified strategy
115 * with the specified datatypes for the specified opfamily.
117 * Returns InvalidOid if there is no pg_amop entry for the given keys.
120 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
124 Form_pg_amop amop_tup;
127 tp = SearchSysCache4(AMOPSTRATEGY,
128 ObjectIdGetDatum(opfamily),
129 ObjectIdGetDatum(lefttype),
130 ObjectIdGetDatum(righttype),
131 Int16GetDatum(strategy));
132 if (!HeapTupleIsValid(tp))
134 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
135 result = amop_tup->amopopr;
141 * get_ordering_op_properties
142 * Given the OID of an ordering operator (a btree "<" or ">" operator),
143 * determine its opfamily, its declared input datatype, and its
144 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
146 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
147 * (This indicates that the operator is not a valid ordering operator.)
149 * Note: the operator could be registered in multiple families, for example
150 * if someone were to build a "reverse sort" opfamily. This would result in
151 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
152 * or NULLS LAST, as well as inefficient planning due to failure to match up
153 * pathkeys that should be the same. So we want a determinate result here.
154 * Because of the way the syscache search works, we'll use the interpretation
155 * associated with the opfamily with smallest OID, which is probably
156 * determinate enough. Since there is no longer any particularly good reason
157 * to build reverse-sort opfamilies, it doesn't seem worth expending any
158 * additional effort on ensuring consistency.
161 get_ordering_op_properties(Oid opno,
162 Oid *opfamily, Oid *opcintype, int16 *strategy)
168 /* ensure outputs are initialized on failure */
169 *opfamily = InvalidOid;
170 *opcintype = InvalidOid;
174 * Search pg_amop to see if the target operator is registered as the "<"
175 * or ">" operator of any btree opfamily.
177 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
179 for (i = 0; i < catlist->n_members; i++)
181 HeapTuple tuple = &catlist->members[i]->tuple;
182 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
185 if (aform->amopmethod != BTREE_AM_OID)
188 if (aform->amopstrategy == BTLessStrategyNumber ||
189 aform->amopstrategy == BTGreaterStrategyNumber)
191 /* Found it ... should have consistent input types */
192 if (aform->amoplefttype == aform->amoprighttype)
194 /* Found a suitable opfamily, return info */
195 *opfamily = aform->amopfamily;
196 *opcintype = aform->amoplefttype;
197 *strategy = aform->amopstrategy;
204 ReleaseSysCacheList(catlist);
210 * get_compare_function_for_ordering_op
211 * Get the OID of the datatype-specific btree comparison function
212 * associated with an ordering operator (a "<" or ">" operator).
214 * *cmpfunc receives the comparison function OID.
215 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
216 * (indicating the comparison result must be negated before use).
218 * Returns TRUE if successful, FALSE if no btree function can be found.
219 * (This indicates that the operator is not a valid ordering operator.)
222 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
228 /* Find the operator in pg_amop */
229 if (get_ordering_op_properties(opno,
230 &opfamily, &opcintype, &strategy))
232 /* Found a suitable opfamily, get matching support function */
233 *cmpfunc = get_opfamily_proc(opfamily,
238 if (!OidIsValid(*cmpfunc)) /* should not happen */
239 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
240 BTORDER_PROC, opcintype, opcintype, opfamily);
241 *reverse = (strategy == BTGreaterStrategyNumber);
245 /* ensure outputs are set on failure */
246 *cmpfunc = InvalidOid;
253 * get_equality_op_for_ordering_op
254 * Get the OID of the datatype-specific btree equality operator
255 * associated with an ordering operator (a "<" or ">" operator).
257 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
260 * Returns InvalidOid if no matching equality operator can be found.
261 * (This indicates that the operator is not a valid ordering operator.)
264 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
266 Oid result = InvalidOid;
271 /* Find the operator in pg_amop */
272 if (get_ordering_op_properties(opno,
273 &opfamily, &opcintype, &strategy))
275 /* Found a suitable opfamily, get matching equality operator */
276 result = get_opfamily_member(opfamily,
279 BTEqualStrategyNumber);
281 *reverse = (strategy == BTGreaterStrategyNumber);
288 * get_ordering_op_for_equality_op
289 * Get the OID of a datatype-specific btree ordering operator
290 * associated with an equality operator. (If there are multiple
291 * possibilities, assume any one will do.)
293 * This function is used when we have to sort data before unique-ifying,
294 * and don't much care which sorting op is used as long as it's compatible
295 * with the intended equality operator. Since we need a sorting operator,
296 * it should be single-data-type even if the given operator is cross-type.
297 * The caller specifies whether to find an op for the LHS or RHS data type.
299 * Returns InvalidOid if no matching ordering operator can be found.
302 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
304 Oid result = InvalidOid;
309 * Search pg_amop to see if the target operator is registered as the "="
310 * operator of any btree opfamily.
312 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
314 for (i = 0; i < catlist->n_members; i++)
316 HeapTuple tuple = &catlist->members[i]->tuple;
317 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
320 if (aform->amopmethod != BTREE_AM_OID)
323 if (aform->amopstrategy == BTEqualStrategyNumber)
325 /* Found a suitable opfamily, get matching ordering operator */
328 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
329 result = get_opfamily_member(aform->amopfamily,
331 BTLessStrategyNumber);
332 if (OidIsValid(result))
334 /* failure probably shouldn't happen, but keep looking if so */
338 ReleaseSysCacheList(catlist);
344 * get_mergejoin_opfamilies
345 * Given a putatively mergejoinable operator, return a list of the OIDs
346 * of the btree opfamilies in which it represents equality.
348 * It is possible (though at present unusual) for an operator to be equality
349 * in more than one opfamily, hence the result is a list. This also lets us
350 * return NIL if the operator is not found in any opfamilies.
352 * The planner currently uses simple equal() tests to compare the lists
353 * returned by this function, which makes the list order relevant, though
354 * strictly speaking it should not be. Because of the way syscache list
355 * searches are handled, in normal operation the result will be sorted by OID
356 * so everything works fine. If running with system index usage disabled,
357 * the result ordering is unspecified and hence the planner might fail to
358 * recognize optimization opportunities ... but that's hardly a scenario in
359 * which performance is good anyway, so there's no point in expending code
360 * or cycles here to guarantee the ordering in that case.
363 get_mergejoin_opfamilies(Oid opno)
370 * Search pg_amop to see if the target operator is registered as the "="
371 * operator of any btree opfamily.
373 catlist = SearchSysCacheList1(AMOPOPID, 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_operators
393 * Get the OID(s) of hash equality operator(s) compatible with the given
394 * operator, but operating on its LHS and/or RHS datatype.
396 * An operator for the LHS type is sought and returned into *lhs_opno if
397 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
398 * and returned into *rhs_opno if rhs_opno isn't NULL.
400 * If the given operator is not cross-type, the results should be the same
401 * operator, but in cross-type situations they will be different.
403 * Returns true if able to find the requested operator(s), false if not.
404 * (This indicates that the operator should not have been marked oprcanhash.)
407 get_compatible_hash_operators(Oid opno,
408 Oid *lhs_opno, Oid *rhs_opno)
414 /* Ensure output args are initialized on failure */
416 *lhs_opno = InvalidOid;
418 *rhs_opno = InvalidOid;
421 * Search pg_amop to see if the target operator is registered as the "="
422 * operator of any hash opfamily. If the operator is registered in
423 * multiple opfamilies, assume we can use any one.
425 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
427 for (i = 0; i < catlist->n_members; i++)
429 HeapTuple tuple = &catlist->members[i]->tuple;
430 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
432 if (aform->amopmethod == HASH_AM_OID &&
433 aform->amopstrategy == HTEqualStrategyNumber)
435 /* No extra lookup needed if given operator is single-type */
436 if (aform->amoplefttype == aform->amoprighttype)
447 * Get the matching single-type operator(s). Failure probably
448 * shouldn't happen --- it implies a bogus opfamily --- but
449 * continue looking if so.
453 *lhs_opno = get_opfamily_member(aform->amopfamily,
456 HTEqualStrategyNumber);
457 if (!OidIsValid(*lhs_opno))
459 /* Matching LHS found, done if caller doesn't want RHS */
468 *rhs_opno = get_opfamily_member(aform->amopfamily,
469 aform->amoprighttype,
470 aform->amoprighttype,
471 HTEqualStrategyNumber);
472 if (!OidIsValid(*rhs_opno))
474 /* Forget any LHS operator from this opfamily */
476 *lhs_opno = InvalidOid;
479 /* Matching RHS found, so done */
486 ReleaseSysCacheList(catlist);
492 * get_op_hash_functions
493 * Get the OID(s) of hash support function(s) compatible with the given
494 * operator, operating on its LHS and/or RHS datatype as required.
496 * A function for the LHS type is sought and returned into *lhs_procno if
497 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
498 * and returned into *rhs_procno if rhs_procno isn't NULL.
500 * If the given operator is not cross-type, the results should be the same
501 * function, but in cross-type situations they will be different.
503 * Returns true if able to find the requested function(s), false if not.
504 * (This indicates that the operator should not have been marked oprcanhash.)
507 get_op_hash_functions(Oid opno,
508 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
514 /* Ensure output args are initialized on failure */
516 *lhs_procno = InvalidOid;
518 *rhs_procno = InvalidOid;
521 * Search pg_amop to see if the target operator is registered as the "="
522 * operator of any hash opfamily. If the operator is registered in
523 * multiple opfamilies, assume we can use any one.
525 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
527 for (i = 0; i < catlist->n_members; i++)
529 HeapTuple tuple = &catlist->members[i]->tuple;
530 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
532 if (aform->amopmethod == HASH_AM_OID &&
533 aform->amopstrategy == HTEqualStrategyNumber)
536 * Get the matching support function(s). Failure probably
537 * shouldn't happen --- it implies a bogus opfamily --- but
538 * continue looking if so.
542 *lhs_procno = get_opfamily_proc(aform->amopfamily,
546 if (!OidIsValid(*lhs_procno))
548 /* Matching LHS found, done if caller doesn't want RHS */
554 /* Only one lookup needed if given operator is single-type */
555 if (aform->amoplefttype == aform->amoprighttype)
557 *rhs_procno = *lhs_procno;
564 *rhs_procno = get_opfamily_proc(aform->amopfamily,
565 aform->amoprighttype,
566 aform->amoprighttype,
568 if (!OidIsValid(*rhs_procno))
570 /* Forget any LHS function from this opfamily */
572 *lhs_procno = InvalidOid;
575 /* Matching RHS found, so done */
582 ReleaseSysCacheList(catlist);
588 * get_op_btree_interpretation
589 * Given an operator's OID, find out which btree opfamilies it belongs to,
590 * and what strategy number it has within each one. The results are
591 * returned as an OID list and a parallel integer list.
593 * In addition to the normal btree operators, we consider a <> operator to be
594 * a "member" of an opfamily if its negator is an equality operator of the
595 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
598 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
608 * Find all the pg_amop entries containing the operator.
610 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
613 * If we can't find any opfamily containing the op, perhaps it is a <>
614 * operator. See if it has a negator that is in an opfamily.
617 if (catlist->n_members == 0)
619 Oid op_negator = get_negator(opno);
621 if (OidIsValid(op_negator))
624 ReleaseSysCacheList(catlist);
625 catlist = SearchSysCacheList1(AMOPOPID,
626 ObjectIdGetDatum(op_negator));
630 /* Now search the opfamilies */
631 for (i = 0; i < catlist->n_members; i++)
633 HeapTuple op_tuple = &catlist->members[i]->tuple;
634 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
636 StrategyNumber op_strategy;
639 if (op_form->amopmethod != BTREE_AM_OID)
642 /* Get the operator's btree strategy number */
643 opfamily_id = op_form->amopfamily;
644 op_strategy = (StrategyNumber) op_form->amopstrategy;
645 Assert(op_strategy >= 1 && op_strategy <= 5);
649 /* Only consider negators that are = */
650 if (op_strategy != BTEqualStrategyNumber)
652 op_strategy = ROWCOMPARE_NE;
655 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
656 *opstrats = lappend_int(*opstrats, op_strategy);
659 ReleaseSysCacheList(catlist);
663 * equality_ops_are_compatible
664 * Return TRUE if the two given equality operators have compatible
667 * This is trivially true if they are the same operator. Otherwise,
668 * we look to see if they can be found in the same btree or hash opfamily.
669 * Either finding allows us to assume that they have compatible notions
670 * of equality. (The reason we need to do these pushups is that one might
671 * be a cross-type operator; for instance int24eq vs int4eq.)
674 equality_ops_are_compatible(Oid opno1, Oid opno2)
680 /* Easy if they're the same operator */
685 * We search through all the pg_amop entries for opno1.
687 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
690 for (i = 0; i < catlist->n_members; i++)
692 HeapTuple op_tuple = &catlist->members[i]->tuple;
693 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
695 /* must be btree or hash */
696 if (op_form->amopmethod == BTREE_AM_OID ||
697 op_form->amopmethod == HASH_AM_OID)
699 if (op_in_opfamily(opno2, op_form->amopfamily))
707 ReleaseSysCacheList(catlist);
713 /* ---------- AMPROC CACHES ---------- */
717 * Get the OID of the specified support function
718 * for the specified opfamily and datatypes.
720 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
723 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
726 Form_pg_amproc amproc_tup;
729 tp = SearchSysCache4(AMPROCNUM,
730 ObjectIdGetDatum(opfamily),
731 ObjectIdGetDatum(lefttype),
732 ObjectIdGetDatum(righttype),
733 Int16GetDatum(procnum));
734 if (!HeapTupleIsValid(tp))
736 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
737 result = amproc_tup->amproc;
743 /* ---------- ATTRIBUTE CACHES ---------- */
747 * Given the relation id and the attribute number,
748 * return the "attname" field from the attribute relation.
750 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
753 get_attname(Oid relid, AttrNumber attnum)
757 tp = SearchSysCache2(ATTNUM,
758 ObjectIdGetDatum(relid),
759 Int16GetDatum(attnum));
760 if (HeapTupleIsValid(tp))
762 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
765 result = pstrdup(NameStr(att_tup->attname));
774 * get_relid_attribute_name
776 * Same as above routine get_attname(), except that error
777 * is handled by elog() instead of returning NULL.
780 get_relid_attribute_name(Oid relid, AttrNumber attnum)
784 attname = get_attname(relid, attnum);
786 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
794 * Given the relation id and the attribute name,
795 * return the "attnum" field from the attribute relation.
797 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
800 get_attnum(Oid relid, const char *attname)
804 tp = SearchSysCacheAttName(relid, attname);
805 if (HeapTupleIsValid(tp))
807 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
810 result = att_tup->attnum;
815 return InvalidAttrNumber;
821 * Given the relation OID and the attribute number with the relation,
822 * return the attribute type OID.
825 get_atttype(Oid relid, AttrNumber attnum)
829 tp = SearchSysCache2(ATTNUM,
830 ObjectIdGetDatum(relid),
831 Int16GetDatum(attnum));
832 if (HeapTupleIsValid(tp))
834 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
837 result = att_tup->atttypid;
848 * Given the relation id and the attribute number,
849 * return the "atttypmod" field from the attribute relation.
852 get_atttypmod(Oid relid, AttrNumber attnum)
856 tp = SearchSysCache2(ATTNUM,
857 ObjectIdGetDatum(relid),
858 Int16GetDatum(attnum));
859 if (HeapTupleIsValid(tp))
861 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
864 result = att_tup->atttypmod;
875 * A two-fer: given the relation id and the attribute number,
876 * fetch both type OID and atttypmod in a single cache lookup.
878 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
879 * raises an error if it can't obtain the information.
882 get_atttypetypmod(Oid relid, AttrNumber attnum,
883 Oid *typid, int32 *typmod)
886 Form_pg_attribute att_tup;
888 tp = SearchSysCache2(ATTNUM,
889 ObjectIdGetDatum(relid),
890 Int16GetDatum(attnum));
891 if (!HeapTupleIsValid(tp))
892 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
894 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
896 *typid = att_tup->atttypid;
897 *typmod = att_tup->atttypmod;
901 /* ---------- CONSTRAINT CACHE ---------- */
904 * get_constraint_name
905 * Returns the name of a given pg_constraint entry.
907 * Returns a palloc'd copy of the string, or NULL if no such constraint.
909 * NOTE: since constraint name is not unique, be wary of code that uses this
910 * for anything except preparing error messages.
913 get_constraint_name(Oid conoid)
917 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
918 if (HeapTupleIsValid(tp))
920 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
923 result = pstrdup(NameStr(contup->conname));
931 /* ---------- OPCLASS CACHE ---------- */
936 * Returns the OID of the operator family the opclass belongs to.
939 get_opclass_family(Oid opclass)
942 Form_pg_opclass cla_tup;
945 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
946 if (!HeapTupleIsValid(tp))
947 elog(ERROR, "cache lookup failed for opclass %u", opclass);
948 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
950 result = cla_tup->opcfamily;
956 * get_opclass_input_type
958 * Returns the OID of the datatype the opclass indexes.
961 get_opclass_input_type(Oid opclass)
964 Form_pg_opclass cla_tup;
967 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
968 if (!HeapTupleIsValid(tp))
969 elog(ERROR, "cache lookup failed for opclass %u", opclass);
970 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
972 result = cla_tup->opcintype;
977 /* ---------- OPERATOR CACHE ---------- */
982 * Returns the regproc id of the routine used to implement an
983 * operator given the operator oid.
990 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
991 if (HeapTupleIsValid(tp))
993 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
996 result = optup->oprcode;
1001 return (RegProcedure) InvalidOid;
1006 * returns the name of the operator with the given opno
1008 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1011 get_opname(Oid opno)
1015 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1016 if (HeapTupleIsValid(tp))
1018 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1021 result = pstrdup(NameStr(optup->oprname));
1022 ReleaseSysCache(tp);
1032 * Returns the left and right input datatypes for an operator
1033 * (InvalidOid if not relevant).
1036 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1039 Form_pg_operator optup;
1041 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1042 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1043 elog(ERROR, "cache lookup failed for operator %u", opno);
1044 optup = (Form_pg_operator) GETSTRUCT(tp);
1045 *lefttype = optup->oprleft;
1046 *righttype = optup->oprright;
1047 ReleaseSysCache(tp);
1053 * Returns true if the operator is potentially mergejoinable. (The planner
1054 * will fail to find any mergejoin plans unless there are suitable btree
1055 * opfamily entries for this operator and associated sortops. The pg_operator
1056 * flag is just a hint to tell the planner whether to bother looking.)
1059 op_mergejoinable(Oid opno)
1062 bool result = false;
1064 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1065 if (HeapTupleIsValid(tp))
1067 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1069 result = optup->oprcanmerge;
1070 ReleaseSysCache(tp);
1078 * Returns true if the operator is hashjoinable. (There must be a suitable
1079 * hash opfamily entry for this operator if it is so marked.)
1082 op_hashjoinable(Oid opno)
1085 bool result = false;
1087 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1088 if (HeapTupleIsValid(tp))
1090 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1092 result = optup->oprcanhash;
1093 ReleaseSysCache(tp);
1101 * Get the proisstrict flag for the operator's underlying function.
1106 RegProcedure funcid = get_opcode(opno);
1108 if (funcid == (RegProcedure) InvalidOid)
1109 elog(ERROR, "operator %u does not exist", opno);
1111 return func_strict((Oid) funcid);
1117 * Get the provolatile flag for the operator's underlying function.
1120 op_volatile(Oid opno)
1122 RegProcedure funcid = get_opcode(opno);
1124 if (funcid == (RegProcedure) InvalidOid)
1125 elog(ERROR, "operator %u does not exist", opno);
1127 return func_volatile((Oid) funcid);
1133 * Returns the corresponding commutator of an operator.
1136 get_commutator(Oid opno)
1140 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1141 if (HeapTupleIsValid(tp))
1143 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1146 result = optup->oprcom;
1147 ReleaseSysCache(tp);
1157 * Returns the corresponding negator of an operator.
1160 get_negator(Oid opno)
1164 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1165 if (HeapTupleIsValid(tp))
1167 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1170 result = optup->oprnegate;
1171 ReleaseSysCache(tp);
1181 * Returns procedure id for computing selectivity of an operator.
1184 get_oprrest(Oid opno)
1188 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1189 if (HeapTupleIsValid(tp))
1191 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1192 RegProcedure result;
1194 result = optup->oprrest;
1195 ReleaseSysCache(tp);
1199 return (RegProcedure) InvalidOid;
1205 * Returns procedure id for computing selectivity of a join.
1208 get_oprjoin(Oid opno)
1212 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1213 if (HeapTupleIsValid(tp))
1215 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1216 RegProcedure result;
1218 result = optup->oprjoin;
1219 ReleaseSysCache(tp);
1223 return (RegProcedure) InvalidOid;
1226 /* ---------- FUNCTION CACHE ---------- */
1230 * returns the name of the function with the given funcid
1232 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1235 get_func_name(Oid funcid)
1239 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1240 if (HeapTupleIsValid(tp))
1242 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1245 result = pstrdup(NameStr(functup->proname));
1246 ReleaseSysCache(tp);
1254 * get_func_namespace
1256 * Returns the pg_namespace OID associated with a given function.
1259 get_func_namespace(Oid funcid)
1263 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1264 if (HeapTupleIsValid(tp))
1266 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1269 result = functup->pronamespace;
1270 ReleaseSysCache(tp);
1279 * Given procedure id, return the function's result type.
1282 get_func_rettype(Oid funcid)
1287 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1288 if (!HeapTupleIsValid(tp))
1289 elog(ERROR, "cache lookup failed for function %u", funcid);
1291 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1292 ReleaseSysCache(tp);
1298 * Given procedure id, return the number of arguments.
1301 get_func_nargs(Oid funcid)
1306 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1307 if (!HeapTupleIsValid(tp))
1308 elog(ERROR, "cache lookup failed for function %u", funcid);
1310 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1311 ReleaseSysCache(tp);
1316 * get_func_signature
1317 * Given procedure id, return the function's argument and result types.
1318 * (The return value is the result type.)
1320 * The arguments are returned as a palloc'd array.
1323 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1326 Form_pg_proc procstruct;
1329 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1330 if (!HeapTupleIsValid(tp))
1331 elog(ERROR, "cache lookup failed for function %u", funcid);
1333 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1335 result = procstruct->prorettype;
1336 *nargs = (int) procstruct->pronargs;
1337 Assert(*nargs == procstruct->proargtypes.dim1);
1338 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1339 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1341 ReleaseSysCache(tp);
1347 * Given procedure id, return the function's proretset flag.
1350 get_func_retset(Oid funcid)
1355 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1356 if (!HeapTupleIsValid(tp))
1357 elog(ERROR, "cache lookup failed for function %u", funcid);
1359 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1360 ReleaseSysCache(tp);
1366 * Given procedure id, return the function's proisstrict flag.
1369 func_strict(Oid funcid)
1374 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1375 if (!HeapTupleIsValid(tp))
1376 elog(ERROR, "cache lookup failed for function %u", funcid);
1378 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1379 ReleaseSysCache(tp);
1385 * Given procedure id, return the function's provolatile flag.
1388 func_volatile(Oid funcid)
1393 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1394 if (!HeapTupleIsValid(tp))
1395 elog(ERROR, "cache lookup failed for function %u", funcid);
1397 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1398 ReleaseSysCache(tp);
1404 * Given procedure id, return the function's procost field.
1407 get_func_cost(Oid funcid)
1412 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1413 if (!HeapTupleIsValid(tp))
1414 elog(ERROR, "cache lookup failed for function %u", funcid);
1416 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1417 ReleaseSysCache(tp);
1423 * Given procedure id, return the function's prorows field.
1426 get_func_rows(Oid funcid)
1431 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1432 if (!HeapTupleIsValid(tp))
1433 elog(ERROR, "cache lookup failed for function %u", funcid);
1435 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1436 ReleaseSysCache(tp);
1440 /* ---------- RELATION CACHE ---------- */
1444 * Given name and namespace of a relation, look up the OID.
1446 * Returns InvalidOid if there is no such relation.
1449 get_relname_relid(const char *relname, Oid relnamespace)
1451 return GetSysCacheOid2(RELNAMENSP,
1452 PointerGetDatum(relname),
1453 ObjectIdGetDatum(relnamespace));
1460 * Returns the number of attributes for a given relation.
1463 get_relnatts(Oid relid)
1467 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1468 if (HeapTupleIsValid(tp))
1470 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1473 result = reltup->relnatts;
1474 ReleaseSysCache(tp);
1478 return InvalidAttrNumber;
1484 * Returns the name of a given relation.
1486 * Returns a palloc'd copy of the string, or NULL if no such relation.
1488 * NOTE: since relation name is not unique, be wary of code that uses this
1489 * for anything except preparing error messages.
1492 get_rel_name(Oid relid)
1496 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1497 if (HeapTupleIsValid(tp))
1499 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1502 result = pstrdup(NameStr(reltup->relname));
1503 ReleaseSysCache(tp);
1513 * Returns the pg_namespace OID associated with a given relation.
1516 get_rel_namespace(Oid relid)
1520 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1521 if (HeapTupleIsValid(tp))
1523 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1526 result = reltup->relnamespace;
1527 ReleaseSysCache(tp);
1537 * Returns the pg_type OID associated with a given relation.
1539 * Note: not all pg_class entries have associated pg_type OIDs; so be
1540 * careful to check for InvalidOid result.
1543 get_rel_type_id(Oid relid)
1547 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1548 if (HeapTupleIsValid(tp))
1550 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1553 result = reltup->reltype;
1554 ReleaseSysCache(tp);
1564 * Returns the relkind associated with a given relation.
1567 get_rel_relkind(Oid relid)
1571 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1572 if (HeapTupleIsValid(tp))
1574 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1577 result = reltup->relkind;
1578 ReleaseSysCache(tp);
1586 * get_rel_tablespace
1588 * Returns the pg_tablespace OID associated with a given relation.
1590 * Note: InvalidOid might mean either that we couldn't find the relation,
1591 * or that it is in the database's default tablespace.
1594 get_rel_tablespace(Oid relid)
1598 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1599 if (HeapTupleIsValid(tp))
1601 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1604 result = reltup->reltablespace;
1605 ReleaseSysCache(tp);
1613 /* ---------- TYPE CACHE ---------- */
1618 * Given the type OID, determine whether the type is defined
1619 * (if not, it's only a shell).
1622 get_typisdefined(Oid typid)
1626 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1627 if (HeapTupleIsValid(tp))
1629 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1632 result = typtup->typisdefined;
1633 ReleaseSysCache(tp);
1643 * Given the type OID, return the length of the type.
1646 get_typlen(Oid typid)
1650 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1651 if (HeapTupleIsValid(tp))
1653 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1656 result = typtup->typlen;
1657 ReleaseSysCache(tp);
1667 * Given the type OID, determine whether the type is returned by value or
1668 * not. Returns true if by value, false if by reference.
1671 get_typbyval(Oid typid)
1675 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1676 if (HeapTupleIsValid(tp))
1678 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1681 result = typtup->typbyval;
1682 ReleaseSysCache(tp);
1692 * A two-fer: given the type OID, return both typlen and typbyval.
1694 * Since both pieces of info are needed to know how to copy a Datum,
1695 * many places need both. Might as well get them with one cache lookup
1696 * instead of two. Also, this routine raises an error instead of
1697 * returning a bogus value when given a bad type OID.
1700 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1703 Form_pg_type typtup;
1705 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1706 if (!HeapTupleIsValid(tp))
1707 elog(ERROR, "cache lookup failed for type %u", typid);
1708 typtup = (Form_pg_type) GETSTRUCT(tp);
1709 *typlen = typtup->typlen;
1710 *typbyval = typtup->typbyval;
1711 ReleaseSysCache(tp);
1715 * get_typlenbyvalalign
1717 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1720 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1724 Form_pg_type typtup;
1726 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1727 if (!HeapTupleIsValid(tp))
1728 elog(ERROR, "cache lookup failed for type %u", typid);
1729 typtup = (Form_pg_type) GETSTRUCT(tp);
1730 *typlen = typtup->typlen;
1731 *typbyval = typtup->typbyval;
1732 *typalign = typtup->typalign;
1733 ReleaseSysCache(tp);
1738 * Given a pg_type row, select the type OID to pass to I/O functions
1740 * Formerly, all I/O functions were passed pg_type.typelem as their second
1741 * parameter, but we now have a more complex rule about what to pass.
1742 * This knowledge is intended to be centralized here --- direct references
1743 * to typelem elsewhere in the code are wrong, if they are associated with
1744 * I/O calls and not with actual subscripting operations! (But see
1745 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1747 * As of PostgreSQL 8.1, output functions receive only the value itself
1748 * and not any auxiliary parameters, so the name of this routine is now
1749 * a bit of a misnomer ... it should be getTypeInputParam.
1752 getTypeIOParam(HeapTuple typeTuple)
1754 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1757 * Array types get their typelem as parameter; everybody else gets their
1758 * own type OID as parameter. (As of 8.2, domains must get their own OID
1759 * even if their base type is an array.)
1761 if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem))
1762 return typeStruct->typelem;
1764 return HeapTupleGetOid(typeTuple);
1770 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1771 * typdelim, typioparam, and IO function OID. The IO function
1772 * returned is controlled by IOFuncSelector
1775 get_type_io_data(Oid typid,
1776 IOFuncSelector which_func,
1784 HeapTuple typeTuple;
1785 Form_pg_type typeStruct;
1788 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1789 * use array_in and array_out during bootstrap.
1791 if (IsBootstrapProcessingMode())
1796 boot_get_type_io_data(typid,
1813 elog(ERROR, "binary I/O not supported during bootstrap");
1819 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1820 if (!HeapTupleIsValid(typeTuple))
1821 elog(ERROR, "cache lookup failed for type %u", typid);
1822 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1824 *typlen = typeStruct->typlen;
1825 *typbyval = typeStruct->typbyval;
1826 *typalign = typeStruct->typalign;
1827 *typdelim = typeStruct->typdelim;
1828 *typioparam = getTypeIOParam(typeTuple);
1832 *func = typeStruct->typinput;
1835 *func = typeStruct->typoutput;
1837 case IOFunc_receive:
1838 *func = typeStruct->typreceive;
1841 *func = typeStruct->typsend;
1844 ReleaseSysCache(typeTuple);
1849 get_typalign(Oid typid)
1853 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1854 if (HeapTupleIsValid(tp))
1856 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1859 result = typtup->typalign;
1860 ReleaseSysCache(tp);
1869 get_typstorage(Oid typid)
1873 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1874 if (HeapTupleIsValid(tp))
1876 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1879 result = typtup->typstorage;
1880 ReleaseSysCache(tp);
1889 * Given a type OID, return the type's default value, if any.
1891 * The result is a palloc'd expression node tree, or NULL if there
1892 * is no defined default for the datatype.
1894 * NB: caller should be prepared to coerce result to correct datatype;
1895 * the returned expression tree might produce something of the wrong type.
1898 get_typdefault(Oid typid)
1900 HeapTuple typeTuple;
1906 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1907 if (!HeapTupleIsValid(typeTuple))
1908 elog(ERROR, "cache lookup failed for type %u", typid);
1909 type = (Form_pg_type) GETSTRUCT(typeTuple);
1912 * typdefault and typdefaultbin are potentially null, so don't try to
1913 * access 'em as struct fields. Must do it the hard way with
1916 datum = SysCacheGetAttr(TYPEOID,
1918 Anum_pg_type_typdefaultbin,
1923 /* We have an expression default */
1924 expr = stringToNode(TextDatumGetCString(datum));
1928 /* Perhaps we have a plain literal default */
1929 datum = SysCacheGetAttr(TYPEOID,
1931 Anum_pg_type_typdefault,
1936 char *strDefaultVal;
1938 /* Convert text datum to C string */
1939 strDefaultVal = TextDatumGetCString(datum);
1940 /* Convert C string to a value of the given type */
1941 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
1942 getTypeIOParam(typeTuple), -1);
1943 /* Build a Const node containing the value */
1944 expr = (Node *) makeConst(typid,
1950 pfree(strDefaultVal);
1959 ReleaseSysCache(typeTuple);
1966 * If the given type is a domain, return its base type;
1967 * otherwise return the type's own OID.
1970 getBaseType(Oid typid)
1974 return getBaseTypeAndTypmod(typid, &typmod);
1978 * getBaseTypeAndTypmod
1979 * If the given type is a domain, return its base type and typmod;
1980 * otherwise return the type's own OID, and leave *typmod unchanged.
1982 * Note that the "applied typmod" should be -1 for every domain level
1983 * above the bottommost; therefore, if the passed-in typid is indeed
1984 * a domain, *typmod should be -1.
1987 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
1990 * We loop to find the bottom base type in a stack of domains.
1995 Form_pg_type typTup;
1997 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1998 if (!HeapTupleIsValid(tup))
1999 elog(ERROR, "cache lookup failed for type %u", typid);
2000 typTup = (Form_pg_type) GETSTRUCT(tup);
2001 if (typTup->typtype != TYPTYPE_DOMAIN)
2003 /* Not a domain, so done */
2004 ReleaseSysCache(tup);
2008 Assert(*typmod == -1);
2009 typid = typTup->typbasetype;
2010 *typmod = typTup->typtypmod;
2012 ReleaseSysCache(tup);
2021 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2022 * estimate the average width of values of the type. This is used by
2023 * the planner, which doesn't require absolutely correct results;
2024 * it's OK (and expected) to guess if we don't know for sure.
2027 get_typavgwidth(Oid typid, int32 typmod)
2029 int typlen = get_typlen(typid);
2033 * Easy if it's a fixed-width type
2039 * type_maximum_size knows the encoding of typmod for some datatypes;
2040 * don't duplicate that knowledge here.
2042 maxwidth = type_maximum_size(typid, typmod);
2046 * For BPCHAR, the max width is also the only width. Otherwise we
2047 * need to guess about the typical data width given the max. A sliding
2048 * scale for percentage of max width seems reasonable.
2050 if (typid == BPCHAROID)
2053 return maxwidth; /* assume full width */
2054 if (maxwidth < 1000)
2055 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2058 * Beyond 1000, assume we're looking at something like
2059 * "varchar(10000)" where the limit isn't actually reached often, and
2060 * use a fixed estimate.
2062 return 32 + (1000 - 32) / 2;
2066 * Ooops, we have no idea ... wild guess time.
2074 * Given the type OID, find if it is a basic type, a complex type, etc.
2075 * It returns the null char if the cache lookup fails...
2078 get_typtype(Oid typid)
2082 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2083 if (HeapTupleIsValid(tp))
2085 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2088 result = typtup->typtype;
2089 ReleaseSysCache(tp);
2099 * Convenience function to determine whether a type OID represents
2100 * a "rowtype" type --- either RECORD or a named composite type.
2103 type_is_rowtype(Oid typid)
2105 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2110 * Returns true if the given type is an enum type.
2113 type_is_enum(Oid typid)
2115 return (get_typtype(typid) == TYPTYPE_ENUM);
2119 * get_type_category_preferred
2121 * Given the type OID, fetch its category and preferred-type status.
2122 * Throws error on failure.
2125 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2128 Form_pg_type typtup;
2130 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2131 if (!HeapTupleIsValid(tp))
2132 elog(ERROR, "cache lookup failed for type %u", typid);
2133 typtup = (Form_pg_type) GETSTRUCT(tp);
2134 *typcategory = typtup->typcategory;
2135 *typispreferred = typtup->typispreferred;
2136 ReleaseSysCache(tp);
2142 * Given the type OID, get the typrelid (InvalidOid if not a complex
2146 get_typ_typrelid(Oid typid)
2150 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2151 if (HeapTupleIsValid(tp))
2153 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2156 result = typtup->typrelid;
2157 ReleaseSysCache(tp);
2167 * Given the type OID, get the typelem (InvalidOid if not an array type).
2169 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2170 * returned if the input is a fixed-length array type.
2173 get_element_type(Oid typid)
2177 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2178 if (HeapTupleIsValid(tp))
2180 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2183 if (typtup->typlen == -1)
2184 result = typtup->typelem;
2186 result = InvalidOid;
2187 ReleaseSysCache(tp);
2197 * Given the type OID, get the corresponding "true" array type.
2198 * Returns InvalidOid if no array type can be found.
2201 get_array_type(Oid typid)
2204 Oid result = InvalidOid;
2206 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2207 if (HeapTupleIsValid(tp))
2209 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2210 ReleaseSysCache(tp);
2218 * Get info needed for converting values of a type to internal form
2221 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2223 HeapTuple typeTuple;
2226 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2227 if (!HeapTupleIsValid(typeTuple))
2228 elog(ERROR, "cache lookup failed for type %u", type);
2229 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2231 if (!pt->typisdefined)
2233 (errcode(ERRCODE_UNDEFINED_OBJECT),
2234 errmsg("type %s is only a shell",
2235 format_type_be(type))));
2236 if (!OidIsValid(pt->typinput))
2238 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2239 errmsg("no input function available for type %s",
2240 format_type_be(type))));
2242 *typInput = pt->typinput;
2243 *typIOParam = getTypeIOParam(typeTuple);
2245 ReleaseSysCache(typeTuple);
2251 * Get info needed for printing values of a type
2254 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2256 HeapTuple typeTuple;
2259 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2260 if (!HeapTupleIsValid(typeTuple))
2261 elog(ERROR, "cache lookup failed for type %u", type);
2262 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2264 if (!pt->typisdefined)
2266 (errcode(ERRCODE_UNDEFINED_OBJECT),
2267 errmsg("type %s is only a shell",
2268 format_type_be(type))));
2269 if (!OidIsValid(pt->typoutput))
2271 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2272 errmsg("no output function available for type %s",
2273 format_type_be(type))));
2275 *typOutput = pt->typoutput;
2276 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2278 ReleaseSysCache(typeTuple);
2282 * getTypeBinaryInputInfo
2284 * Get info needed for binary input of values of a type
2287 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2289 HeapTuple typeTuple;
2292 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2293 if (!HeapTupleIsValid(typeTuple))
2294 elog(ERROR, "cache lookup failed for type %u", type);
2295 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2297 if (!pt->typisdefined)
2299 (errcode(ERRCODE_UNDEFINED_OBJECT),
2300 errmsg("type %s is only a shell",
2301 format_type_be(type))));
2302 if (!OidIsValid(pt->typreceive))
2304 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2305 errmsg("no binary input function available for type %s",
2306 format_type_be(type))));
2308 *typReceive = pt->typreceive;
2309 *typIOParam = getTypeIOParam(typeTuple);
2311 ReleaseSysCache(typeTuple);
2315 * getTypeBinaryOutputInfo
2317 * Get info needed for binary output of values of a type
2320 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2322 HeapTuple typeTuple;
2325 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2326 if (!HeapTupleIsValid(typeTuple))
2327 elog(ERROR, "cache lookup failed for type %u", type);
2328 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2330 if (!pt->typisdefined)
2332 (errcode(ERRCODE_UNDEFINED_OBJECT),
2333 errmsg("type %s is only a shell",
2334 format_type_be(type))));
2335 if (!OidIsValid(pt->typsend))
2337 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2338 errmsg("no binary output function available for type %s",
2339 format_type_be(type))));
2341 *typSend = pt->typsend;
2342 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2344 ReleaseSysCache(typeTuple);
2350 * Given the type OID, return the type's typmodin procedure, if any.
2353 get_typmodin(Oid typid)
2357 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2358 if (HeapTupleIsValid(tp))
2360 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2363 result = typtup->typmodin;
2364 ReleaseSysCache(tp);
2375 * Given the type OID, return the type's typmodout procedure, if any.
2378 get_typmodout(Oid typid)
2382 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2383 if (HeapTupleIsValid(tp))
2385 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2388 result = typtup->typmodout;
2389 ReleaseSysCache(tp);
2395 #endif /* NOT_USED */
2398 /* ---------- STATISTICS CACHE ---------- */
2403 * Given the table and attribute number of a column, get the average
2404 * width of entries in the column. Return zero if no data available.
2406 * Currently this is only consulted for individual tables, not for inheritance
2407 * trees, so we don't need an "inh" parameter.
2409 * Calling a hook at this point looks somewhat strange, but is required
2410 * because the optimizer calls this function without any other way for
2411 * plug-ins to control the result.
2414 get_attavgwidth(Oid relid, AttrNumber attnum)
2419 if (get_attavgwidth_hook)
2421 stawidth = (*get_attavgwidth_hook) (relid, attnum);
2425 tp = SearchSysCache3(STATRELATTINH,
2426 ObjectIdGetDatum(relid),
2427 Int16GetDatum(attnum),
2428 BoolGetDatum(false));
2429 if (HeapTupleIsValid(tp))
2431 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2432 ReleaseSysCache(tp);
2442 * Extract the contents of a "slot" of a pg_statistic tuple.
2443 * Returns TRUE if requested slot type was found, else FALSE.
2445 * Unlike other routines in this file, this takes a pointer to an
2446 * already-looked-up tuple in the pg_statistic cache. We do this since
2447 * most callers will want to extract more than one value from the cache
2448 * entry, and we don't want to repeat the cache lookup unnecessarily.
2449 * Also, this API allows this routine to be used with statistics tuples
2450 * that have been provided by a stats hook and didn't really come from
2453 * statstuple: pg_statistics tuple to be examined.
2454 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2455 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2456 * reqkind: STAKIND code for desired statistics slot kind.
2457 * reqop: STAOP value wanted, or InvalidOid if don't care.
2458 * actualop: if not NULL, *actualop receives the actual STAOP value.
2459 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2460 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2462 * If assigned, values and numbers are set to point to palloc'd arrays.
2463 * If the attribute type is pass-by-reference, the values referenced by
2464 * the values array are themselves palloc'd. The palloc'd stuff can be
2465 * freed by calling free_attstatsslot.
2467 * Note: at present, atttype/atttypmod aren't actually used here at all.
2468 * But the caller must have the correct (or at least binary-compatible)
2469 * type ID to pass to free_attstatsslot later.
2472 get_attstatsslot(HeapTuple statstuple,
2473 Oid atttype, int32 atttypmod,
2474 int reqkind, Oid reqop,
2476 Datum **values, int *nvalues,
2477 float4 **numbers, int *nnumbers)
2479 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2484 ArrayType *statarray;
2487 HeapTuple typeTuple;
2488 Form_pg_type typeForm;
2490 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2492 if ((&stats->stakind1)[i] == reqkind &&
2493 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2496 if (i >= STATISTIC_NUM_SLOTS)
2497 return false; /* not there */
2500 *actualop = (&stats->staop1)[i];
2504 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2505 Anum_pg_statistic_stavalues1 + i,
2508 elog(ERROR, "stavalues is null");
2509 statarray = DatumGetArrayTypeP(val);
2512 * Need to get info about the array element type. We look at the
2513 * actual element type embedded in the array, which might be only
2514 * binary-compatible with the passed-in atttype. The info we
2515 * extract here should be the same either way, but deconstruct_array
2516 * is picky about having an exact type OID match.
2518 arrayelemtype = ARR_ELEMTYPE(statarray);
2519 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
2520 if (!HeapTupleIsValid(typeTuple))
2521 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
2522 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2524 /* Deconstruct array into Datum elements; NULLs not expected */
2525 deconstruct_array(statarray,
2530 values, NULL, nvalues);
2533 * If the element type is pass-by-reference, we now have a bunch of
2534 * Datums that are pointers into the syscache value. Copy them to
2535 * avoid problems if syscache decides to drop the entry.
2537 if (!typeForm->typbyval)
2539 for (j = 0; j < *nvalues; j++)
2541 (*values)[j] = datumCopy((*values)[j],
2547 ReleaseSysCache(typeTuple);
2550 * Free statarray if it's a detoasted copy.
2552 if ((Pointer) statarray != DatumGetPointer(val))
2558 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2559 Anum_pg_statistic_stanumbers1 + i,
2562 elog(ERROR, "stanumbers is null");
2563 statarray = DatumGetArrayTypeP(val);
2566 * We expect the array to be a 1-D float4 array; verify that. We don't
2567 * need to use deconstruct_array() since the array data is just going
2568 * to look like a C array of float4 values.
2570 narrayelem = ARR_DIMS(statarray)[0];
2571 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2572 ARR_HASNULL(statarray) ||
2573 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2574 elog(ERROR, "stanumbers is not a 1-D float4 array");
2575 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2576 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2577 *nnumbers = narrayelem;
2580 * Free statarray if it's a detoasted copy.
2582 if ((Pointer) statarray != DatumGetPointer(val))
2591 * Free data allocated by get_attstatsslot
2593 * atttype need be valid only if values != NULL.
2596 free_attstatsslot(Oid atttype,
2597 Datum *values, int nvalues,
2598 float4 *numbers, int nnumbers)
2602 if (!get_typbyval(atttype))
2606 for (i = 0; i < nvalues; i++)
2607 pfree(DatumGetPointer(values[i]));
2615 /* ---------- PG_NAMESPACE CACHE ---------- */
2618 * get_namespace_name
2619 * Returns the name of a given namespace
2621 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2624 get_namespace_name(Oid nspid)
2628 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
2629 if (HeapTupleIsValid(tp))
2631 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2634 result = pstrdup(NameStr(nsptup->nspname));
2635 ReleaseSysCache(tp);
2642 /* ---------- PG_AUTHID CACHE ---------- */
2646 * Given a role name, look up the role's OID.
2647 * Returns InvalidOid if no such role.
2650 get_roleid(const char *rolname)
2652 return GetSysCacheOid1(AUTHNAME, PointerGetDatum(rolname));
2656 * get_roleid_checked
2657 * Given a role name, look up the role's OID.
2658 * ereports if no such role.
2661 get_roleid_checked(const char *rolname)
2665 roleid = get_roleid(rolname);
2666 if (!OidIsValid(roleid))
2668 (errcode(ERRCODE_UNDEFINED_OBJECT),
2669 errmsg("role \"%s\" does not exist", rolname)));