1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2008, 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.158 2008/07/30 17:05:04 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 and declared input data types
84 * 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,
96 Form_pg_amop amop_tup;
98 tp = SearchSysCache(AMOPOPID,
99 ObjectIdGetDatum(opno),
100 ObjectIdGetDatum(opfamily),
102 if (!HeapTupleIsValid(tp))
103 elog(ERROR, "operator %u is not a member of opfamily %u",
105 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
106 *strategy = amop_tup->amopstrategy;
107 *lefttype = amop_tup->amoplefttype;
108 *righttype = amop_tup->amoprighttype;
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 = SearchSysCache(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 = SearchSysCacheList(AMOPOPID, 1,
178 ObjectIdGetDatum(opno),
181 for (i = 0; i < catlist->n_members; i++)
183 HeapTuple tuple = &catlist->members[i]->tuple;
184 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
187 if (aform->amopmethod != BTREE_AM_OID)
190 if (aform->amopstrategy == BTLessStrategyNumber ||
191 aform->amopstrategy == BTGreaterStrategyNumber)
193 /* Found it ... should have consistent input types */
194 if (aform->amoplefttype == aform->amoprighttype)
196 /* Found a suitable opfamily, return info */
197 *opfamily = aform->amopfamily;
198 *opcintype = aform->amoplefttype;
199 *strategy = aform->amopstrategy;
206 ReleaseSysCacheList(catlist);
212 * get_compare_function_for_ordering_op
213 * Get the OID of the datatype-specific btree comparison function
214 * associated with an ordering operator (a "<" or ">" operator).
216 * *cmpfunc receives the comparison function OID.
217 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
218 * (indicating the comparison result must be negated before use).
220 * Returns TRUE if successful, FALSE if no btree function can be found.
221 * (This indicates that the operator is not a valid ordering operator.)
224 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
230 /* Find the operator in pg_amop */
231 if (get_ordering_op_properties(opno,
232 &opfamily, &opcintype, &strategy))
234 /* Found a suitable opfamily, get matching support function */
235 *cmpfunc = get_opfamily_proc(opfamily,
239 if (!OidIsValid(*cmpfunc)) /* should not happen */
240 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
241 BTORDER_PROC, opcintype, opcintype, opfamily);
242 *reverse = (strategy == BTGreaterStrategyNumber);
246 /* ensure outputs are set on failure */
247 *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 * Returns InvalidOid if no matching equality operator can be found.
258 * (This indicates that the operator is not a valid ordering operator.)
261 get_equality_op_for_ordering_op(Oid opno)
263 Oid result = InvalidOid;
268 /* Find the operator in pg_amop */
269 if (get_ordering_op_properties(opno,
270 &opfamily, &opcintype, &strategy))
272 /* Found a suitable opfamily, get matching equality operator */
273 result = get_opfamily_member(opfamily,
276 BTEqualStrategyNumber);
283 * get_ordering_op_for_equality_op
284 * Get the OID of a datatype-specific btree ordering operator
285 * associated with an equality operator. (If there are multiple
286 * possibilities, assume any one will do.)
288 * This function is used when we have to sort data before unique-ifying,
289 * and don't much care which sorting op is used as long as it's compatible
290 * with the intended equality operator. Since we need a sorting operator,
291 * it should be single-data-type even if the given operator is cross-type.
292 * The caller specifies whether to find an op for the LHS or RHS data type.
294 * Returns InvalidOid if no matching ordering operator can be found.
297 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
299 Oid result = InvalidOid;
304 * Search pg_amop to see if the target operator is registered as the "="
305 * operator of any btree opfamily.
307 catlist = SearchSysCacheList(AMOPOPID, 1,
308 ObjectIdGetDatum(opno),
311 for (i = 0; i < catlist->n_members; i++)
313 HeapTuple tuple = &catlist->members[i]->tuple;
314 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
317 if (aform->amopmethod != BTREE_AM_OID)
320 if (aform->amopstrategy == BTEqualStrategyNumber)
322 /* Found a suitable opfamily, get matching ordering operator */
325 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
326 result = get_opfamily_member(aform->amopfamily,
328 BTLessStrategyNumber);
329 if (OidIsValid(result))
331 /* failure probably shouldn't happen, but keep looking if so */
335 ReleaseSysCacheList(catlist);
341 * get_mergejoin_opfamilies
342 * Given a putatively mergejoinable operator, return a list of the OIDs
343 * of the btree opfamilies in which it represents equality.
345 * It is possible (though at present unusual) for an operator to be equality
346 * in more than one opfamily, hence the result is a list. This also lets us
347 * return NIL if the operator is not found in any opfamilies.
349 * The planner currently uses simple equal() tests to compare the lists
350 * returned by this function, which makes the list order relevant, though
351 * strictly speaking it should not be. Because of the way syscache list
352 * searches are handled, in normal operation the result will be sorted by OID
353 * so everything works fine. If running with system index usage disabled,
354 * the result ordering is unspecified and hence the planner might fail to
355 * recognize optimization opportunities ... but that's hardly a scenario in
356 * which performance is good anyway, so there's no point in expending code
357 * or cycles here to guarantee the ordering in that case.
360 get_mergejoin_opfamilies(Oid opno)
367 * Search pg_amop to see if the target operator is registered as the "="
368 * operator of any btree opfamily.
370 catlist = SearchSysCacheList(AMOPOPID, 1,
371 ObjectIdGetDatum(opno),
374 for (i = 0; i < catlist->n_members; i++)
376 HeapTuple tuple = &catlist->members[i]->tuple;
377 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
379 /* must be btree equality */
380 if (aform->amopmethod == BTREE_AM_OID &&
381 aform->amopstrategy == BTEqualStrategyNumber)
382 result = lappend_oid(result, aform->amopfamily);
385 ReleaseSysCacheList(catlist);
391 * get_compatible_hash_operators
392 * Get the OID(s) of hash equality operator(s) compatible with the given
393 * operator, but operating on its LHS and/or RHS datatype.
395 * An operator for the LHS type is sought and returned into *lhs_opno if
396 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
397 * and returned into *rhs_opno if rhs_opno isn't NULL.
399 * If the given operator is not cross-type, the results should be the same
400 * operator, but in cross-type situations they will be different.
402 * Returns true if able to find the requested operator(s), false if not.
403 * (This indicates that the operator should not have been marked oprcanhash.)
406 get_compatible_hash_operators(Oid opno,
407 Oid *lhs_opno, Oid *rhs_opno)
413 /* Ensure output args are initialized on failure */
415 *lhs_opno = InvalidOid;
417 *rhs_opno = InvalidOid;
420 * Search pg_amop to see if the target operator is registered as the "="
421 * operator of any hash opfamily. If the operator is registered in
422 * multiple opfamilies, assume we can use any one.
424 catlist = SearchSysCacheList(AMOPOPID, 1,
425 ObjectIdGetDatum(opno),
428 for (i = 0; i < catlist->n_members; i++)
430 HeapTuple tuple = &catlist->members[i]->tuple;
431 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
433 if (aform->amopmethod == HASH_AM_OID &&
434 aform->amopstrategy == HTEqualStrategyNumber)
436 /* No extra lookup needed if given operator is single-type */
437 if (aform->amoplefttype == aform->amoprighttype)
448 * Get the matching single-type operator(s). Failure probably
449 * shouldn't happen --- it implies a bogus opfamily --- but
450 * continue looking if so.
454 *lhs_opno = get_opfamily_member(aform->amopfamily,
457 HTEqualStrategyNumber);
458 if (!OidIsValid(*lhs_opno))
460 /* Matching LHS found, done if caller doesn't want RHS */
469 *rhs_opno = get_opfamily_member(aform->amopfamily,
470 aform->amoprighttype,
471 aform->amoprighttype,
472 HTEqualStrategyNumber);
473 if (!OidIsValid(*rhs_opno))
475 /* Forget any LHS operator from this opfamily */
477 *lhs_opno = InvalidOid;
480 /* Matching RHS found, so done */
487 ReleaseSysCacheList(catlist);
493 * get_op_hash_functions
494 * Get the OID(s) of hash support function(s) compatible with the given
495 * operator, operating on its LHS and/or RHS datatype as required.
497 * A function for the LHS type is sought and returned into *lhs_procno if
498 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
499 * and returned into *rhs_procno if rhs_procno isn't NULL.
501 * If the given operator is not cross-type, the results should be the same
502 * function, but in cross-type situations they will be different.
504 * Returns true if able to find the requested function(s), false if not.
505 * (This indicates that the operator should not have been marked oprcanhash.)
508 get_op_hash_functions(Oid opno,
509 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
515 /* Ensure output args are initialized on failure */
517 *lhs_procno = InvalidOid;
519 *rhs_procno = InvalidOid;
522 * Search pg_amop to see if the target operator is registered as the "="
523 * operator of any hash opfamily. If the operator is registered in
524 * multiple opfamilies, assume we can use any one.
526 catlist = SearchSysCacheList(AMOPOPID, 1,
527 ObjectIdGetDatum(opno),
530 for (i = 0; i < catlist->n_members; i++)
532 HeapTuple tuple = &catlist->members[i]->tuple;
533 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
535 if (aform->amopmethod == HASH_AM_OID &&
536 aform->amopstrategy == HTEqualStrategyNumber)
539 * Get the matching support function(s). Failure probably
540 * shouldn't happen --- it implies a bogus opfamily --- but
541 * continue looking if so.
545 *lhs_procno = get_opfamily_proc(aform->amopfamily,
549 if (!OidIsValid(*lhs_procno))
551 /* Matching LHS found, done if caller doesn't want RHS */
557 /* Only one lookup needed if given operator is single-type */
558 if (aform->amoplefttype == aform->amoprighttype)
560 *rhs_procno = *lhs_procno;
567 *rhs_procno = get_opfamily_proc(aform->amopfamily,
568 aform->amoprighttype,
569 aform->amoprighttype,
571 if (!OidIsValid(*rhs_procno))
573 /* Forget any LHS function from this opfamily */
575 *lhs_procno = InvalidOid;
578 /* Matching RHS found, so done */
585 ReleaseSysCacheList(catlist);
591 * get_op_btree_interpretation
592 * Given an operator's OID, find out which btree opfamilies it belongs to,
593 * and what strategy number it has within each one. The results are
594 * returned as an OID list and a parallel integer list.
596 * In addition to the normal btree operators, we consider a <> operator to be
597 * a "member" of an opfamily if its negator is an equality operator of the
598 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
601 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
611 * Find all the pg_amop entries containing the operator.
613 catlist = SearchSysCacheList(AMOPOPID, 1,
614 ObjectIdGetDatum(opno),
618 * If we can't find any opfamily containing the op, perhaps it is a <>
619 * operator. See if it has a negator that is in an opfamily.
622 if (catlist->n_members == 0)
624 Oid op_negator = get_negator(opno);
626 if (OidIsValid(op_negator))
629 ReleaseSysCacheList(catlist);
630 catlist = SearchSysCacheList(AMOPOPID, 1,
631 ObjectIdGetDatum(op_negator),
636 /* Now search the opfamilies */
637 for (i = 0; i < catlist->n_members; i++)
639 HeapTuple op_tuple = &catlist->members[i]->tuple;
640 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
642 StrategyNumber op_strategy;
645 if (op_form->amopmethod != BTREE_AM_OID)
648 /* Get the operator's btree strategy number */
649 opfamily_id = op_form->amopfamily;
650 op_strategy = (StrategyNumber) op_form->amopstrategy;
651 Assert(op_strategy >= 1 && op_strategy <= 5);
655 /* Only consider negators that are = */
656 if (op_strategy != BTEqualStrategyNumber)
658 op_strategy = ROWCOMPARE_NE;
661 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
662 *opstrats = lappend_int(*opstrats, op_strategy);
665 ReleaseSysCacheList(catlist);
669 * ops_in_same_btree_opfamily
670 * Return TRUE if there exists a btree opfamily containing both operators.
671 * (This implies that they have compatible notions of equality.)
674 ops_in_same_btree_opfamily(Oid opno1, Oid opno2)
681 * We search through all the pg_amop entries for opno1.
683 catlist = SearchSysCacheList(AMOPOPID, 1,
684 ObjectIdGetDatum(opno1),
686 for (i = 0; i < catlist->n_members; i++)
688 HeapTuple op_tuple = &catlist->members[i]->tuple;
689 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
692 if (op_form->amopmethod != BTREE_AM_OID)
695 if (op_in_opfamily(opno2, op_form->amopfamily))
702 ReleaseSysCacheList(catlist);
708 /* ---------- AMPROC CACHES ---------- */
712 * Get the OID of the specified support function
713 * for the specified opfamily and datatypes.
715 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
718 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
721 Form_pg_amproc amproc_tup;
724 tp = SearchSysCache(AMPROCNUM,
725 ObjectIdGetDatum(opfamily),
726 ObjectIdGetDatum(lefttype),
727 ObjectIdGetDatum(righttype),
728 Int16GetDatum(procnum));
729 if (!HeapTupleIsValid(tp))
731 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
732 result = amproc_tup->amproc;
738 /* ---------- ATTRIBUTE CACHES ---------- */
742 * Given the relation id and the attribute number,
743 * return the "attname" field from the attribute relation.
745 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
748 get_attname(Oid relid, AttrNumber attnum)
752 tp = SearchSysCache(ATTNUM,
753 ObjectIdGetDatum(relid),
754 Int16GetDatum(attnum),
756 if (HeapTupleIsValid(tp))
758 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
761 result = pstrdup(NameStr(att_tup->attname));
770 * get_relid_attribute_name
772 * Same as above routine get_attname(), except that error
773 * is handled by elog() instead of returning NULL.
776 get_relid_attribute_name(Oid relid, AttrNumber attnum)
780 attname = get_attname(relid, attnum);
782 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
790 * Given the relation id and the attribute name,
791 * return the "attnum" field from the attribute relation.
793 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
796 get_attnum(Oid relid, const char *attname)
800 tp = SearchSysCacheAttName(relid, attname);
801 if (HeapTupleIsValid(tp))
803 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
806 result = att_tup->attnum;
811 return InvalidAttrNumber;
817 * Given the relation OID and the attribute number with the relation,
818 * return the attribute type OID.
821 get_atttype(Oid relid, AttrNumber attnum)
825 tp = SearchSysCache(ATTNUM,
826 ObjectIdGetDatum(relid),
827 Int16GetDatum(attnum),
829 if (HeapTupleIsValid(tp))
831 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
834 result = att_tup->atttypid;
845 * Given the relation id and the attribute number,
846 * return the "atttypmod" field from the attribute relation.
849 get_atttypmod(Oid relid, AttrNumber attnum)
853 tp = SearchSysCache(ATTNUM,
854 ObjectIdGetDatum(relid),
855 Int16GetDatum(attnum),
857 if (HeapTupleIsValid(tp))
859 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
862 result = att_tup->atttypmod;
873 * A two-fer: given the relation id and the attribute number,
874 * fetch both type OID and atttypmod in a single cache lookup.
876 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
877 * raises an error if it can't obtain the information.
880 get_atttypetypmod(Oid relid, AttrNumber attnum,
881 Oid *typid, int32 *typmod)
884 Form_pg_attribute att_tup;
886 tp = SearchSysCache(ATTNUM,
887 ObjectIdGetDatum(relid),
888 Int16GetDatum(attnum),
890 if (!HeapTupleIsValid(tp))
891 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
893 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
895 *typid = att_tup->atttypid;
896 *typmod = att_tup->atttypmod;
900 /* ---------- CONSTRAINT CACHE ---------- */
903 * get_constraint_name
904 * Returns the name of a given pg_constraint entry.
906 * Returns a palloc'd copy of the string, or NULL if no such constraint.
908 * NOTE: since constraint name is not unique, be wary of code that uses this
909 * for anything except preparing error messages.
912 get_constraint_name(Oid conoid)
916 tp = SearchSysCache(CONSTROID,
917 ObjectIdGetDatum(conoid),
919 if (HeapTupleIsValid(tp))
921 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
924 result = pstrdup(NameStr(contup->conname));
932 /* ---------- OPCLASS CACHE ---------- */
937 * Returns the OID of the operator family the opclass belongs to.
940 get_opclass_family(Oid opclass)
943 Form_pg_opclass cla_tup;
946 tp = SearchSysCache(CLAOID,
947 ObjectIdGetDatum(opclass),
949 if (!HeapTupleIsValid(tp))
950 elog(ERROR, "cache lookup failed for opclass %u", opclass);
951 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
953 result = cla_tup->opcfamily;
959 * get_opclass_input_type
961 * Returns the OID of the datatype the opclass indexes.
964 get_opclass_input_type(Oid opclass)
967 Form_pg_opclass cla_tup;
970 tp = SearchSysCache(CLAOID,
971 ObjectIdGetDatum(opclass),
973 if (!HeapTupleIsValid(tp))
974 elog(ERROR, "cache lookup failed for opclass %u", opclass);
975 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
977 result = cla_tup->opcintype;
982 /* ---------- OPERATOR CACHE ---------- */
987 * Returns the regproc id of the routine used to implement an
988 * operator given the operator oid.
995 tp = SearchSysCache(OPEROID,
996 ObjectIdGetDatum(opno),
998 if (HeapTupleIsValid(tp))
1000 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1001 RegProcedure result;
1003 result = optup->oprcode;
1004 ReleaseSysCache(tp);
1008 return (RegProcedure) InvalidOid;
1013 * returns the name of the operator with the given opno
1015 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1018 get_opname(Oid opno)
1022 tp = SearchSysCache(OPEROID,
1023 ObjectIdGetDatum(opno),
1025 if (HeapTupleIsValid(tp))
1027 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1030 result = pstrdup(NameStr(optup->oprname));
1031 ReleaseSysCache(tp);
1041 * Returns the left and right input datatypes for an operator
1042 * (InvalidOid if not relevant).
1045 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1048 Form_pg_operator optup;
1050 tp = SearchSysCache(OPEROID,
1051 ObjectIdGetDatum(opno),
1053 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1054 elog(ERROR, "cache lookup failed for operator %u", opno);
1055 optup = (Form_pg_operator) GETSTRUCT(tp);
1056 *lefttype = optup->oprleft;
1057 *righttype = optup->oprright;
1058 ReleaseSysCache(tp);
1064 * Returns true if the operator is potentially mergejoinable. (The planner
1065 * will fail to find any mergejoin plans unless there are suitable btree
1066 * opfamily entries for this operator and associated sortops. The pg_operator
1067 * flag is just a hint to tell the planner whether to bother looking.)
1070 op_mergejoinable(Oid opno)
1073 bool result = false;
1075 tp = SearchSysCache(OPEROID,
1076 ObjectIdGetDatum(opno),
1078 if (HeapTupleIsValid(tp))
1080 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1082 result = optup->oprcanmerge;
1083 ReleaseSysCache(tp);
1091 * Returns true if the operator is hashjoinable. (There must be a suitable
1092 * hash opfamily entry for this operator if it is so marked.)
1095 op_hashjoinable(Oid opno)
1098 bool result = false;
1100 tp = SearchSysCache(OPEROID,
1101 ObjectIdGetDatum(opno),
1103 if (HeapTupleIsValid(tp))
1105 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1107 result = optup->oprcanhash;
1108 ReleaseSysCache(tp);
1116 * Get the proisstrict flag for the operator's underlying function.
1121 RegProcedure funcid = get_opcode(opno);
1123 if (funcid == (RegProcedure) InvalidOid)
1124 elog(ERROR, "operator %u does not exist", opno);
1126 return func_strict((Oid) funcid);
1132 * Get the provolatile flag for the operator's underlying function.
1135 op_volatile(Oid opno)
1137 RegProcedure funcid = get_opcode(opno);
1139 if (funcid == (RegProcedure) InvalidOid)
1140 elog(ERROR, "operator %u does not exist", opno);
1142 return func_volatile((Oid) funcid);
1148 * Returns the corresponding commutator of an operator.
1151 get_commutator(Oid opno)
1155 tp = SearchSysCache(OPEROID,
1156 ObjectIdGetDatum(opno),
1158 if (HeapTupleIsValid(tp))
1160 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1163 result = optup->oprcom;
1164 ReleaseSysCache(tp);
1174 * Returns the corresponding negator of an operator.
1177 get_negator(Oid opno)
1181 tp = SearchSysCache(OPEROID,
1182 ObjectIdGetDatum(opno),
1184 if (HeapTupleIsValid(tp))
1186 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1189 result = optup->oprnegate;
1190 ReleaseSysCache(tp);
1200 * Returns procedure id for computing selectivity of an operator.
1203 get_oprrest(Oid opno)
1207 tp = SearchSysCache(OPEROID,
1208 ObjectIdGetDatum(opno),
1210 if (HeapTupleIsValid(tp))
1212 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1213 RegProcedure result;
1215 result = optup->oprrest;
1216 ReleaseSysCache(tp);
1220 return (RegProcedure) InvalidOid;
1226 * Returns procedure id for computing selectivity of a join.
1229 get_oprjoin(Oid opno)
1233 tp = SearchSysCache(OPEROID,
1234 ObjectIdGetDatum(opno),
1236 if (HeapTupleIsValid(tp))
1238 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1239 RegProcedure result;
1241 result = optup->oprjoin;
1242 ReleaseSysCache(tp);
1246 return (RegProcedure) InvalidOid;
1249 /* ---------- FUNCTION CACHE ---------- */
1253 * returns the name of the function with the given funcid
1255 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1258 get_func_name(Oid funcid)
1262 tp = SearchSysCache(PROCOID,
1263 ObjectIdGetDatum(funcid),
1265 if (HeapTupleIsValid(tp))
1267 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1270 result = pstrdup(NameStr(functup->proname));
1271 ReleaseSysCache(tp);
1280 * Given procedure id, return the function's result type.
1283 get_func_rettype(Oid funcid)
1288 tp = SearchSysCache(PROCOID,
1289 ObjectIdGetDatum(funcid),
1291 if (!HeapTupleIsValid(tp))
1292 elog(ERROR, "cache lookup failed for function %u", funcid);
1294 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1295 ReleaseSysCache(tp);
1301 * Given procedure id, return the number of arguments.
1304 get_func_nargs(Oid funcid)
1309 tp = SearchSysCache(PROCOID,
1310 ObjectIdGetDatum(funcid),
1312 if (!HeapTupleIsValid(tp))
1313 elog(ERROR, "cache lookup failed for function %u", funcid);
1315 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1316 ReleaseSysCache(tp);
1321 * get_func_signature
1322 * Given procedure id, return the function's argument and result types.
1323 * (The return value is the result type.)
1325 * The arguments are returned as a palloc'd array.
1328 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1331 Form_pg_proc procstruct;
1334 tp = SearchSysCache(PROCOID,
1335 ObjectIdGetDatum(funcid),
1337 if (!HeapTupleIsValid(tp))
1338 elog(ERROR, "cache lookup failed for function %u", funcid);
1340 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1342 result = procstruct->prorettype;
1343 *nargs = (int) procstruct->pronargs;
1344 Assert(*nargs == procstruct->proargtypes.dim1);
1345 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1346 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1348 ReleaseSysCache(tp);
1354 * Given procedure id, return the function's proretset flag.
1357 get_func_retset(Oid funcid)
1362 tp = SearchSysCache(PROCOID,
1363 ObjectIdGetDatum(funcid),
1365 if (!HeapTupleIsValid(tp))
1366 elog(ERROR, "cache lookup failed for function %u", funcid);
1368 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1369 ReleaseSysCache(tp);
1375 * Given procedure id, return the function's proisstrict flag.
1378 func_strict(Oid funcid)
1383 tp = SearchSysCache(PROCOID,
1384 ObjectIdGetDatum(funcid),
1386 if (!HeapTupleIsValid(tp))
1387 elog(ERROR, "cache lookup failed for function %u", funcid);
1389 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1390 ReleaseSysCache(tp);
1396 * Given procedure id, return the function's provolatile flag.
1399 func_volatile(Oid funcid)
1404 tp = SearchSysCache(PROCOID,
1405 ObjectIdGetDatum(funcid),
1407 if (!HeapTupleIsValid(tp))
1408 elog(ERROR, "cache lookup failed for function %u", funcid);
1410 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1411 ReleaseSysCache(tp);
1417 * Given procedure id, return the function's procost field.
1420 get_func_cost(Oid funcid)
1425 tp = SearchSysCache(PROCOID,
1426 ObjectIdGetDatum(funcid),
1428 if (!HeapTupleIsValid(tp))
1429 elog(ERROR, "cache lookup failed for function %u", funcid);
1431 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1432 ReleaseSysCache(tp);
1438 * Given procedure id, return the function's prorows field.
1441 get_func_rows(Oid funcid)
1446 tp = SearchSysCache(PROCOID,
1447 ObjectIdGetDatum(funcid),
1449 if (!HeapTupleIsValid(tp))
1450 elog(ERROR, "cache lookup failed for function %u", funcid);
1452 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1453 ReleaseSysCache(tp);
1457 /* ---------- RELATION CACHE ---------- */
1461 * Given name and namespace of a relation, look up the OID.
1463 * Returns InvalidOid if there is no such relation.
1466 get_relname_relid(const char *relname, Oid relnamespace)
1468 return GetSysCacheOid(RELNAMENSP,
1469 PointerGetDatum(relname),
1470 ObjectIdGetDatum(relnamespace),
1478 * Returns the number of attributes for a given relation.
1481 get_relnatts(Oid relid)
1485 tp = SearchSysCache(RELOID,
1486 ObjectIdGetDatum(relid),
1488 if (HeapTupleIsValid(tp))
1490 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1493 result = reltup->relnatts;
1494 ReleaseSysCache(tp);
1498 return InvalidAttrNumber;
1504 * Returns the name of a given relation.
1506 * Returns a palloc'd copy of the string, or NULL if no such relation.
1508 * NOTE: since relation name is not unique, be wary of code that uses this
1509 * for anything except preparing error messages.
1512 get_rel_name(Oid relid)
1516 tp = SearchSysCache(RELOID,
1517 ObjectIdGetDatum(relid),
1519 if (HeapTupleIsValid(tp))
1521 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1524 result = pstrdup(NameStr(reltup->relname));
1525 ReleaseSysCache(tp);
1535 * Returns the pg_namespace OID associated with a given relation.
1538 get_rel_namespace(Oid relid)
1542 tp = SearchSysCache(RELOID,
1543 ObjectIdGetDatum(relid),
1545 if (HeapTupleIsValid(tp))
1547 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1550 result = reltup->relnamespace;
1551 ReleaseSysCache(tp);
1561 * Returns the pg_type OID associated with a given relation.
1563 * Note: not all pg_class entries have associated pg_type OIDs; so be
1564 * careful to check for InvalidOid result.
1567 get_rel_type_id(Oid relid)
1571 tp = SearchSysCache(RELOID,
1572 ObjectIdGetDatum(relid),
1574 if (HeapTupleIsValid(tp))
1576 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1579 result = reltup->reltype;
1580 ReleaseSysCache(tp);
1590 * Returns the relkind associated with a given relation.
1593 get_rel_relkind(Oid relid)
1597 tp = SearchSysCache(RELOID,
1598 ObjectIdGetDatum(relid),
1600 if (HeapTupleIsValid(tp))
1602 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1605 result = reltup->relkind;
1606 ReleaseSysCache(tp);
1614 * get_rel_tablespace
1616 * Returns the pg_tablespace OID associated with a given relation.
1618 * Note: InvalidOid might mean either that we couldn't find the relation,
1619 * or that it is in the database's default tablespace.
1622 get_rel_tablespace(Oid relid)
1626 tp = SearchSysCache(RELOID,
1627 ObjectIdGetDatum(relid),
1629 if (HeapTupleIsValid(tp))
1631 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1634 result = reltup->reltablespace;
1635 ReleaseSysCache(tp);
1643 /* ---------- TYPE CACHE ---------- */
1648 * Given the type OID, determine whether the type is defined
1649 * (if not, it's only a shell).
1652 get_typisdefined(Oid typid)
1656 tp = SearchSysCache(TYPEOID,
1657 ObjectIdGetDatum(typid),
1659 if (HeapTupleIsValid(tp))
1661 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1664 result = typtup->typisdefined;
1665 ReleaseSysCache(tp);
1675 * Given the type OID, return the length of the type.
1678 get_typlen(Oid typid)
1682 tp = SearchSysCache(TYPEOID,
1683 ObjectIdGetDatum(typid),
1685 if (HeapTupleIsValid(tp))
1687 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1690 result = typtup->typlen;
1691 ReleaseSysCache(tp);
1701 * Given the type OID, determine whether the type is returned by value or
1702 * not. Returns true if by value, false if by reference.
1705 get_typbyval(Oid typid)
1709 tp = SearchSysCache(TYPEOID,
1710 ObjectIdGetDatum(typid),
1712 if (HeapTupleIsValid(tp))
1714 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1717 result = typtup->typbyval;
1718 ReleaseSysCache(tp);
1728 * A two-fer: given the type OID, return both typlen and typbyval.
1730 * Since both pieces of info are needed to know how to copy a Datum,
1731 * many places need both. Might as well get them with one cache lookup
1732 * instead of two. Also, this routine raises an error instead of
1733 * returning a bogus value when given a bad type OID.
1736 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1739 Form_pg_type typtup;
1741 tp = SearchSysCache(TYPEOID,
1742 ObjectIdGetDatum(typid),
1744 if (!HeapTupleIsValid(tp))
1745 elog(ERROR, "cache lookup failed for type %u", typid);
1746 typtup = (Form_pg_type) GETSTRUCT(tp);
1747 *typlen = typtup->typlen;
1748 *typbyval = typtup->typbyval;
1749 ReleaseSysCache(tp);
1753 * get_typlenbyvalalign
1755 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1758 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1762 Form_pg_type typtup;
1764 tp = SearchSysCache(TYPEOID,
1765 ObjectIdGetDatum(typid),
1767 if (!HeapTupleIsValid(tp))
1768 elog(ERROR, "cache lookup failed for type %u", typid);
1769 typtup = (Form_pg_type) GETSTRUCT(tp);
1770 *typlen = typtup->typlen;
1771 *typbyval = typtup->typbyval;
1772 *typalign = typtup->typalign;
1773 ReleaseSysCache(tp);
1778 * Given a pg_type row, select the type OID to pass to I/O functions
1780 * Formerly, all I/O functions were passed pg_type.typelem as their second
1781 * parameter, but we now have a more complex rule about what to pass.
1782 * This knowledge is intended to be centralized here --- direct references
1783 * to typelem elsewhere in the code are wrong, if they are associated with
1784 * I/O calls and not with actual subscripting operations! (But see
1785 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1787 * As of PostgreSQL 8.1, output functions receive only the value itself
1788 * and not any auxiliary parameters, so the name of this routine is now
1789 * a bit of a misnomer ... it should be getTypeInputParam.
1792 getTypeIOParam(HeapTuple typeTuple)
1794 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1797 * Array types get their typelem as parameter; everybody else gets their
1798 * own type OID as parameter. (As of 8.2, domains must get their own OID
1799 * even if their base type is an array.)
1801 if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem))
1802 return typeStruct->typelem;
1804 return HeapTupleGetOid(typeTuple);
1810 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1811 * typdelim, typioparam, and IO function OID. The IO function
1812 * returned is controlled by IOFuncSelector
1815 get_type_io_data(Oid typid,
1816 IOFuncSelector which_func,
1824 HeapTuple typeTuple;
1825 Form_pg_type typeStruct;
1828 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1829 * use array_in and array_out during bootstrap.
1831 if (IsBootstrapProcessingMode())
1836 boot_get_type_io_data(typid,
1853 elog(ERROR, "binary I/O not supported during bootstrap");
1859 typeTuple = SearchSysCache(TYPEOID,
1860 ObjectIdGetDatum(typid),
1862 if (!HeapTupleIsValid(typeTuple))
1863 elog(ERROR, "cache lookup failed for type %u", typid);
1864 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1866 *typlen = typeStruct->typlen;
1867 *typbyval = typeStruct->typbyval;
1868 *typalign = typeStruct->typalign;
1869 *typdelim = typeStruct->typdelim;
1870 *typioparam = getTypeIOParam(typeTuple);
1874 *func = typeStruct->typinput;
1877 *func = typeStruct->typoutput;
1879 case IOFunc_receive:
1880 *func = typeStruct->typreceive;
1883 *func = typeStruct->typsend;
1886 ReleaseSysCache(typeTuple);
1891 get_typalign(Oid typid)
1895 tp = SearchSysCache(TYPEOID,
1896 ObjectIdGetDatum(typid),
1898 if (HeapTupleIsValid(tp))
1900 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1903 result = typtup->typalign;
1904 ReleaseSysCache(tp);
1913 get_typstorage(Oid typid)
1917 tp = SearchSysCache(TYPEOID,
1918 ObjectIdGetDatum(typid),
1920 if (HeapTupleIsValid(tp))
1922 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1925 result = typtup->typstorage;
1926 ReleaseSysCache(tp);
1935 * Given a type OID, return the type's default value, if any.
1937 * The result is a palloc'd expression node tree, or NULL if there
1938 * is no defined default for the datatype.
1940 * NB: caller should be prepared to coerce result to correct datatype;
1941 * the returned expression tree might produce something of the wrong type.
1944 get_typdefault(Oid typid)
1946 HeapTuple typeTuple;
1952 typeTuple = SearchSysCache(TYPEOID,
1953 ObjectIdGetDatum(typid),
1955 if (!HeapTupleIsValid(typeTuple))
1956 elog(ERROR, "cache lookup failed for type %u", typid);
1957 type = (Form_pg_type) GETSTRUCT(typeTuple);
1960 * typdefault and typdefaultbin are potentially null, so don't try to
1961 * access 'em as struct fields. Must do it the hard way with
1964 datum = SysCacheGetAttr(TYPEOID,
1966 Anum_pg_type_typdefaultbin,
1971 /* We have an expression default */
1972 expr = stringToNode(TextDatumGetCString(datum));
1976 /* Perhaps we have a plain literal default */
1977 datum = SysCacheGetAttr(TYPEOID,
1979 Anum_pg_type_typdefault,
1984 char *strDefaultVal;
1986 /* Convert text datum to C string */
1987 strDefaultVal = TextDatumGetCString(datum);
1988 /* Convert C string to a value of the given type */
1989 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
1990 getTypeIOParam(typeTuple), -1);
1991 /* Build a Const node containing the value */
1992 expr = (Node *) makeConst(typid,
1998 pfree(strDefaultVal);
2007 ReleaseSysCache(typeTuple);
2014 * If the given type is a domain, return its base type;
2015 * otherwise return the type's own OID.
2018 getBaseType(Oid typid)
2022 return getBaseTypeAndTypmod(typid, &typmod);
2026 * getBaseTypeAndTypmod
2027 * If the given type is a domain, return its base type and typmod;
2028 * otherwise return the type's own OID, and leave *typmod unchanged.
2030 * Note that the "applied typmod" should be -1 for every domain level
2031 * above the bottommost; therefore, if the passed-in typid is indeed
2032 * a domain, *typmod should be -1.
2035 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2038 * We loop to find the bottom base type in a stack of domains.
2043 Form_pg_type typTup;
2045 tup = SearchSysCache(TYPEOID,
2046 ObjectIdGetDatum(typid),
2048 if (!HeapTupleIsValid(tup))
2049 elog(ERROR, "cache lookup failed for type %u", typid);
2050 typTup = (Form_pg_type) GETSTRUCT(tup);
2051 if (typTup->typtype != TYPTYPE_DOMAIN)
2053 /* Not a domain, so done */
2054 ReleaseSysCache(tup);
2058 Assert(*typmod == -1);
2059 typid = typTup->typbasetype;
2060 *typmod = typTup->typtypmod;
2062 ReleaseSysCache(tup);
2071 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2072 * estimate the average width of values of the type. This is used by
2073 * the planner, which doesn't require absolutely correct results;
2074 * it's OK (and expected) to guess if we don't know for sure.
2077 get_typavgwidth(Oid typid, int32 typmod)
2079 int typlen = get_typlen(typid);
2083 * Easy if it's a fixed-width type
2089 * type_maximum_size knows the encoding of typmod for some datatypes;
2090 * don't duplicate that knowledge here.
2092 maxwidth = type_maximum_size(typid, typmod);
2096 * For BPCHAR, the max width is also the only width. Otherwise we
2097 * need to guess about the typical data width given the max. A sliding
2098 * scale for percentage of max width seems reasonable.
2100 if (typid == BPCHAROID)
2103 return maxwidth; /* assume full width */
2104 if (maxwidth < 1000)
2105 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2108 * Beyond 1000, assume we're looking at something like
2109 * "varchar(10000)" where the limit isn't actually reached often, and
2110 * use a fixed estimate.
2112 return 32 + (1000 - 32) / 2;
2116 * Ooops, we have no idea ... wild guess time.
2124 * Given the type OID, find if it is a basic type, a complex type, etc.
2125 * It returns the null char if the cache lookup fails...
2128 get_typtype(Oid typid)
2132 tp = SearchSysCache(TYPEOID,
2133 ObjectIdGetDatum(typid),
2135 if (HeapTupleIsValid(tp))
2137 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2140 result = typtup->typtype;
2141 ReleaseSysCache(tp);
2151 * Convenience function to determine whether a type OID represents
2152 * a "rowtype" type --- either RECORD or a named composite type.
2155 type_is_rowtype(Oid typid)
2157 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2162 * Returns true if the given type is an enum type.
2165 type_is_enum(Oid typid)
2167 return (get_typtype(typid) == TYPTYPE_ENUM);
2171 * get_type_category_preferred
2173 * Given the type OID, fetch its category and preferred-type status.
2174 * Throws error on failure.
2177 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2180 Form_pg_type typtup;
2182 tp = SearchSysCache(TYPEOID,
2183 ObjectIdGetDatum(typid),
2185 if (!HeapTupleIsValid(tp))
2186 elog(ERROR, "cache lookup failed for type %u", typid);
2187 typtup = (Form_pg_type) GETSTRUCT(tp);
2188 *typcategory = typtup->typcategory;
2189 *typispreferred = typtup->typispreferred;
2190 ReleaseSysCache(tp);
2196 * Given the type OID, get the typrelid (InvalidOid if not a complex
2200 get_typ_typrelid(Oid typid)
2204 tp = SearchSysCache(TYPEOID,
2205 ObjectIdGetDatum(typid),
2207 if (HeapTupleIsValid(tp))
2209 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2212 result = typtup->typrelid;
2213 ReleaseSysCache(tp);
2223 * Given the type OID, get the typelem (InvalidOid if not an array type).
2225 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2226 * returned if the input is a fixed-length array type.
2229 get_element_type(Oid typid)
2233 tp = SearchSysCache(TYPEOID,
2234 ObjectIdGetDatum(typid),
2236 if (HeapTupleIsValid(tp))
2238 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2241 if (typtup->typlen == -1)
2242 result = typtup->typelem;
2244 result = InvalidOid;
2245 ReleaseSysCache(tp);
2255 * Given the type OID, get the corresponding "true" array type.
2256 * Returns InvalidOid if no array type can be found.
2259 get_array_type(Oid typid)
2262 Oid result = InvalidOid;
2264 tp = SearchSysCache(TYPEOID,
2265 ObjectIdGetDatum(typid),
2267 if (HeapTupleIsValid(tp))
2269 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2270 ReleaseSysCache(tp);
2278 * Get info needed for converting values of a type to internal form
2281 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2283 HeapTuple typeTuple;
2286 typeTuple = SearchSysCache(TYPEOID,
2287 ObjectIdGetDatum(type),
2289 if (!HeapTupleIsValid(typeTuple))
2290 elog(ERROR, "cache lookup failed for type %u", type);
2291 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2293 if (!pt->typisdefined)
2295 (errcode(ERRCODE_UNDEFINED_OBJECT),
2296 errmsg("type %s is only a shell",
2297 format_type_be(type))));
2298 if (!OidIsValid(pt->typinput))
2300 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2301 errmsg("no input function available for type %s",
2302 format_type_be(type))));
2304 *typInput = pt->typinput;
2305 *typIOParam = getTypeIOParam(typeTuple);
2307 ReleaseSysCache(typeTuple);
2313 * Get info needed for printing values of a type
2316 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2318 HeapTuple typeTuple;
2321 typeTuple = SearchSysCache(TYPEOID,
2322 ObjectIdGetDatum(type),
2324 if (!HeapTupleIsValid(typeTuple))
2325 elog(ERROR, "cache lookup failed for type %u", type);
2326 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2328 if (!pt->typisdefined)
2330 (errcode(ERRCODE_UNDEFINED_OBJECT),
2331 errmsg("type %s is only a shell",
2332 format_type_be(type))));
2333 if (!OidIsValid(pt->typoutput))
2335 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2336 errmsg("no output function available for type %s",
2337 format_type_be(type))));
2339 *typOutput = pt->typoutput;
2340 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2342 ReleaseSysCache(typeTuple);
2346 * getTypeBinaryInputInfo
2348 * Get info needed for binary input of values of a type
2351 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2353 HeapTuple typeTuple;
2356 typeTuple = SearchSysCache(TYPEOID,
2357 ObjectIdGetDatum(type),
2359 if (!HeapTupleIsValid(typeTuple))
2360 elog(ERROR, "cache lookup failed for type %u", type);
2361 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2363 if (!pt->typisdefined)
2365 (errcode(ERRCODE_UNDEFINED_OBJECT),
2366 errmsg("type %s is only a shell",
2367 format_type_be(type))));
2368 if (!OidIsValid(pt->typreceive))
2370 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2371 errmsg("no binary input function available for type %s",
2372 format_type_be(type))));
2374 *typReceive = pt->typreceive;
2375 *typIOParam = getTypeIOParam(typeTuple);
2377 ReleaseSysCache(typeTuple);
2381 * getTypeBinaryOutputInfo
2383 * Get info needed for binary output of values of a type
2386 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2388 HeapTuple typeTuple;
2391 typeTuple = SearchSysCache(TYPEOID,
2392 ObjectIdGetDatum(type),
2394 if (!HeapTupleIsValid(typeTuple))
2395 elog(ERROR, "cache lookup failed for type %u", type);
2396 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2398 if (!pt->typisdefined)
2400 (errcode(ERRCODE_UNDEFINED_OBJECT),
2401 errmsg("type %s is only a shell",
2402 format_type_be(type))));
2403 if (!OidIsValid(pt->typsend))
2405 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2406 errmsg("no binary output function available for type %s",
2407 format_type_be(type))));
2409 *typSend = pt->typsend;
2410 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2412 ReleaseSysCache(typeTuple);
2418 * Given the type OID, return the type's typmodin procedure, if any.
2421 get_typmodin(Oid typid)
2425 tp = SearchSysCache(TYPEOID,
2426 ObjectIdGetDatum(typid),
2428 if (HeapTupleIsValid(tp))
2430 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2433 result = typtup->typmodin;
2434 ReleaseSysCache(tp);
2445 * Given the type OID, return the type's typmodout procedure, if any.
2448 get_typmodout(Oid typid)
2452 tp = SearchSysCache(TYPEOID,
2453 ObjectIdGetDatum(typid),
2455 if (HeapTupleIsValid(tp))
2457 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2460 result = typtup->typmodout;
2461 ReleaseSysCache(tp);
2467 #endif /* NOT_USED */
2470 /* ---------- STATISTICS CACHE ---------- */
2475 * Given the table and attribute number of a column, get the average
2476 * width of entries in the column. Return zero if no data available.
2479 get_attavgwidth(Oid relid, AttrNumber attnum)
2483 tp = SearchSysCache(STATRELATT,
2484 ObjectIdGetDatum(relid),
2485 Int16GetDatum(attnum),
2487 if (HeapTupleIsValid(tp))
2489 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2491 ReleaseSysCache(tp);
2501 * Extract the contents of a "slot" of a pg_statistic tuple.
2502 * Returns TRUE if requested slot type was found, else FALSE.
2504 * Unlike other routines in this file, this takes a pointer to an
2505 * already-looked-up tuple in the pg_statistic cache. We do this since
2506 * most callers will want to extract more than one value from the cache
2507 * entry, and we don't want to repeat the cache lookup unnecessarily.
2509 * statstuple: pg_statistics tuple to be examined.
2510 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2511 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2512 * reqkind: STAKIND code for desired statistics slot kind.
2513 * reqop: STAOP value wanted, or InvalidOid if don't care.
2514 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2515 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2517 * If assigned, values and numbers are set to point to palloc'd arrays.
2518 * If the attribute type is pass-by-reference, the values referenced by
2519 * the values array are themselves palloc'd. The palloc'd stuff can be
2520 * freed by calling free_attstatsslot.
2523 get_attstatsslot(HeapTuple statstuple,
2524 Oid atttype, int32 atttypmod,
2525 int reqkind, Oid reqop,
2526 Datum **values, int *nvalues,
2527 float4 **numbers, int *nnumbers)
2529 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2534 ArrayType *statarray;
2536 HeapTuple typeTuple;
2537 Form_pg_type typeForm;
2539 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2541 if ((&stats->stakind1)[i] == reqkind &&
2542 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2545 if (i >= STATISTIC_NUM_SLOTS)
2546 return false; /* not there */
2550 val = SysCacheGetAttr(STATRELATT, statstuple,
2551 Anum_pg_statistic_stavalues1 + i,
2554 elog(ERROR, "stavalues is null");
2555 statarray = DatumGetArrayTypeP(val);
2557 /* Need to get info about the array element type */
2558 typeTuple = SearchSysCache(TYPEOID,
2559 ObjectIdGetDatum(atttype),
2561 if (!HeapTupleIsValid(typeTuple))
2562 elog(ERROR, "cache lookup failed for type %u", atttype);
2563 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2565 /* Deconstruct array into Datum elements; NULLs not expected */
2566 deconstruct_array(statarray,
2571 values, NULL, nvalues);
2574 * If the element type is pass-by-reference, we now have a bunch of
2575 * Datums that are pointers into the syscache value. Copy them to
2576 * avoid problems if syscache decides to drop the entry.
2578 if (!typeForm->typbyval)
2580 for (j = 0; j < *nvalues; j++)
2582 (*values)[j] = datumCopy((*values)[j],
2588 ReleaseSysCache(typeTuple);
2591 * Free statarray if it's a detoasted copy.
2593 if ((Pointer) statarray != DatumGetPointer(val))
2599 val = SysCacheGetAttr(STATRELATT, statstuple,
2600 Anum_pg_statistic_stanumbers1 + i,
2603 elog(ERROR, "stanumbers is null");
2604 statarray = DatumGetArrayTypeP(val);
2607 * We expect the array to be a 1-D float4 array; verify that. We don't
2608 * need to use deconstruct_array() since the array data is just going
2609 * to look like a C array of float4 values.
2611 narrayelem = ARR_DIMS(statarray)[0];
2612 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2613 ARR_HASNULL(statarray) ||
2614 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2615 elog(ERROR, "stanumbers is not a 1-D float4 array");
2616 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2617 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2618 *nnumbers = narrayelem;
2621 * Free statarray if it's a detoasted copy.
2623 if ((Pointer) statarray != DatumGetPointer(val))
2632 * Free data allocated by get_attstatsslot
2634 * atttype need be valid only if values != NULL.
2637 free_attstatsslot(Oid atttype,
2638 Datum *values, int nvalues,
2639 float4 *numbers, int nnumbers)
2643 if (!get_typbyval(atttype))
2647 for (i = 0; i < nvalues; i++)
2648 pfree(DatumGetPointer(values[i]));
2656 /* ---------- PG_NAMESPACE CACHE ---------- */
2659 * get_namespace_name
2660 * Returns the name of a given namespace
2662 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2665 get_namespace_name(Oid nspid)
2669 tp = SearchSysCache(NAMESPACEOID,
2670 ObjectIdGetDatum(nspid),
2672 if (HeapTupleIsValid(tp))
2674 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2677 result = pstrdup(NameStr(nsptup->nspname));
2678 ReleaseSysCache(tp);
2685 /* ---------- PG_AUTHID CACHE ---------- */
2689 * Given a role name, look up the role's OID.
2690 * Returns InvalidOid if no such role.
2693 get_roleid(const char *rolname)
2695 return GetSysCacheOid(AUTHNAME,
2696 PointerGetDatum(rolname),
2701 * get_roleid_checked
2702 * Given a role name, look up the role's OID.
2703 * ereports if no such role.
2706 get_roleid_checked(const char *rolname)
2710 roleid = get_roleid(rolname);
2711 if (!OidIsValid(roleid))
2713 (errcode(ERRCODE_UNDEFINED_OBJECT),
2714 errmsg("role \"%s\" does not exist", rolname)));