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.149 2007/03/17 00:11:05 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"
39 /* ---------- AMOP CACHES ---------- */
44 * Return t iff operator 'opno' is in operator family 'opfamily'.
47 op_in_opfamily(Oid opno, Oid opfamily)
49 return SearchSysCacheExists(AMOPOPID,
50 ObjectIdGetDatum(opno),
51 ObjectIdGetDatum(opfamily),
56 * get_op_opfamily_strategy
58 * Get the operator's strategy number within the specified opfamily,
59 * or 0 if it's not a member of the opfamily.
62 get_op_opfamily_strategy(Oid opno, Oid opfamily)
65 Form_pg_amop amop_tup;
68 tp = SearchSysCache(AMOPOPID,
69 ObjectIdGetDatum(opno),
70 ObjectIdGetDatum(opfamily),
72 if (!HeapTupleIsValid(tp))
74 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
75 result = amop_tup->amopstrategy;
81 * get_op_opfamily_properties
83 * Get the operator's strategy number, input types, and recheck (lossy)
84 * flag within the specified opfamily.
86 * Caller should already have verified that opno is a member of opfamily,
87 * therefore we raise an error if the tuple is not found.
90 get_op_opfamily_properties(Oid opno, Oid opfamily,
97 Form_pg_amop amop_tup;
99 tp = SearchSysCache(AMOPOPID,
100 ObjectIdGetDatum(opno),
101 ObjectIdGetDatum(opfamily),
103 if (!HeapTupleIsValid(tp))
104 elog(ERROR, "operator %u is not a member of opfamily %u",
106 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
107 *strategy = amop_tup->amopstrategy;
108 *lefttype = amop_tup->amoplefttype;
109 *righttype = amop_tup->amoprighttype;
110 *recheck = amop_tup->amopreqcheck;
115 * get_opfamily_member
116 * Get the OID of the operator that implements the specified strategy
117 * with the specified datatypes for the specified opfamily.
119 * Returns InvalidOid if there is no pg_amop entry for the given keys.
122 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
126 Form_pg_amop amop_tup;
129 tp = SearchSysCache(AMOPSTRATEGY,
130 ObjectIdGetDatum(opfamily),
131 ObjectIdGetDatum(lefttype),
132 ObjectIdGetDatum(righttype),
133 Int16GetDatum(strategy));
134 if (!HeapTupleIsValid(tp))
136 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
137 result = amop_tup->amopopr;
143 * get_ordering_op_properties
144 * Given the OID of an ordering operator (a btree "<" or ">" operator),
145 * determine its opfamily, its declared input datatype, and its
146 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
148 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
149 * (This indicates that the operator is not a valid ordering operator.)
151 * Note: the operator could be registered in multiple families, for example
152 * if someone were to build a "reverse sort" opfamily. This would result in
153 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
154 * or NULLS LAST, as well as inefficient planning due to failure to match up
155 * pathkeys that should be the same. So we want a determinate result here.
156 * Because of the way the syscache search works, we'll use the interpretation
157 * associated with the opfamily with smallest OID, which is probably
158 * determinate enough. Since there is no longer any particularly good reason
159 * to build reverse-sort opfamilies, it doesn't seem worth expending any
160 * additional effort on ensuring consistency.
163 get_ordering_op_properties(Oid opno,
164 Oid *opfamily, Oid *opcintype, int16 *strategy)
170 /* ensure outputs are initialized on failure */
171 *opfamily = InvalidOid;
172 *opcintype = InvalidOid;
176 * Search pg_amop to see if the target operator is registered as the "<"
177 * or ">" operator of any btree opfamily.
179 catlist = SearchSysCacheList(AMOPOPID, 1,
180 ObjectIdGetDatum(opno),
183 for (i = 0; i < catlist->n_members; i++)
185 HeapTuple tuple = &catlist->members[i]->tuple;
186 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
189 if (aform->amopmethod != BTREE_AM_OID)
192 if (aform->amopstrategy == BTLessStrategyNumber ||
193 aform->amopstrategy == BTGreaterStrategyNumber)
195 /* Found it ... should have consistent input types */
196 if (aform->amoplefttype == aform->amoprighttype)
198 /* Found a suitable opfamily, return info */
199 *opfamily = aform->amopfamily;
200 *opcintype = aform->amoplefttype;
201 *strategy = aform->amopstrategy;
208 ReleaseSysCacheList(catlist);
214 * get_compare_function_for_ordering_op
215 * Get the OID of the datatype-specific btree comparison function
216 * associated with an ordering operator (a "<" or ">" operator).
218 * *cmpfunc receives the comparison function OID.
219 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
220 * (indicating the comparison result must be negated before use).
222 * Returns TRUE if successful, FALSE if no btree function can be found.
223 * (This indicates that the operator is not a valid ordering operator.)
226 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
232 /* Find the operator in pg_amop */
233 if (get_ordering_op_properties(opno,
234 &opfamily, &opcintype, &strategy))
236 /* Found a suitable opfamily, get matching support function */
237 *cmpfunc = get_opfamily_proc(opfamily,
241 if (!OidIsValid(*cmpfunc)) /* should not happen */
242 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
243 BTORDER_PROC, opcintype, opcintype, opfamily);
244 *reverse = (strategy == BTGreaterStrategyNumber);
248 /* ensure outputs are set on failure */
249 *cmpfunc = InvalidOid;
255 * get_equality_op_for_ordering_op
256 * Get the OID of the datatype-specific btree equality operator
257 * associated with an ordering operator (a "<" or ">" operator).
259 * Returns InvalidOid if no matching equality operator can be found.
260 * (This indicates that the operator is not a valid ordering operator.)
263 get_equality_op_for_ordering_op(Oid opno)
265 Oid result = InvalidOid;
270 /* Find the operator in pg_amop */
271 if (get_ordering_op_properties(opno,
272 &opfamily, &opcintype, &strategy))
274 /* Found a suitable opfamily, get matching equality operator */
275 result = get_opfamily_member(opfamily,
278 BTEqualStrategyNumber);
285 * get_ordering_op_for_equality_op
286 * Get the OID of a datatype-specific btree ordering operator
287 * associated with an equality operator. (If there are multiple
288 * possibilities, assume any one will do.)
290 * This function is used when we have to sort data before unique-ifying,
291 * and don't much care which sorting op is used as long as it's compatible
292 * with the intended equality operator. Since we need a sorting operator,
293 * it should be single-data-type even if the given operator is cross-type.
294 * The caller specifies whether to find an op for the LHS or RHS data type.
296 * Returns InvalidOid if no matching ordering operator can be found.
299 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
301 Oid result = InvalidOid;
306 * Search pg_amop to see if the target operator is registered as the "="
307 * operator of any btree opfamily.
309 catlist = SearchSysCacheList(AMOPOPID, 1,
310 ObjectIdGetDatum(opno),
313 for (i = 0; i < catlist->n_members; i++)
315 HeapTuple tuple = &catlist->members[i]->tuple;
316 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
319 if (aform->amopmethod != BTREE_AM_OID)
322 if (aform->amopstrategy == BTEqualStrategyNumber)
324 /* Found a suitable opfamily, get matching ordering operator */
327 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
328 result = get_opfamily_member(aform->amopfamily,
330 BTLessStrategyNumber);
331 if (OidIsValid(result))
333 /* failure probably shouldn't happen, but keep looking if so */
337 ReleaseSysCacheList(catlist);
343 * get_mergejoin_opfamilies
344 * Given a putatively mergejoinable operator, return a list of the OIDs
345 * of the btree opfamilies in which it represents equality.
347 * It is possible (though at present unusual) for an operator to be equality
348 * in more than one opfamily, hence the result is a list. This also lets us
349 * return NIL if the operator is not found in any opfamilies.
351 * The planner currently uses simple equal() tests to compare the lists
352 * returned by this function, which makes the list order relevant, though
353 * strictly speaking it should not be. Because of the way syscache list
354 * searches are handled, in normal operation the result will be sorted by OID
355 * so everything works fine. If running with system index usage disabled,
356 * the result ordering is unspecified and hence the planner might fail to
357 * recognize optimization opportunities ... but that's hardly a scenario in
358 * which performance is good anyway, so there's no point in expending code
359 * or cycles here to guarantee the ordering in that case.
362 get_mergejoin_opfamilies(Oid opno)
369 * Search pg_amop to see if the target operator is registered as the "="
370 * operator of any btree opfamily.
372 catlist = SearchSysCacheList(AMOPOPID, 1,
373 ObjectIdGetDatum(opno),
376 for (i = 0; i < catlist->n_members; i++)
378 HeapTuple tuple = &catlist->members[i]->tuple;
379 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
381 /* must be btree equality */
382 if (aform->amopmethod == BTREE_AM_OID &&
383 aform->amopstrategy == BTEqualStrategyNumber)
384 result = lappend_oid(result, aform->amopfamily);
387 ReleaseSysCacheList(catlist);
393 * get_compatible_hash_operators
394 * Get the OID(s) of hash equality operator(s) compatible with the given
395 * operator, but operating on its LHS and/or RHS datatype.
397 * An operator for the LHS type is sought and returned into *lhs_opno if
398 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
399 * and returned into *rhs_opno if rhs_opno isn't NULL.
401 * If the given operator is not cross-type, the results should be the same
402 * operator, but in cross-type situations they will be different.
404 * Returns true if able to find the requested operator(s), false if not.
405 * (This indicates that the operator should not have been marked oprcanhash.)
408 get_compatible_hash_operators(Oid opno,
409 Oid *lhs_opno, Oid *rhs_opno)
415 /* Ensure output args are initialized on failure */
417 *lhs_opno = InvalidOid;
419 *rhs_opno = InvalidOid;
422 * Search pg_amop to see if the target operator is registered as the "="
423 * operator of any hash opfamily. If the operator is registered in
424 * multiple opfamilies, assume we can use any one.
426 catlist = SearchSysCacheList(AMOPOPID, 1,
427 ObjectIdGetDatum(opno),
430 for (i = 0; i < catlist->n_members; i++)
432 HeapTuple tuple = &catlist->members[i]->tuple;
433 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
435 if (aform->amopmethod == HASH_AM_OID &&
436 aform->amopstrategy == HTEqualStrategyNumber)
438 /* No extra lookup needed if given operator is single-type */
439 if (aform->amoplefttype == aform->amoprighttype)
449 * Get the matching single-type operator(s). Failure probably
450 * shouldn't happen --- it implies a bogus opfamily --- but
451 * continue looking if so.
455 *lhs_opno = get_opfamily_member(aform->amopfamily,
458 HTEqualStrategyNumber);
459 if (!OidIsValid(*lhs_opno))
461 /* Matching LHS found, done if caller doesn't want RHS */
470 *rhs_opno = get_opfamily_member(aform->amopfamily,
471 aform->amoprighttype,
472 aform->amoprighttype,
473 HTEqualStrategyNumber);
474 if (!OidIsValid(*rhs_opno))
476 /* Forget any LHS operator from this opfamily */
478 *lhs_opno = InvalidOid;
481 /* Matching RHS found, so done */
488 ReleaseSysCacheList(catlist);
494 * get_op_hash_functions
495 * Get the OID(s) of hash support function(s) compatible with the given
496 * operator, operating on its LHS and/or RHS datatype as required.
498 * A function for the LHS type is sought and returned into *lhs_procno if
499 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
500 * and returned into *rhs_procno if rhs_procno isn't NULL.
502 * If the given operator is not cross-type, the results should be the same
503 * function, but in cross-type situations they will be different.
505 * Returns true if able to find the requested function(s), false if not.
506 * (This indicates that the operator should not have been marked oprcanhash.)
509 get_op_hash_functions(Oid opno,
510 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
516 /* Ensure output args are initialized on failure */
518 *lhs_procno = InvalidOid;
520 *rhs_procno = InvalidOid;
523 * Search pg_amop to see if the target operator is registered as the "="
524 * operator of any hash opfamily. If the operator is registered in
525 * multiple opfamilies, assume we can use any one.
527 catlist = SearchSysCacheList(AMOPOPID, 1,
528 ObjectIdGetDatum(opno),
531 for (i = 0; i < catlist->n_members; i++)
533 HeapTuple tuple = &catlist->members[i]->tuple;
534 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
536 if (aform->amopmethod == HASH_AM_OID &&
537 aform->amopstrategy == HTEqualStrategyNumber)
540 * Get the matching support function(s). Failure probably
541 * shouldn't happen --- it implies a bogus opfamily --- but
542 * continue looking if so.
546 *lhs_procno = get_opfamily_proc(aform->amopfamily,
550 if (!OidIsValid(*lhs_procno))
552 /* Matching LHS found, done if caller doesn't want RHS */
558 /* Only one lookup needed if given operator is single-type */
559 if (aform->amoplefttype == aform->amoprighttype)
561 *rhs_procno = *lhs_procno;
568 *rhs_procno = get_opfamily_proc(aform->amopfamily,
569 aform->amoprighttype,
570 aform->amoprighttype,
572 if (!OidIsValid(*rhs_procno))
574 /* Forget any LHS function from this opfamily */
576 *lhs_procno = InvalidOid;
579 /* Matching RHS found, so done */
586 ReleaseSysCacheList(catlist);
592 * get_op_btree_interpretation
593 * Given an operator's OID, find out which btree opfamilies it belongs to,
594 * and what strategy number it has within each one. The results are
595 * returned as an OID list and a parallel integer list.
597 * In addition to the normal btree operators, we consider a <> operator to be
598 * a "member" of an opfamily if its negator is an equality operator of the
599 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
602 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
612 * Find all the pg_amop entries containing the operator.
614 catlist = SearchSysCacheList(AMOPOPID, 1,
615 ObjectIdGetDatum(opno),
619 * If we can't find any opfamily containing the op, perhaps it is a <>
620 * operator. See if it has a negator that is in an opfamily.
623 if (catlist->n_members == 0)
625 Oid op_negator = get_negator(opno);
627 if (OidIsValid(op_negator))
630 ReleaseSysCacheList(catlist);
631 catlist = SearchSysCacheList(AMOPOPID, 1,
632 ObjectIdGetDatum(op_negator),
637 /* Now search the opfamilies */
638 for (i = 0; i < catlist->n_members; i++)
640 HeapTuple op_tuple = &catlist->members[i]->tuple;
641 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
643 StrategyNumber op_strategy;
646 if (op_form->amopmethod != BTREE_AM_OID)
649 /* Get the operator's btree strategy number */
650 opfamily_id = op_form->amopfamily;
651 op_strategy = (StrategyNumber) op_form->amopstrategy;
652 Assert(op_strategy >= 1 && op_strategy <= 5);
656 /* Only consider negators that are = */
657 if (op_strategy != BTEqualStrategyNumber)
659 op_strategy = ROWCOMPARE_NE;
662 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
663 *opstrats = lappend_int(*opstrats, op_strategy);
666 ReleaseSysCacheList(catlist);
670 * ops_in_same_btree_opfamily
671 * Return TRUE if there exists a btree opfamily containing both operators.
672 * (This implies that they have compatible notions of equality.)
675 ops_in_same_btree_opfamily(Oid opno1, Oid opno2)
682 * We search through all the pg_amop entries for opno1.
684 catlist = SearchSysCacheList(AMOPOPID, 1,
685 ObjectIdGetDatum(opno1),
687 for (i = 0; i < catlist->n_members; i++)
689 HeapTuple op_tuple = &catlist->members[i]->tuple;
690 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
693 if (op_form->amopmethod != BTREE_AM_OID)
696 if (op_in_opfamily(opno2, op_form->amopfamily))
703 ReleaseSysCacheList(catlist);
709 /* ---------- AMPROC CACHES ---------- */
713 * Get the OID of the specified support function
714 * for the specified opfamily and datatypes.
716 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
719 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
722 Form_pg_amproc amproc_tup;
725 tp = SearchSysCache(AMPROCNUM,
726 ObjectIdGetDatum(opfamily),
727 ObjectIdGetDatum(lefttype),
728 ObjectIdGetDatum(righttype),
729 Int16GetDatum(procnum));
730 if (!HeapTupleIsValid(tp))
732 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
733 result = amproc_tup->amproc;
739 /* ---------- ATTRIBUTE CACHES ---------- */
743 * Given the relation id and the attribute number,
744 * return the "attname" field from the attribute relation.
746 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
749 get_attname(Oid relid, AttrNumber attnum)
753 tp = SearchSysCache(ATTNUM,
754 ObjectIdGetDatum(relid),
755 Int16GetDatum(attnum),
757 if (HeapTupleIsValid(tp))
759 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
762 result = pstrdup(NameStr(att_tup->attname));
771 * get_relid_attribute_name
773 * Same as above routine get_attname(), except that error
774 * is handled by elog() instead of returning NULL.
777 get_relid_attribute_name(Oid relid, AttrNumber attnum)
781 attname = get_attname(relid, attnum);
783 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
791 * Given the relation id and the attribute name,
792 * return the "attnum" field from the attribute relation.
794 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
797 get_attnum(Oid relid, const char *attname)
801 tp = SearchSysCacheAttName(relid, attname);
802 if (HeapTupleIsValid(tp))
804 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
807 result = att_tup->attnum;
812 return InvalidAttrNumber;
818 * Given the relation OID and the attribute number with the relation,
819 * return the attribute type OID.
822 get_atttype(Oid relid, AttrNumber attnum)
826 tp = SearchSysCache(ATTNUM,
827 ObjectIdGetDatum(relid),
828 Int16GetDatum(attnum),
830 if (HeapTupleIsValid(tp))
832 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
835 result = att_tup->atttypid;
846 * Given the relation id and the attribute number,
847 * return the "atttypmod" field from the attribute relation.
850 get_atttypmod(Oid relid, AttrNumber attnum)
854 tp = SearchSysCache(ATTNUM,
855 ObjectIdGetDatum(relid),
856 Int16GetDatum(attnum),
858 if (HeapTupleIsValid(tp))
860 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
863 result = att_tup->atttypmod;
874 * A two-fer: given the relation id and the attribute number,
875 * fetch both type OID and atttypmod in a single cache lookup.
877 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
878 * raises an error if it can't obtain the information.
881 get_atttypetypmod(Oid relid, AttrNumber attnum,
882 Oid *typid, int32 *typmod)
885 Form_pg_attribute att_tup;
887 tp = SearchSysCache(ATTNUM,
888 ObjectIdGetDatum(relid),
889 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 = SearchSysCache(CONSTROID,
918 ObjectIdGetDatum(conoid),
920 if (HeapTupleIsValid(tp))
922 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
925 result = pstrdup(NameStr(contup->conname));
933 /* ---------- OPCLASS CACHE ---------- */
938 * Returns the OID of the operator family the opclass belongs to.
941 get_opclass_family(Oid opclass)
944 Form_pg_opclass cla_tup;
947 tp = SearchSysCache(CLAOID,
948 ObjectIdGetDatum(opclass),
950 if (!HeapTupleIsValid(tp))
951 elog(ERROR, "cache lookup failed for opclass %u", opclass);
952 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
954 result = cla_tup->opcfamily;
960 * get_opclass_input_type
962 * Returns the OID of the datatype the opclass indexes.
965 get_opclass_input_type(Oid opclass)
968 Form_pg_opclass cla_tup;
971 tp = SearchSysCache(CLAOID,
972 ObjectIdGetDatum(opclass),
974 if (!HeapTupleIsValid(tp))
975 elog(ERROR, "cache lookup failed for opclass %u", opclass);
976 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
978 result = cla_tup->opcintype;
983 /* ---------- OPERATOR CACHE ---------- */
988 * Returns the regproc id of the routine used to implement an
989 * operator given the operator oid.
996 tp = SearchSysCache(OPEROID,
997 ObjectIdGetDatum(opno),
999 if (HeapTupleIsValid(tp))
1001 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1002 RegProcedure result;
1004 result = optup->oprcode;
1005 ReleaseSysCache(tp);
1009 return (RegProcedure) InvalidOid;
1014 * returns the name of the operator with the given opno
1016 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1019 get_opname(Oid opno)
1023 tp = SearchSysCache(OPEROID,
1024 ObjectIdGetDatum(opno),
1026 if (HeapTupleIsValid(tp))
1028 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1031 result = pstrdup(NameStr(optup->oprname));
1032 ReleaseSysCache(tp);
1042 * Returns the left and right input datatypes for an operator
1043 * (InvalidOid if not relevant).
1046 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1049 Form_pg_operator optup;
1051 tp = SearchSysCache(OPEROID,
1052 ObjectIdGetDatum(opno),
1054 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1055 elog(ERROR, "cache lookup failed for operator %u", opno);
1056 optup = (Form_pg_operator) GETSTRUCT(tp);
1057 *lefttype = optup->oprleft;
1058 *righttype = optup->oprright;
1059 ReleaseSysCache(tp);
1065 * Returns true if the operator is potentially mergejoinable. (The planner
1066 * will fail to find any mergejoin plans unless there are suitable btree
1067 * opfamily entries for this operator and associated sortops. The pg_operator
1068 * flag is just a hint to tell the planner whether to bother looking.)
1071 op_mergejoinable(Oid opno)
1074 bool result = false;
1076 tp = SearchSysCache(OPEROID,
1077 ObjectIdGetDatum(opno),
1079 if (HeapTupleIsValid(tp))
1081 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1083 result = optup->oprcanmerge;
1084 ReleaseSysCache(tp);
1092 * Returns true if the operator is hashjoinable. (There must be a suitable
1093 * hash opfamily entry for this operator if it is so marked.)
1096 op_hashjoinable(Oid opno)
1099 bool result = false;
1101 tp = SearchSysCache(OPEROID,
1102 ObjectIdGetDatum(opno),
1104 if (HeapTupleIsValid(tp))
1106 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1108 result = optup->oprcanhash;
1109 ReleaseSysCache(tp);
1117 * Get the proisstrict flag for the operator's underlying function.
1122 RegProcedure funcid = get_opcode(opno);
1124 if (funcid == (RegProcedure) InvalidOid)
1125 elog(ERROR, "operator %u does not exist", opno);
1127 return func_strict((Oid) funcid);
1133 * Get the provolatile flag for the operator's underlying function.
1136 op_volatile(Oid opno)
1138 RegProcedure funcid = get_opcode(opno);
1140 if (funcid == (RegProcedure) InvalidOid)
1141 elog(ERROR, "operator %u does not exist", opno);
1143 return func_volatile((Oid) funcid);
1149 * Returns the corresponding commutator of an operator.
1152 get_commutator(Oid opno)
1156 tp = SearchSysCache(OPEROID,
1157 ObjectIdGetDatum(opno),
1159 if (HeapTupleIsValid(tp))
1161 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1164 result = optup->oprcom;
1165 ReleaseSysCache(tp);
1175 * Returns the corresponding negator of an operator.
1178 get_negator(Oid opno)
1182 tp = SearchSysCache(OPEROID,
1183 ObjectIdGetDatum(opno),
1185 if (HeapTupleIsValid(tp))
1187 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1190 result = optup->oprnegate;
1191 ReleaseSysCache(tp);
1201 * Returns procedure id for computing selectivity of an operator.
1204 get_oprrest(Oid opno)
1208 tp = SearchSysCache(OPEROID,
1209 ObjectIdGetDatum(opno),
1211 if (HeapTupleIsValid(tp))
1213 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1214 RegProcedure result;
1216 result = optup->oprrest;
1217 ReleaseSysCache(tp);
1221 return (RegProcedure) InvalidOid;
1227 * Returns procedure id for computing selectivity of a join.
1230 get_oprjoin(Oid opno)
1234 tp = SearchSysCache(OPEROID,
1235 ObjectIdGetDatum(opno),
1237 if (HeapTupleIsValid(tp))
1239 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1240 RegProcedure result;
1242 result = optup->oprjoin;
1243 ReleaseSysCache(tp);
1247 return (RegProcedure) InvalidOid;
1250 /* ---------- FUNCTION CACHE ---------- */
1254 * returns the name of the function with the given funcid
1256 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1259 get_func_name(Oid funcid)
1263 tp = SearchSysCache(PROCOID,
1264 ObjectIdGetDatum(funcid),
1266 if (HeapTupleIsValid(tp))
1268 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1271 result = pstrdup(NameStr(functup->proname));
1272 ReleaseSysCache(tp);
1281 * Given procedure id, return the function's result type.
1284 get_func_rettype(Oid funcid)
1289 tp = SearchSysCache(PROCOID,
1290 ObjectIdGetDatum(funcid),
1292 if (!HeapTupleIsValid(tp))
1293 elog(ERROR, "cache lookup failed for function %u", funcid);
1295 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1296 ReleaseSysCache(tp);
1302 * Given procedure id, return the number of arguments.
1305 get_func_nargs(Oid funcid)
1310 tp = SearchSysCache(PROCOID,
1311 ObjectIdGetDatum(funcid),
1313 if (!HeapTupleIsValid(tp))
1314 elog(ERROR, "cache lookup failed for function %u", funcid);
1316 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1317 ReleaseSysCache(tp);
1322 * get_func_signature
1323 * Given procedure id, return the function's argument and result types.
1324 * (The return value is the result type.)
1326 * The arguments are returned as a palloc'd array.
1329 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1332 Form_pg_proc procstruct;
1335 tp = SearchSysCache(PROCOID,
1336 ObjectIdGetDatum(funcid),
1338 if (!HeapTupleIsValid(tp))
1339 elog(ERROR, "cache lookup failed for function %u", funcid);
1341 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1343 result = procstruct->prorettype;
1344 *nargs = (int) procstruct->pronargs;
1345 Assert(*nargs == procstruct->proargtypes.dim1);
1346 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1347 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1349 ReleaseSysCache(tp);
1355 * Given procedure id, return the function's proretset flag.
1358 get_func_retset(Oid funcid)
1363 tp = SearchSysCache(PROCOID,
1364 ObjectIdGetDatum(funcid),
1366 if (!HeapTupleIsValid(tp))
1367 elog(ERROR, "cache lookup failed for function %u", funcid);
1369 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1370 ReleaseSysCache(tp);
1376 * Given procedure id, return the function's proisstrict flag.
1379 func_strict(Oid funcid)
1384 tp = SearchSysCache(PROCOID,
1385 ObjectIdGetDatum(funcid),
1387 if (!HeapTupleIsValid(tp))
1388 elog(ERROR, "cache lookup failed for function %u", funcid);
1390 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1391 ReleaseSysCache(tp);
1397 * Given procedure id, return the function's provolatile flag.
1400 func_volatile(Oid funcid)
1405 tp = SearchSysCache(PROCOID,
1406 ObjectIdGetDatum(funcid),
1408 if (!HeapTupleIsValid(tp))
1409 elog(ERROR, "cache lookup failed for function %u", funcid);
1411 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1412 ReleaseSysCache(tp);
1418 * Given procedure id, return the function's procost field.
1421 get_func_cost(Oid funcid)
1426 tp = SearchSysCache(PROCOID,
1427 ObjectIdGetDatum(funcid),
1429 if (!HeapTupleIsValid(tp))
1430 elog(ERROR, "cache lookup failed for function %u", funcid);
1432 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1433 ReleaseSysCache(tp);
1439 * Given procedure id, return the function's prorows field.
1442 get_func_rows(Oid funcid)
1447 tp = SearchSysCache(PROCOID,
1448 ObjectIdGetDatum(funcid),
1450 if (!HeapTupleIsValid(tp))
1451 elog(ERROR, "cache lookup failed for function %u", funcid);
1453 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1454 ReleaseSysCache(tp);
1458 /* ---------- RELATION CACHE ---------- */
1462 * Given name and namespace of a relation, look up the OID.
1464 * Returns InvalidOid if there is no such relation.
1467 get_relname_relid(const char *relname, Oid relnamespace)
1469 return GetSysCacheOid(RELNAMENSP,
1470 PointerGetDatum(relname),
1471 ObjectIdGetDatum(relnamespace),
1479 * Returns the number of attributes for a given relation.
1482 get_relnatts(Oid relid)
1486 tp = SearchSysCache(RELOID,
1487 ObjectIdGetDatum(relid),
1489 if (HeapTupleIsValid(tp))
1491 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1494 result = reltup->relnatts;
1495 ReleaseSysCache(tp);
1499 return InvalidAttrNumber;
1505 * Returns the name of a given relation.
1507 * Returns a palloc'd copy of the string, or NULL if no such relation.
1509 * NOTE: since relation name is not unique, be wary of code that uses this
1510 * for anything except preparing error messages.
1513 get_rel_name(Oid relid)
1517 tp = SearchSysCache(RELOID,
1518 ObjectIdGetDatum(relid),
1520 if (HeapTupleIsValid(tp))
1522 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1525 result = pstrdup(NameStr(reltup->relname));
1526 ReleaseSysCache(tp);
1536 * Returns the pg_namespace OID associated with a given relation.
1539 get_rel_namespace(Oid relid)
1543 tp = SearchSysCache(RELOID,
1544 ObjectIdGetDatum(relid),
1546 if (HeapTupleIsValid(tp))
1548 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1551 result = reltup->relnamespace;
1552 ReleaseSysCache(tp);
1562 * Returns the pg_type OID associated with a given relation.
1564 * Note: not all pg_class entries have associated pg_type OIDs; so be
1565 * careful to check for InvalidOid result.
1568 get_rel_type_id(Oid relid)
1572 tp = SearchSysCache(RELOID,
1573 ObjectIdGetDatum(relid),
1575 if (HeapTupleIsValid(tp))
1577 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1580 result = reltup->reltype;
1581 ReleaseSysCache(tp);
1591 * Returns the relkind associated with a given relation.
1594 get_rel_relkind(Oid relid)
1598 tp = SearchSysCache(RELOID,
1599 ObjectIdGetDatum(relid),
1601 if (HeapTupleIsValid(tp))
1603 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1606 result = reltup->relkind;
1607 ReleaseSysCache(tp);
1615 /* ---------- TYPE CACHE ---------- */
1620 * Given the type OID, determine whether the type is defined
1621 * (if not, it's only a shell).
1624 get_typisdefined(Oid typid)
1628 tp = SearchSysCache(TYPEOID,
1629 ObjectIdGetDatum(typid),
1631 if (HeapTupleIsValid(tp))
1633 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1636 result = typtup->typisdefined;
1637 ReleaseSysCache(tp);
1647 * Given the type OID, return the length of the type.
1650 get_typlen(Oid typid)
1654 tp = SearchSysCache(TYPEOID,
1655 ObjectIdGetDatum(typid),
1657 if (HeapTupleIsValid(tp))
1659 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1662 result = typtup->typlen;
1663 ReleaseSysCache(tp);
1673 * Given the type OID, determine whether the type is returned by value or
1674 * not. Returns true if by value, false if by reference.
1677 get_typbyval(Oid typid)
1681 tp = SearchSysCache(TYPEOID,
1682 ObjectIdGetDatum(typid),
1684 if (HeapTupleIsValid(tp))
1686 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1689 result = typtup->typbyval;
1690 ReleaseSysCache(tp);
1700 * A two-fer: given the type OID, return both typlen and typbyval.
1702 * Since both pieces of info are needed to know how to copy a Datum,
1703 * many places need both. Might as well get them with one cache lookup
1704 * instead of two. Also, this routine raises an error instead of
1705 * returning a bogus value when given a bad type OID.
1708 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1711 Form_pg_type typtup;
1713 tp = SearchSysCache(TYPEOID,
1714 ObjectIdGetDatum(typid),
1716 if (!HeapTupleIsValid(tp))
1717 elog(ERROR, "cache lookup failed for type %u", typid);
1718 typtup = (Form_pg_type) GETSTRUCT(tp);
1719 *typlen = typtup->typlen;
1720 *typbyval = typtup->typbyval;
1721 ReleaseSysCache(tp);
1725 * get_typlenbyvalalign
1727 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1730 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1734 Form_pg_type typtup;
1736 tp = SearchSysCache(TYPEOID,
1737 ObjectIdGetDatum(typid),
1739 if (!HeapTupleIsValid(tp))
1740 elog(ERROR, "cache lookup failed for type %u", typid);
1741 typtup = (Form_pg_type) GETSTRUCT(tp);
1742 *typlen = typtup->typlen;
1743 *typbyval = typtup->typbyval;
1744 *typalign = typtup->typalign;
1745 ReleaseSysCache(tp);
1750 * Given a pg_type row, select the type OID to pass to I/O functions
1752 * Formerly, all I/O functions were passed pg_type.typelem as their second
1753 * parameter, but we now have a more complex rule about what to pass.
1754 * This knowledge is intended to be centralized here --- direct references
1755 * to typelem elsewhere in the code are wrong, if they are associated with
1756 * I/O calls and not with actual subscripting operations! (But see
1757 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1759 * As of PostgreSQL 8.1, output functions receive only the value itself
1760 * and not any auxiliary parameters, so the name of this routine is now
1761 * a bit of a misnomer ... it should be getTypeInputParam.
1764 getTypeIOParam(HeapTuple typeTuple)
1766 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1769 * Array types get their typelem as parameter; everybody else gets their
1770 * own type OID as parameter. (This is a change from 8.0, in which only
1771 * composite types got their own OID as parameter.)
1773 if (OidIsValid(typeStruct->typelem))
1774 return typeStruct->typelem;
1776 return HeapTupleGetOid(typeTuple);
1782 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1783 * typdelim, typioparam, and IO function OID. The IO function
1784 * returned is controlled by IOFuncSelector
1787 get_type_io_data(Oid typid,
1788 IOFuncSelector which_func,
1796 HeapTuple typeTuple;
1797 Form_pg_type typeStruct;
1800 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1801 * use array_in and array_out during bootstrap.
1803 if (IsBootstrapProcessingMode())
1808 boot_get_type_io_data(typid,
1825 elog(ERROR, "binary I/O not supported during bootstrap");
1831 typeTuple = SearchSysCache(TYPEOID,
1832 ObjectIdGetDatum(typid),
1834 if (!HeapTupleIsValid(typeTuple))
1835 elog(ERROR, "cache lookup failed for type %u", typid);
1836 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1838 *typlen = typeStruct->typlen;
1839 *typbyval = typeStruct->typbyval;
1840 *typalign = typeStruct->typalign;
1841 *typdelim = typeStruct->typdelim;
1842 *typioparam = getTypeIOParam(typeTuple);
1846 *func = typeStruct->typinput;
1849 *func = typeStruct->typoutput;
1851 case IOFunc_receive:
1852 *func = typeStruct->typreceive;
1855 *func = typeStruct->typsend;
1858 ReleaseSysCache(typeTuple);
1863 get_typalign(Oid typid)
1867 tp = SearchSysCache(TYPEOID,
1868 ObjectIdGetDatum(typid),
1870 if (HeapTupleIsValid(tp))
1872 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1875 result = typtup->typalign;
1876 ReleaseSysCache(tp);
1885 get_typstorage(Oid typid)
1889 tp = SearchSysCache(TYPEOID,
1890 ObjectIdGetDatum(typid),
1892 if (HeapTupleIsValid(tp))
1894 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1897 result = typtup->typstorage;
1898 ReleaseSysCache(tp);
1907 * Given a type OID, return the type's default value, if any.
1909 * The result is a palloc'd expression node tree, or NULL if there
1910 * is no defined default for the datatype.
1912 * NB: caller should be prepared to coerce result to correct datatype;
1913 * the returned expression tree might produce something of the wrong type.
1916 get_typdefault(Oid typid)
1918 HeapTuple typeTuple;
1924 typeTuple = SearchSysCache(TYPEOID,
1925 ObjectIdGetDatum(typid),
1927 if (!HeapTupleIsValid(typeTuple))
1928 elog(ERROR, "cache lookup failed for type %u", typid);
1929 type = (Form_pg_type) GETSTRUCT(typeTuple);
1932 * typdefault and typdefaultbin are potentially null, so don't try to
1933 * access 'em as struct fields. Must do it the hard way with
1936 datum = SysCacheGetAttr(TYPEOID,
1938 Anum_pg_type_typdefaultbin,
1943 /* We have an expression default */
1944 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1949 /* Perhaps we have a plain literal default */
1950 datum = SysCacheGetAttr(TYPEOID,
1952 Anum_pg_type_typdefault,
1957 char *strDefaultVal;
1959 /* Convert text datum to C string */
1960 strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1962 /* Convert C string to a value of the given type */
1963 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
1964 getTypeIOParam(typeTuple), -1);
1965 /* Build a Const node containing the value */
1966 expr = (Node *) makeConst(typid,
1972 pfree(strDefaultVal);
1981 ReleaseSysCache(typeTuple);
1988 * If the given type is a domain, return its base type;
1989 * otherwise return the type's own OID.
1992 getBaseType(Oid typid)
1996 return getBaseTypeAndTypmod(typid, &typmod);
2000 * getBaseTypeAndTypmod
2001 * If the given type is a domain, return its base type and typmod;
2002 * otherwise return the type's own OID, and leave *typmod unchanged.
2004 * Note that the "applied typmod" should be -1 for every domain level
2005 * above the bottommost; therefore, if the passed-in typid is indeed
2006 * a domain, *typmod should be -1.
2009 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2012 * We loop to find the bottom base type in a stack of domains.
2017 Form_pg_type typTup;
2019 tup = SearchSysCache(TYPEOID,
2020 ObjectIdGetDatum(typid),
2022 if (!HeapTupleIsValid(tup))
2023 elog(ERROR, "cache lookup failed for type %u", typid);
2024 typTup = (Form_pg_type) GETSTRUCT(tup);
2025 if (typTup->typtype != 'd')
2027 /* Not a domain, so done */
2028 ReleaseSysCache(tup);
2032 Assert(*typmod == -1);
2033 typid = typTup->typbasetype;
2034 *typmod = typTup->typtypmod;
2036 ReleaseSysCache(tup);
2045 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2046 * estimate the average width of values of the type. This is used by
2047 * the planner, which doesn't require absolutely correct results;
2048 * it's OK (and expected) to guess if we don't know for sure.
2051 get_typavgwidth(Oid typid, int32 typmod)
2053 int typlen = get_typlen(typid);
2057 * Easy if it's a fixed-width type
2063 * type_maximum_size knows the encoding of typmod for some datatypes;
2064 * don't duplicate that knowledge here.
2066 maxwidth = type_maximum_size(typid, typmod);
2070 * For BPCHAR, the max width is also the only width. Otherwise we
2071 * need to guess about the typical data width given the max. A sliding
2072 * scale for percentage of max width seems reasonable.
2074 if (typid == BPCHAROID)
2077 return maxwidth; /* assume full width */
2078 if (maxwidth < 1000)
2079 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2082 * Beyond 1000, assume we're looking at something like
2083 * "varchar(10000)" where the limit isn't actually reached often, and
2084 * use a fixed estimate.
2086 return 32 + (1000 - 32) / 2;
2090 * Ooops, we have no idea ... wild guess time.
2098 * Given the type OID, find if it is a basic type, a complex type, etc.
2099 * It returns the null char if the cache lookup fails...
2102 get_typtype(Oid typid)
2106 tp = SearchSysCache(TYPEOID,
2107 ObjectIdGetDatum(typid),
2109 if (HeapTupleIsValid(tp))
2111 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2114 result = typtup->typtype;
2115 ReleaseSysCache(tp);
2125 * Convenience function to determine whether a type OID represents
2126 * a "rowtype" type --- either RECORD or a named composite type.
2129 type_is_rowtype(Oid typid)
2131 return (typid == RECORDOID || get_typtype(typid) == 'c');
2137 * Given the type OID, get the typrelid (InvalidOid if not a complex
2141 get_typ_typrelid(Oid typid)
2145 tp = SearchSysCache(TYPEOID,
2146 ObjectIdGetDatum(typid),
2148 if (HeapTupleIsValid(tp))
2150 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2153 result = typtup->typrelid;
2154 ReleaseSysCache(tp);
2164 * Given the type OID, get the typelem (InvalidOid if not an array type).
2166 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2167 * returned if the input is a fixed-length array type.
2170 get_element_type(Oid typid)
2174 tp = SearchSysCache(TYPEOID,
2175 ObjectIdGetDatum(typid),
2177 if (HeapTupleIsValid(tp))
2179 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2182 if (typtup->typlen == -1)
2183 result = typtup->typelem;
2185 result = InvalidOid;
2186 ReleaseSysCache(tp);
2196 * Given the type OID, get the corresponding array type.
2197 * Returns InvalidOid if no array type can be found.
2199 * NB: this only considers varlena arrays to be true arrays.
2202 get_array_type(Oid typid)
2206 tp = SearchSysCache(TYPEOID,
2207 ObjectIdGetDatum(typid),
2209 if (HeapTupleIsValid(tp))
2211 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2212 char *array_typename;
2215 array_typename = makeArrayTypeName(NameStr(typtup->typname));
2216 namespaceId = typtup->typnamespace;
2217 ReleaseSysCache(tp);
2219 tp = SearchSysCache(TYPENAMENSP,
2220 PointerGetDatum(array_typename),
2221 ObjectIdGetDatum(namespaceId),
2224 pfree(array_typename);
2226 if (HeapTupleIsValid(tp))
2230 typtup = (Form_pg_type) GETSTRUCT(tp);
2231 if (typtup->typlen == -1 && typtup->typelem == typid)
2232 result = HeapTupleGetOid(tp);
2234 result = InvalidOid;
2235 ReleaseSysCache(tp);
2245 * Get info needed for converting values of a type to internal form
2248 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2250 HeapTuple typeTuple;
2253 typeTuple = SearchSysCache(TYPEOID,
2254 ObjectIdGetDatum(type),
2256 if (!HeapTupleIsValid(typeTuple))
2257 elog(ERROR, "cache lookup failed for type %u", type);
2258 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2260 if (!pt->typisdefined)
2262 (errcode(ERRCODE_UNDEFINED_OBJECT),
2263 errmsg("type %s is only a shell",
2264 format_type_be(type))));
2265 if (!OidIsValid(pt->typinput))
2267 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2268 errmsg("no input function available for type %s",
2269 format_type_be(type))));
2271 *typInput = pt->typinput;
2272 *typIOParam = getTypeIOParam(typeTuple);
2274 ReleaseSysCache(typeTuple);
2280 * Get info needed for printing values of a type
2283 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2285 HeapTuple typeTuple;
2288 typeTuple = SearchSysCache(TYPEOID,
2289 ObjectIdGetDatum(type),
2291 if (!HeapTupleIsValid(typeTuple))
2292 elog(ERROR, "cache lookup failed for type %u", type);
2293 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2295 if (!pt->typisdefined)
2297 (errcode(ERRCODE_UNDEFINED_OBJECT),
2298 errmsg("type %s is only a shell",
2299 format_type_be(type))));
2300 if (!OidIsValid(pt->typoutput))
2302 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2303 errmsg("no output function available for type %s",
2304 format_type_be(type))));
2306 *typOutput = pt->typoutput;
2307 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2309 ReleaseSysCache(typeTuple);
2313 * getTypeBinaryInputInfo
2315 * Get info needed for binary input of values of a type
2318 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2320 HeapTuple typeTuple;
2323 typeTuple = SearchSysCache(TYPEOID,
2324 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->typreceive))
2337 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2338 errmsg("no binary input function available for type %s",
2339 format_type_be(type))));
2341 *typReceive = pt->typreceive;
2342 *typIOParam = getTypeIOParam(typeTuple);
2344 ReleaseSysCache(typeTuple);
2348 * getTypeBinaryOutputInfo
2350 * Get info needed for binary output of values of a type
2353 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2355 HeapTuple typeTuple;
2358 typeTuple = SearchSysCache(TYPEOID,
2359 ObjectIdGetDatum(type),
2361 if (!HeapTupleIsValid(typeTuple))
2362 elog(ERROR, "cache lookup failed for type %u", type);
2363 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2365 if (!pt->typisdefined)
2367 (errcode(ERRCODE_UNDEFINED_OBJECT),
2368 errmsg("type %s is only a shell",
2369 format_type_be(type))));
2370 if (!OidIsValid(pt->typsend))
2372 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2373 errmsg("no binary output function available for type %s",
2374 format_type_be(type))));
2376 *typSend = pt->typsend;
2377 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2379 ReleaseSysCache(typeTuple);
2385 * Given the type OID, return the type's typmodin procedure, if any.
2388 get_typmodin(Oid typid)
2392 tp = SearchSysCache(TYPEOID,
2393 ObjectIdGetDatum(typid),
2395 if (HeapTupleIsValid(tp))
2397 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2400 result = typtup->typmodin;
2401 ReleaseSysCache(tp);
2412 * Given the type OID, return the type's typmodout procedure, if any.
2415 get_typmodout(Oid typid)
2419 tp = SearchSysCache(TYPEOID,
2420 ObjectIdGetDatum(typid),
2422 if (HeapTupleIsValid(tp))
2424 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2427 result = typtup->typmodout;
2428 ReleaseSysCache(tp);
2434 #endif /* NOT_USED */
2437 /* ---------- STATISTICS CACHE ---------- */
2442 * Given the table and attribute number of a column, get the average
2443 * width of entries in the column. Return zero if no data available.
2446 get_attavgwidth(Oid relid, AttrNumber attnum)
2450 tp = SearchSysCache(STATRELATT,
2451 ObjectIdGetDatum(relid),
2452 Int16GetDatum(attnum),
2454 if (HeapTupleIsValid(tp))
2456 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2458 ReleaseSysCache(tp);
2468 * Extract the contents of a "slot" of a pg_statistic tuple.
2469 * Returns TRUE if requested slot type was found, else FALSE.
2471 * Unlike other routines in this file, this takes a pointer to an
2472 * already-looked-up tuple in the pg_statistic cache. We do this since
2473 * most callers will want to extract more than one value from the cache
2474 * entry, and we don't want to repeat the cache lookup unnecessarily.
2476 * statstuple: pg_statistics tuple to be examined.
2477 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2478 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2479 * reqkind: STAKIND code for desired statistics slot kind.
2480 * reqop: STAOP value wanted, or InvalidOid if don't care.
2481 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2482 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2484 * If assigned, values and numbers are set to point to palloc'd arrays.
2485 * If the attribute type is pass-by-reference, the values referenced by
2486 * the values array are themselves palloc'd. The palloc'd stuff can be
2487 * freed by calling free_attstatsslot.
2490 get_attstatsslot(HeapTuple statstuple,
2491 Oid atttype, int32 atttypmod,
2492 int reqkind, Oid reqop,
2493 Datum **values, int *nvalues,
2494 float4 **numbers, int *nnumbers)
2496 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2501 ArrayType *statarray;
2503 HeapTuple typeTuple;
2504 Form_pg_type typeForm;
2506 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2508 if ((&stats->stakind1)[i] == reqkind &&
2509 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2512 if (i >= STATISTIC_NUM_SLOTS)
2513 return false; /* not there */
2517 val = SysCacheGetAttr(STATRELATT, statstuple,
2518 Anum_pg_statistic_stavalues1 + i,
2521 elog(ERROR, "stavalues is null");
2522 statarray = DatumGetArrayTypeP(val);
2524 /* Need to get info about the array element type */
2525 typeTuple = SearchSysCache(TYPEOID,
2526 ObjectIdGetDatum(atttype),
2528 if (!HeapTupleIsValid(typeTuple))
2529 elog(ERROR, "cache lookup failed for type %u", atttype);
2530 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2532 /* Deconstruct array into Datum elements; NULLs not expected */
2533 deconstruct_array(statarray,
2538 values, NULL, nvalues);
2541 * If the element type is pass-by-reference, we now have a bunch of
2542 * Datums that are pointers into the syscache value. Copy them to
2543 * avoid problems if syscache decides to drop the entry.
2545 if (!typeForm->typbyval)
2547 for (j = 0; j < *nvalues; j++)
2549 (*values)[j] = datumCopy((*values)[j],
2555 ReleaseSysCache(typeTuple);
2558 * Free statarray if it's a detoasted copy.
2560 if ((Pointer) statarray != DatumGetPointer(val))
2566 val = SysCacheGetAttr(STATRELATT, statstuple,
2567 Anum_pg_statistic_stanumbers1 + i,
2570 elog(ERROR, "stanumbers is null");
2571 statarray = DatumGetArrayTypeP(val);
2574 * We expect the array to be a 1-D float4 array; verify that. We don't
2575 * need to use deconstruct_array() since the array data is just going
2576 * to look like a C array of float4 values.
2578 narrayelem = ARR_DIMS(statarray)[0];
2579 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2580 ARR_HASNULL(statarray) ||
2581 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2582 elog(ERROR, "stanumbers is not a 1-D float4 array");
2583 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2584 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2585 *nnumbers = narrayelem;
2588 * Free statarray if it's a detoasted copy.
2590 if ((Pointer) statarray != DatumGetPointer(val))
2599 * Free data allocated by get_attstatsslot
2601 * atttype need be valid only if values != NULL.
2604 free_attstatsslot(Oid atttype,
2605 Datum *values, int nvalues,
2606 float4 *numbers, int nnumbers)
2610 if (!get_typbyval(atttype))
2614 for (i = 0; i < nvalues; i++)
2615 pfree(DatumGetPointer(values[i]));
2623 /* ---------- PG_NAMESPACE CACHE ---------- */
2626 * get_namespace_name
2627 * Returns the name of a given namespace
2629 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2632 get_namespace_name(Oid nspid)
2636 tp = SearchSysCache(NAMESPACEOID,
2637 ObjectIdGetDatum(nspid),
2639 if (HeapTupleIsValid(tp))
2641 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2644 result = pstrdup(NameStr(nsptup->nspname));
2645 ReleaseSysCache(tp);
2652 /* ---------- PG_AUTHID CACHE ---------- */
2656 * Given a role name, look up the role's OID.
2657 * Returns InvalidOid if no such role.
2660 get_roleid(const char *rolname)
2662 return GetSysCacheOid(AUTHNAME,
2663 PointerGetDatum(rolname),
2668 * get_roleid_checked
2669 * Given a role name, look up the role's OID.
2670 * ereports if no such role.
2673 get_roleid_checked(const char *rolname)
2677 roleid = get_roleid(rolname);
2678 if (!OidIsValid(roleid))
2680 (errcode(ERRCODE_UNDEFINED_OBJECT),
2681 errmsg("role \"%s\" does not exist", rolname)));