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.159 2008/08/02 21:32:00 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 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
260 * Returns InvalidOid if no matching equality operator can be found.
261 * (This indicates that the operator is not a valid ordering operator.)
264 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
266 Oid result = InvalidOid;
271 /* Find the operator in pg_amop */
272 if (get_ordering_op_properties(opno,
273 &opfamily, &opcintype, &strategy))
275 /* Found a suitable opfamily, get matching equality operator */
276 result = get_opfamily_member(opfamily,
279 BTEqualStrategyNumber);
281 *reverse = (strategy == BTGreaterStrategyNumber);
288 * get_ordering_op_for_equality_op
289 * Get the OID of a datatype-specific btree ordering operator
290 * associated with an equality operator. (If there are multiple
291 * possibilities, assume any one will do.)
293 * This function is used when we have to sort data before unique-ifying,
294 * and don't much care which sorting op is used as long as it's compatible
295 * with the intended equality operator. Since we need a sorting operator,
296 * it should be single-data-type even if the given operator is cross-type.
297 * The caller specifies whether to find an op for the LHS or RHS data type.
299 * Returns InvalidOid if no matching ordering operator can be found.
302 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
304 Oid result = InvalidOid;
309 * Search pg_amop to see if the target operator is registered as the "="
310 * operator of any btree opfamily.
312 catlist = SearchSysCacheList(AMOPOPID, 1,
313 ObjectIdGetDatum(opno),
316 for (i = 0; i < catlist->n_members; i++)
318 HeapTuple tuple = &catlist->members[i]->tuple;
319 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
322 if (aform->amopmethod != BTREE_AM_OID)
325 if (aform->amopstrategy == BTEqualStrategyNumber)
327 /* Found a suitable opfamily, get matching ordering operator */
330 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
331 result = get_opfamily_member(aform->amopfamily,
333 BTLessStrategyNumber);
334 if (OidIsValid(result))
336 /* failure probably shouldn't happen, but keep looking if so */
340 ReleaseSysCacheList(catlist);
346 * get_mergejoin_opfamilies
347 * Given a putatively mergejoinable operator, return a list of the OIDs
348 * of the btree opfamilies in which it represents equality.
350 * It is possible (though at present unusual) for an operator to be equality
351 * in more than one opfamily, hence the result is a list. This also lets us
352 * return NIL if the operator is not found in any opfamilies.
354 * The planner currently uses simple equal() tests to compare the lists
355 * returned by this function, which makes the list order relevant, though
356 * strictly speaking it should not be. Because of the way syscache list
357 * searches are handled, in normal operation the result will be sorted by OID
358 * so everything works fine. If running with system index usage disabled,
359 * the result ordering is unspecified and hence the planner might fail to
360 * recognize optimization opportunities ... but that's hardly a scenario in
361 * which performance is good anyway, so there's no point in expending code
362 * or cycles here to guarantee the ordering in that case.
365 get_mergejoin_opfamilies(Oid opno)
372 * Search pg_amop to see if the target operator is registered as the "="
373 * operator of any btree opfamily.
375 catlist = SearchSysCacheList(AMOPOPID, 1,
376 ObjectIdGetDatum(opno),
379 for (i = 0; i < catlist->n_members; i++)
381 HeapTuple tuple = &catlist->members[i]->tuple;
382 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
384 /* must be btree equality */
385 if (aform->amopmethod == BTREE_AM_OID &&
386 aform->amopstrategy == BTEqualStrategyNumber)
387 result = lappend_oid(result, aform->amopfamily);
390 ReleaseSysCacheList(catlist);
396 * get_compatible_hash_operators
397 * Get the OID(s) of hash equality operator(s) compatible with the given
398 * operator, but operating on its LHS and/or RHS datatype.
400 * An operator for the LHS type is sought and returned into *lhs_opno if
401 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
402 * and returned into *rhs_opno if rhs_opno isn't NULL.
404 * If the given operator is not cross-type, the results should be the same
405 * operator, but in cross-type situations they will be different.
407 * Returns true if able to find the requested operator(s), false if not.
408 * (This indicates that the operator should not have been marked oprcanhash.)
411 get_compatible_hash_operators(Oid opno,
412 Oid *lhs_opno, Oid *rhs_opno)
418 /* Ensure output args are initialized on failure */
420 *lhs_opno = InvalidOid;
422 *rhs_opno = InvalidOid;
425 * Search pg_amop to see if the target operator is registered as the "="
426 * operator of any hash opfamily. If the operator is registered in
427 * multiple opfamilies, assume we can use any one.
429 catlist = SearchSysCacheList(AMOPOPID, 1,
430 ObjectIdGetDatum(opno),
433 for (i = 0; i < catlist->n_members; i++)
435 HeapTuple tuple = &catlist->members[i]->tuple;
436 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
438 if (aform->amopmethod == HASH_AM_OID &&
439 aform->amopstrategy == HTEqualStrategyNumber)
441 /* No extra lookup needed if given operator is single-type */
442 if (aform->amoplefttype == aform->amoprighttype)
453 * Get the matching single-type operator(s). Failure probably
454 * shouldn't happen --- it implies a bogus opfamily --- but
455 * continue looking if so.
459 *lhs_opno = get_opfamily_member(aform->amopfamily,
462 HTEqualStrategyNumber);
463 if (!OidIsValid(*lhs_opno))
465 /* Matching LHS found, done if caller doesn't want RHS */
474 *rhs_opno = get_opfamily_member(aform->amopfamily,
475 aform->amoprighttype,
476 aform->amoprighttype,
477 HTEqualStrategyNumber);
478 if (!OidIsValid(*rhs_opno))
480 /* Forget any LHS operator from this opfamily */
482 *lhs_opno = InvalidOid;
485 /* Matching RHS found, so done */
492 ReleaseSysCacheList(catlist);
498 * get_op_hash_functions
499 * Get the OID(s) of hash support function(s) compatible with the given
500 * operator, operating on its LHS and/or RHS datatype as required.
502 * A function for the LHS type is sought and returned into *lhs_procno if
503 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
504 * and returned into *rhs_procno if rhs_procno isn't NULL.
506 * If the given operator is not cross-type, the results should be the same
507 * function, but in cross-type situations they will be different.
509 * Returns true if able to find the requested function(s), false if not.
510 * (This indicates that the operator should not have been marked oprcanhash.)
513 get_op_hash_functions(Oid opno,
514 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
520 /* Ensure output args are initialized on failure */
522 *lhs_procno = InvalidOid;
524 *rhs_procno = InvalidOid;
527 * Search pg_amop to see if the target operator is registered as the "="
528 * operator of any hash opfamily. If the operator is registered in
529 * multiple opfamilies, assume we can use any one.
531 catlist = SearchSysCacheList(AMOPOPID, 1,
532 ObjectIdGetDatum(opno),
535 for (i = 0; i < catlist->n_members; i++)
537 HeapTuple tuple = &catlist->members[i]->tuple;
538 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
540 if (aform->amopmethod == HASH_AM_OID &&
541 aform->amopstrategy == HTEqualStrategyNumber)
544 * Get the matching support function(s). Failure probably
545 * shouldn't happen --- it implies a bogus opfamily --- but
546 * continue looking if so.
550 *lhs_procno = get_opfamily_proc(aform->amopfamily,
554 if (!OidIsValid(*lhs_procno))
556 /* Matching LHS found, done if caller doesn't want RHS */
562 /* Only one lookup needed if given operator is single-type */
563 if (aform->amoplefttype == aform->amoprighttype)
565 *rhs_procno = *lhs_procno;
572 *rhs_procno = get_opfamily_proc(aform->amopfamily,
573 aform->amoprighttype,
574 aform->amoprighttype,
576 if (!OidIsValid(*rhs_procno))
578 /* Forget any LHS function from this opfamily */
580 *lhs_procno = InvalidOid;
583 /* Matching RHS found, so done */
590 ReleaseSysCacheList(catlist);
596 * get_op_btree_interpretation
597 * Given an operator's OID, find out which btree opfamilies it belongs to,
598 * and what strategy number it has within each one. The results are
599 * returned as an OID list and a parallel integer list.
601 * In addition to the normal btree operators, we consider a <> operator to be
602 * a "member" of an opfamily if its negator is an equality operator of the
603 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
606 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
616 * Find all the pg_amop entries containing the operator.
618 catlist = SearchSysCacheList(AMOPOPID, 1,
619 ObjectIdGetDatum(opno),
623 * If we can't find any opfamily containing the op, perhaps it is a <>
624 * operator. See if it has a negator that is in an opfamily.
627 if (catlist->n_members == 0)
629 Oid op_negator = get_negator(opno);
631 if (OidIsValid(op_negator))
634 ReleaseSysCacheList(catlist);
635 catlist = SearchSysCacheList(AMOPOPID, 1,
636 ObjectIdGetDatum(op_negator),
641 /* Now search the opfamilies */
642 for (i = 0; i < catlist->n_members; i++)
644 HeapTuple op_tuple = &catlist->members[i]->tuple;
645 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
647 StrategyNumber op_strategy;
650 if (op_form->amopmethod != BTREE_AM_OID)
653 /* Get the operator's btree strategy number */
654 opfamily_id = op_form->amopfamily;
655 op_strategy = (StrategyNumber) op_form->amopstrategy;
656 Assert(op_strategy >= 1 && op_strategy <= 5);
660 /* Only consider negators that are = */
661 if (op_strategy != BTEqualStrategyNumber)
663 op_strategy = ROWCOMPARE_NE;
666 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
667 *opstrats = lappend_int(*opstrats, op_strategy);
670 ReleaseSysCacheList(catlist);
674 * equality_ops_are_compatible
675 * Return TRUE if the two given equality operators have compatible
678 * This is trivially true if they are the same operator. Otherwise,
679 * we look to see if they can be found in the same btree or hash opfamily.
680 * Either finding allows us to assume that they have compatible notions
681 * of equality. (The reason we need to do these pushups is that one might
682 * be a cross-type operator; for instance int24eq vs int4eq.)
685 equality_ops_are_compatible(Oid opno1, Oid opno2)
691 /* Easy if they're the same operator */
696 * We search through all the pg_amop entries for opno1.
698 catlist = SearchSysCacheList(AMOPOPID, 1,
699 ObjectIdGetDatum(opno1),
703 for (i = 0; i < catlist->n_members; i++)
705 HeapTuple op_tuple = &catlist->members[i]->tuple;
706 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
708 /* must be btree or hash */
709 if (op_form->amopmethod == BTREE_AM_OID ||
710 op_form->amopmethod == HASH_AM_OID)
712 if (op_in_opfamily(opno2, op_form->amopfamily))
720 ReleaseSysCacheList(catlist);
726 /* ---------- AMPROC CACHES ---------- */
730 * Get the OID of the specified support function
731 * for the specified opfamily and datatypes.
733 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
736 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
739 Form_pg_amproc amproc_tup;
742 tp = SearchSysCache(AMPROCNUM,
743 ObjectIdGetDatum(opfamily),
744 ObjectIdGetDatum(lefttype),
745 ObjectIdGetDatum(righttype),
746 Int16GetDatum(procnum));
747 if (!HeapTupleIsValid(tp))
749 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
750 result = amproc_tup->amproc;
756 /* ---------- ATTRIBUTE CACHES ---------- */
760 * Given the relation id and the attribute number,
761 * return the "attname" field from the attribute relation.
763 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
766 get_attname(Oid relid, AttrNumber attnum)
770 tp = SearchSysCache(ATTNUM,
771 ObjectIdGetDatum(relid),
772 Int16GetDatum(attnum),
774 if (HeapTupleIsValid(tp))
776 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
779 result = pstrdup(NameStr(att_tup->attname));
788 * get_relid_attribute_name
790 * Same as above routine get_attname(), except that error
791 * is handled by elog() instead of returning NULL.
794 get_relid_attribute_name(Oid relid, AttrNumber attnum)
798 attname = get_attname(relid, attnum);
800 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
808 * Given the relation id and the attribute name,
809 * return the "attnum" field from the attribute relation.
811 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
814 get_attnum(Oid relid, const char *attname)
818 tp = SearchSysCacheAttName(relid, attname);
819 if (HeapTupleIsValid(tp))
821 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
824 result = att_tup->attnum;
829 return InvalidAttrNumber;
835 * Given the relation OID and the attribute number with the relation,
836 * return the attribute type OID.
839 get_atttype(Oid relid, AttrNumber attnum)
843 tp = SearchSysCache(ATTNUM,
844 ObjectIdGetDatum(relid),
845 Int16GetDatum(attnum),
847 if (HeapTupleIsValid(tp))
849 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
852 result = att_tup->atttypid;
863 * Given the relation id and the attribute number,
864 * return the "atttypmod" field from the attribute relation.
867 get_atttypmod(Oid relid, AttrNumber attnum)
871 tp = SearchSysCache(ATTNUM,
872 ObjectIdGetDatum(relid),
873 Int16GetDatum(attnum),
875 if (HeapTupleIsValid(tp))
877 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
880 result = att_tup->atttypmod;
891 * A two-fer: given the relation id and the attribute number,
892 * fetch both type OID and atttypmod in a single cache lookup.
894 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
895 * raises an error if it can't obtain the information.
898 get_atttypetypmod(Oid relid, AttrNumber attnum,
899 Oid *typid, int32 *typmod)
902 Form_pg_attribute att_tup;
904 tp = SearchSysCache(ATTNUM,
905 ObjectIdGetDatum(relid),
906 Int16GetDatum(attnum),
908 if (!HeapTupleIsValid(tp))
909 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
911 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
913 *typid = att_tup->atttypid;
914 *typmod = att_tup->atttypmod;
918 /* ---------- CONSTRAINT CACHE ---------- */
921 * get_constraint_name
922 * Returns the name of a given pg_constraint entry.
924 * Returns a palloc'd copy of the string, or NULL if no such constraint.
926 * NOTE: since constraint name is not unique, be wary of code that uses this
927 * for anything except preparing error messages.
930 get_constraint_name(Oid conoid)
934 tp = SearchSysCache(CONSTROID,
935 ObjectIdGetDatum(conoid),
937 if (HeapTupleIsValid(tp))
939 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
942 result = pstrdup(NameStr(contup->conname));
950 /* ---------- OPCLASS CACHE ---------- */
955 * Returns the OID of the operator family the opclass belongs to.
958 get_opclass_family(Oid opclass)
961 Form_pg_opclass cla_tup;
964 tp = SearchSysCache(CLAOID,
965 ObjectIdGetDatum(opclass),
967 if (!HeapTupleIsValid(tp))
968 elog(ERROR, "cache lookup failed for opclass %u", opclass);
969 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
971 result = cla_tup->opcfamily;
977 * get_opclass_input_type
979 * Returns the OID of the datatype the opclass indexes.
982 get_opclass_input_type(Oid opclass)
985 Form_pg_opclass cla_tup;
988 tp = SearchSysCache(CLAOID,
989 ObjectIdGetDatum(opclass),
991 if (!HeapTupleIsValid(tp))
992 elog(ERROR, "cache lookup failed for opclass %u", opclass);
993 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
995 result = cla_tup->opcintype;
1000 /* ---------- OPERATOR CACHE ---------- */
1005 * Returns the regproc id of the routine used to implement an
1006 * operator given the operator oid.
1009 get_opcode(Oid opno)
1013 tp = SearchSysCache(OPEROID,
1014 ObjectIdGetDatum(opno),
1016 if (HeapTupleIsValid(tp))
1018 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1019 RegProcedure result;
1021 result = optup->oprcode;
1022 ReleaseSysCache(tp);
1026 return (RegProcedure) InvalidOid;
1031 * returns the name of the operator with the given opno
1033 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1036 get_opname(Oid opno)
1040 tp = SearchSysCache(OPEROID,
1041 ObjectIdGetDatum(opno),
1043 if (HeapTupleIsValid(tp))
1045 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1048 result = pstrdup(NameStr(optup->oprname));
1049 ReleaseSysCache(tp);
1059 * Returns the left and right input datatypes for an operator
1060 * (InvalidOid if not relevant).
1063 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1066 Form_pg_operator optup;
1068 tp = SearchSysCache(OPEROID,
1069 ObjectIdGetDatum(opno),
1071 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1072 elog(ERROR, "cache lookup failed for operator %u", opno);
1073 optup = (Form_pg_operator) GETSTRUCT(tp);
1074 *lefttype = optup->oprleft;
1075 *righttype = optup->oprright;
1076 ReleaseSysCache(tp);
1082 * Returns true if the operator is potentially mergejoinable. (The planner
1083 * will fail to find any mergejoin plans unless there are suitable btree
1084 * opfamily entries for this operator and associated sortops. The pg_operator
1085 * flag is just a hint to tell the planner whether to bother looking.)
1088 op_mergejoinable(Oid opno)
1091 bool result = false;
1093 tp = SearchSysCache(OPEROID,
1094 ObjectIdGetDatum(opno),
1096 if (HeapTupleIsValid(tp))
1098 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1100 result = optup->oprcanmerge;
1101 ReleaseSysCache(tp);
1109 * Returns true if the operator is hashjoinable. (There must be a suitable
1110 * hash opfamily entry for this operator if it is so marked.)
1113 op_hashjoinable(Oid opno)
1116 bool result = false;
1118 tp = SearchSysCache(OPEROID,
1119 ObjectIdGetDatum(opno),
1121 if (HeapTupleIsValid(tp))
1123 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1125 result = optup->oprcanhash;
1126 ReleaseSysCache(tp);
1134 * Get the proisstrict flag for the operator's underlying function.
1139 RegProcedure funcid = get_opcode(opno);
1141 if (funcid == (RegProcedure) InvalidOid)
1142 elog(ERROR, "operator %u does not exist", opno);
1144 return func_strict((Oid) funcid);
1150 * Get the provolatile flag for the operator's underlying function.
1153 op_volatile(Oid opno)
1155 RegProcedure funcid = get_opcode(opno);
1157 if (funcid == (RegProcedure) InvalidOid)
1158 elog(ERROR, "operator %u does not exist", opno);
1160 return func_volatile((Oid) funcid);
1166 * Returns the corresponding commutator of an operator.
1169 get_commutator(Oid opno)
1173 tp = SearchSysCache(OPEROID,
1174 ObjectIdGetDatum(opno),
1176 if (HeapTupleIsValid(tp))
1178 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1181 result = optup->oprcom;
1182 ReleaseSysCache(tp);
1192 * Returns the corresponding negator of an operator.
1195 get_negator(Oid opno)
1199 tp = SearchSysCache(OPEROID,
1200 ObjectIdGetDatum(opno),
1202 if (HeapTupleIsValid(tp))
1204 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1207 result = optup->oprnegate;
1208 ReleaseSysCache(tp);
1218 * Returns procedure id for computing selectivity of an operator.
1221 get_oprrest(Oid opno)
1225 tp = SearchSysCache(OPEROID,
1226 ObjectIdGetDatum(opno),
1228 if (HeapTupleIsValid(tp))
1230 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1231 RegProcedure result;
1233 result = optup->oprrest;
1234 ReleaseSysCache(tp);
1238 return (RegProcedure) InvalidOid;
1244 * Returns procedure id for computing selectivity of a join.
1247 get_oprjoin(Oid opno)
1251 tp = SearchSysCache(OPEROID,
1252 ObjectIdGetDatum(opno),
1254 if (HeapTupleIsValid(tp))
1256 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1257 RegProcedure result;
1259 result = optup->oprjoin;
1260 ReleaseSysCache(tp);
1264 return (RegProcedure) InvalidOid;
1267 /* ---------- FUNCTION CACHE ---------- */
1271 * returns the name of the function with the given funcid
1273 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1276 get_func_name(Oid funcid)
1280 tp = SearchSysCache(PROCOID,
1281 ObjectIdGetDatum(funcid),
1283 if (HeapTupleIsValid(tp))
1285 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1288 result = pstrdup(NameStr(functup->proname));
1289 ReleaseSysCache(tp);
1298 * Given procedure id, return the function's result type.
1301 get_func_rettype(Oid funcid)
1306 tp = SearchSysCache(PROCOID,
1307 ObjectIdGetDatum(funcid),
1309 if (!HeapTupleIsValid(tp))
1310 elog(ERROR, "cache lookup failed for function %u", funcid);
1312 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1313 ReleaseSysCache(tp);
1319 * Given procedure id, return the number of arguments.
1322 get_func_nargs(Oid funcid)
1327 tp = SearchSysCache(PROCOID,
1328 ObjectIdGetDatum(funcid),
1330 if (!HeapTupleIsValid(tp))
1331 elog(ERROR, "cache lookup failed for function %u", funcid);
1333 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1334 ReleaseSysCache(tp);
1339 * get_func_signature
1340 * Given procedure id, return the function's argument and result types.
1341 * (The return value is the result type.)
1343 * The arguments are returned as a palloc'd array.
1346 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1349 Form_pg_proc procstruct;
1352 tp = SearchSysCache(PROCOID,
1353 ObjectIdGetDatum(funcid),
1355 if (!HeapTupleIsValid(tp))
1356 elog(ERROR, "cache lookup failed for function %u", funcid);
1358 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1360 result = procstruct->prorettype;
1361 *nargs = (int) procstruct->pronargs;
1362 Assert(*nargs == procstruct->proargtypes.dim1);
1363 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1364 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1366 ReleaseSysCache(tp);
1372 * Given procedure id, return the function's proretset flag.
1375 get_func_retset(Oid funcid)
1380 tp = SearchSysCache(PROCOID,
1381 ObjectIdGetDatum(funcid),
1383 if (!HeapTupleIsValid(tp))
1384 elog(ERROR, "cache lookup failed for function %u", funcid);
1386 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1387 ReleaseSysCache(tp);
1393 * Given procedure id, return the function's proisstrict flag.
1396 func_strict(Oid funcid)
1401 tp = SearchSysCache(PROCOID,
1402 ObjectIdGetDatum(funcid),
1404 if (!HeapTupleIsValid(tp))
1405 elog(ERROR, "cache lookup failed for function %u", funcid);
1407 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1408 ReleaseSysCache(tp);
1414 * Given procedure id, return the function's provolatile flag.
1417 func_volatile(Oid funcid)
1422 tp = SearchSysCache(PROCOID,
1423 ObjectIdGetDatum(funcid),
1425 if (!HeapTupleIsValid(tp))
1426 elog(ERROR, "cache lookup failed for function %u", funcid);
1428 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1429 ReleaseSysCache(tp);
1435 * Given procedure id, return the function's procost field.
1438 get_func_cost(Oid funcid)
1443 tp = SearchSysCache(PROCOID,
1444 ObjectIdGetDatum(funcid),
1446 if (!HeapTupleIsValid(tp))
1447 elog(ERROR, "cache lookup failed for function %u", funcid);
1449 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1450 ReleaseSysCache(tp);
1456 * Given procedure id, return the function's prorows field.
1459 get_func_rows(Oid funcid)
1464 tp = SearchSysCache(PROCOID,
1465 ObjectIdGetDatum(funcid),
1467 if (!HeapTupleIsValid(tp))
1468 elog(ERROR, "cache lookup failed for function %u", funcid);
1470 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1471 ReleaseSysCache(tp);
1475 /* ---------- RELATION CACHE ---------- */
1479 * Given name and namespace of a relation, look up the OID.
1481 * Returns InvalidOid if there is no such relation.
1484 get_relname_relid(const char *relname, Oid relnamespace)
1486 return GetSysCacheOid(RELNAMENSP,
1487 PointerGetDatum(relname),
1488 ObjectIdGetDatum(relnamespace),
1496 * Returns the number of attributes for a given relation.
1499 get_relnatts(Oid relid)
1503 tp = SearchSysCache(RELOID,
1504 ObjectIdGetDatum(relid),
1506 if (HeapTupleIsValid(tp))
1508 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1511 result = reltup->relnatts;
1512 ReleaseSysCache(tp);
1516 return InvalidAttrNumber;
1522 * Returns the name of a given relation.
1524 * Returns a palloc'd copy of the string, or NULL if no such relation.
1526 * NOTE: since relation name is not unique, be wary of code that uses this
1527 * for anything except preparing error messages.
1530 get_rel_name(Oid relid)
1534 tp = SearchSysCache(RELOID,
1535 ObjectIdGetDatum(relid),
1537 if (HeapTupleIsValid(tp))
1539 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1542 result = pstrdup(NameStr(reltup->relname));
1543 ReleaseSysCache(tp);
1553 * Returns the pg_namespace OID associated with a given relation.
1556 get_rel_namespace(Oid relid)
1560 tp = SearchSysCache(RELOID,
1561 ObjectIdGetDatum(relid),
1563 if (HeapTupleIsValid(tp))
1565 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1568 result = reltup->relnamespace;
1569 ReleaseSysCache(tp);
1579 * Returns the pg_type OID associated with a given relation.
1581 * Note: not all pg_class entries have associated pg_type OIDs; so be
1582 * careful to check for InvalidOid result.
1585 get_rel_type_id(Oid relid)
1589 tp = SearchSysCache(RELOID,
1590 ObjectIdGetDatum(relid),
1592 if (HeapTupleIsValid(tp))
1594 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1597 result = reltup->reltype;
1598 ReleaseSysCache(tp);
1608 * Returns the relkind associated with a given relation.
1611 get_rel_relkind(Oid relid)
1615 tp = SearchSysCache(RELOID,
1616 ObjectIdGetDatum(relid),
1618 if (HeapTupleIsValid(tp))
1620 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1623 result = reltup->relkind;
1624 ReleaseSysCache(tp);
1632 * get_rel_tablespace
1634 * Returns the pg_tablespace OID associated with a given relation.
1636 * Note: InvalidOid might mean either that we couldn't find the relation,
1637 * or that it is in the database's default tablespace.
1640 get_rel_tablespace(Oid relid)
1644 tp = SearchSysCache(RELOID,
1645 ObjectIdGetDatum(relid),
1647 if (HeapTupleIsValid(tp))
1649 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1652 result = reltup->reltablespace;
1653 ReleaseSysCache(tp);
1661 /* ---------- TYPE CACHE ---------- */
1666 * Given the type OID, determine whether the type is defined
1667 * (if not, it's only a shell).
1670 get_typisdefined(Oid typid)
1674 tp = SearchSysCache(TYPEOID,
1675 ObjectIdGetDatum(typid),
1677 if (HeapTupleIsValid(tp))
1679 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1682 result = typtup->typisdefined;
1683 ReleaseSysCache(tp);
1693 * Given the type OID, return the length of the type.
1696 get_typlen(Oid typid)
1700 tp = SearchSysCache(TYPEOID,
1701 ObjectIdGetDatum(typid),
1703 if (HeapTupleIsValid(tp))
1705 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1708 result = typtup->typlen;
1709 ReleaseSysCache(tp);
1719 * Given the type OID, determine whether the type is returned by value or
1720 * not. Returns true if by value, false if by reference.
1723 get_typbyval(Oid typid)
1727 tp = SearchSysCache(TYPEOID,
1728 ObjectIdGetDatum(typid),
1730 if (HeapTupleIsValid(tp))
1732 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1735 result = typtup->typbyval;
1736 ReleaseSysCache(tp);
1746 * A two-fer: given the type OID, return both typlen and typbyval.
1748 * Since both pieces of info are needed to know how to copy a Datum,
1749 * many places need both. Might as well get them with one cache lookup
1750 * instead of two. Also, this routine raises an error instead of
1751 * returning a bogus value when given a bad type OID.
1754 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1757 Form_pg_type typtup;
1759 tp = SearchSysCache(TYPEOID,
1760 ObjectIdGetDatum(typid),
1762 if (!HeapTupleIsValid(tp))
1763 elog(ERROR, "cache lookup failed for type %u", typid);
1764 typtup = (Form_pg_type) GETSTRUCT(tp);
1765 *typlen = typtup->typlen;
1766 *typbyval = typtup->typbyval;
1767 ReleaseSysCache(tp);
1771 * get_typlenbyvalalign
1773 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1776 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1780 Form_pg_type typtup;
1782 tp = SearchSysCache(TYPEOID,
1783 ObjectIdGetDatum(typid),
1785 if (!HeapTupleIsValid(tp))
1786 elog(ERROR, "cache lookup failed for type %u", typid);
1787 typtup = (Form_pg_type) GETSTRUCT(tp);
1788 *typlen = typtup->typlen;
1789 *typbyval = typtup->typbyval;
1790 *typalign = typtup->typalign;
1791 ReleaseSysCache(tp);
1796 * Given a pg_type row, select the type OID to pass to I/O functions
1798 * Formerly, all I/O functions were passed pg_type.typelem as their second
1799 * parameter, but we now have a more complex rule about what to pass.
1800 * This knowledge is intended to be centralized here --- direct references
1801 * to typelem elsewhere in the code are wrong, if they are associated with
1802 * I/O calls and not with actual subscripting operations! (But see
1803 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1805 * As of PostgreSQL 8.1, output functions receive only the value itself
1806 * and not any auxiliary parameters, so the name of this routine is now
1807 * a bit of a misnomer ... it should be getTypeInputParam.
1810 getTypeIOParam(HeapTuple typeTuple)
1812 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1815 * Array types get their typelem as parameter; everybody else gets their
1816 * own type OID as parameter. (As of 8.2, domains must get their own OID
1817 * even if their base type is an array.)
1819 if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem))
1820 return typeStruct->typelem;
1822 return HeapTupleGetOid(typeTuple);
1828 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1829 * typdelim, typioparam, and IO function OID. The IO function
1830 * returned is controlled by IOFuncSelector
1833 get_type_io_data(Oid typid,
1834 IOFuncSelector which_func,
1842 HeapTuple typeTuple;
1843 Form_pg_type typeStruct;
1846 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1847 * use array_in and array_out during bootstrap.
1849 if (IsBootstrapProcessingMode())
1854 boot_get_type_io_data(typid,
1871 elog(ERROR, "binary I/O not supported during bootstrap");
1877 typeTuple = SearchSysCache(TYPEOID,
1878 ObjectIdGetDatum(typid),
1880 if (!HeapTupleIsValid(typeTuple))
1881 elog(ERROR, "cache lookup failed for type %u", typid);
1882 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1884 *typlen = typeStruct->typlen;
1885 *typbyval = typeStruct->typbyval;
1886 *typalign = typeStruct->typalign;
1887 *typdelim = typeStruct->typdelim;
1888 *typioparam = getTypeIOParam(typeTuple);
1892 *func = typeStruct->typinput;
1895 *func = typeStruct->typoutput;
1897 case IOFunc_receive:
1898 *func = typeStruct->typreceive;
1901 *func = typeStruct->typsend;
1904 ReleaseSysCache(typeTuple);
1909 get_typalign(Oid typid)
1913 tp = SearchSysCache(TYPEOID,
1914 ObjectIdGetDatum(typid),
1916 if (HeapTupleIsValid(tp))
1918 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1921 result = typtup->typalign;
1922 ReleaseSysCache(tp);
1931 get_typstorage(Oid typid)
1935 tp = SearchSysCache(TYPEOID,
1936 ObjectIdGetDatum(typid),
1938 if (HeapTupleIsValid(tp))
1940 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1943 result = typtup->typstorage;
1944 ReleaseSysCache(tp);
1953 * Given a type OID, return the type's default value, if any.
1955 * The result is a palloc'd expression node tree, or NULL if there
1956 * is no defined default for the datatype.
1958 * NB: caller should be prepared to coerce result to correct datatype;
1959 * the returned expression tree might produce something of the wrong type.
1962 get_typdefault(Oid typid)
1964 HeapTuple typeTuple;
1970 typeTuple = SearchSysCache(TYPEOID,
1971 ObjectIdGetDatum(typid),
1973 if (!HeapTupleIsValid(typeTuple))
1974 elog(ERROR, "cache lookup failed for type %u", typid);
1975 type = (Form_pg_type) GETSTRUCT(typeTuple);
1978 * typdefault and typdefaultbin are potentially null, so don't try to
1979 * access 'em as struct fields. Must do it the hard way with
1982 datum = SysCacheGetAttr(TYPEOID,
1984 Anum_pg_type_typdefaultbin,
1989 /* We have an expression default */
1990 expr = stringToNode(TextDatumGetCString(datum));
1994 /* Perhaps we have a plain literal default */
1995 datum = SysCacheGetAttr(TYPEOID,
1997 Anum_pg_type_typdefault,
2002 char *strDefaultVal;
2004 /* Convert text datum to C string */
2005 strDefaultVal = TextDatumGetCString(datum);
2006 /* Convert C string to a value of the given type */
2007 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2008 getTypeIOParam(typeTuple), -1);
2009 /* Build a Const node containing the value */
2010 expr = (Node *) makeConst(typid,
2016 pfree(strDefaultVal);
2025 ReleaseSysCache(typeTuple);
2032 * If the given type is a domain, return its base type;
2033 * otherwise return the type's own OID.
2036 getBaseType(Oid typid)
2040 return getBaseTypeAndTypmod(typid, &typmod);
2044 * getBaseTypeAndTypmod
2045 * If the given type is a domain, return its base type and typmod;
2046 * otherwise return the type's own OID, and leave *typmod unchanged.
2048 * Note that the "applied typmod" should be -1 for every domain level
2049 * above the bottommost; therefore, if the passed-in typid is indeed
2050 * a domain, *typmod should be -1.
2053 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2056 * We loop to find the bottom base type in a stack of domains.
2061 Form_pg_type typTup;
2063 tup = SearchSysCache(TYPEOID,
2064 ObjectIdGetDatum(typid),
2066 if (!HeapTupleIsValid(tup))
2067 elog(ERROR, "cache lookup failed for type %u", typid);
2068 typTup = (Form_pg_type) GETSTRUCT(tup);
2069 if (typTup->typtype != TYPTYPE_DOMAIN)
2071 /* Not a domain, so done */
2072 ReleaseSysCache(tup);
2076 Assert(*typmod == -1);
2077 typid = typTup->typbasetype;
2078 *typmod = typTup->typtypmod;
2080 ReleaseSysCache(tup);
2089 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2090 * estimate the average width of values of the type. This is used by
2091 * the planner, which doesn't require absolutely correct results;
2092 * it's OK (and expected) to guess if we don't know for sure.
2095 get_typavgwidth(Oid typid, int32 typmod)
2097 int typlen = get_typlen(typid);
2101 * Easy if it's a fixed-width type
2107 * type_maximum_size knows the encoding of typmod for some datatypes;
2108 * don't duplicate that knowledge here.
2110 maxwidth = type_maximum_size(typid, typmod);
2114 * For BPCHAR, the max width is also the only width. Otherwise we
2115 * need to guess about the typical data width given the max. A sliding
2116 * scale for percentage of max width seems reasonable.
2118 if (typid == BPCHAROID)
2121 return maxwidth; /* assume full width */
2122 if (maxwidth < 1000)
2123 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2126 * Beyond 1000, assume we're looking at something like
2127 * "varchar(10000)" where the limit isn't actually reached often, and
2128 * use a fixed estimate.
2130 return 32 + (1000 - 32) / 2;
2134 * Ooops, we have no idea ... wild guess time.
2142 * Given the type OID, find if it is a basic type, a complex type, etc.
2143 * It returns the null char if the cache lookup fails...
2146 get_typtype(Oid typid)
2150 tp = SearchSysCache(TYPEOID,
2151 ObjectIdGetDatum(typid),
2153 if (HeapTupleIsValid(tp))
2155 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2158 result = typtup->typtype;
2159 ReleaseSysCache(tp);
2169 * Convenience function to determine whether a type OID represents
2170 * a "rowtype" type --- either RECORD or a named composite type.
2173 type_is_rowtype(Oid typid)
2175 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2180 * Returns true if the given type is an enum type.
2183 type_is_enum(Oid typid)
2185 return (get_typtype(typid) == TYPTYPE_ENUM);
2189 * get_type_category_preferred
2191 * Given the type OID, fetch its category and preferred-type status.
2192 * Throws error on failure.
2195 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2198 Form_pg_type typtup;
2200 tp = SearchSysCache(TYPEOID,
2201 ObjectIdGetDatum(typid),
2203 if (!HeapTupleIsValid(tp))
2204 elog(ERROR, "cache lookup failed for type %u", typid);
2205 typtup = (Form_pg_type) GETSTRUCT(tp);
2206 *typcategory = typtup->typcategory;
2207 *typispreferred = typtup->typispreferred;
2208 ReleaseSysCache(tp);
2214 * Given the type OID, get the typrelid (InvalidOid if not a complex
2218 get_typ_typrelid(Oid typid)
2222 tp = SearchSysCache(TYPEOID,
2223 ObjectIdGetDatum(typid),
2225 if (HeapTupleIsValid(tp))
2227 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2230 result = typtup->typrelid;
2231 ReleaseSysCache(tp);
2241 * Given the type OID, get the typelem (InvalidOid if not an array type).
2243 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2244 * returned if the input is a fixed-length array type.
2247 get_element_type(Oid typid)
2251 tp = SearchSysCache(TYPEOID,
2252 ObjectIdGetDatum(typid),
2254 if (HeapTupleIsValid(tp))
2256 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2259 if (typtup->typlen == -1)
2260 result = typtup->typelem;
2262 result = InvalidOid;
2263 ReleaseSysCache(tp);
2273 * Given the type OID, get the corresponding "true" array type.
2274 * Returns InvalidOid if no array type can be found.
2277 get_array_type(Oid typid)
2280 Oid result = InvalidOid;
2282 tp = SearchSysCache(TYPEOID,
2283 ObjectIdGetDatum(typid),
2285 if (HeapTupleIsValid(tp))
2287 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2288 ReleaseSysCache(tp);
2296 * Get info needed for converting values of a type to internal form
2299 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2301 HeapTuple typeTuple;
2304 typeTuple = SearchSysCache(TYPEOID,
2305 ObjectIdGetDatum(type),
2307 if (!HeapTupleIsValid(typeTuple))
2308 elog(ERROR, "cache lookup failed for type %u", type);
2309 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2311 if (!pt->typisdefined)
2313 (errcode(ERRCODE_UNDEFINED_OBJECT),
2314 errmsg("type %s is only a shell",
2315 format_type_be(type))));
2316 if (!OidIsValid(pt->typinput))
2318 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2319 errmsg("no input function available for type %s",
2320 format_type_be(type))));
2322 *typInput = pt->typinput;
2323 *typIOParam = getTypeIOParam(typeTuple);
2325 ReleaseSysCache(typeTuple);
2331 * Get info needed for printing values of a type
2334 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2336 HeapTuple typeTuple;
2339 typeTuple = SearchSysCache(TYPEOID,
2340 ObjectIdGetDatum(type),
2342 if (!HeapTupleIsValid(typeTuple))
2343 elog(ERROR, "cache lookup failed for type %u", type);
2344 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2346 if (!pt->typisdefined)
2348 (errcode(ERRCODE_UNDEFINED_OBJECT),
2349 errmsg("type %s is only a shell",
2350 format_type_be(type))));
2351 if (!OidIsValid(pt->typoutput))
2353 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2354 errmsg("no output function available for type %s",
2355 format_type_be(type))));
2357 *typOutput = pt->typoutput;
2358 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2360 ReleaseSysCache(typeTuple);
2364 * getTypeBinaryInputInfo
2366 * Get info needed for binary input of values of a type
2369 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2371 HeapTuple typeTuple;
2374 typeTuple = SearchSysCache(TYPEOID,
2375 ObjectIdGetDatum(type),
2377 if (!HeapTupleIsValid(typeTuple))
2378 elog(ERROR, "cache lookup failed for type %u", type);
2379 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2381 if (!pt->typisdefined)
2383 (errcode(ERRCODE_UNDEFINED_OBJECT),
2384 errmsg("type %s is only a shell",
2385 format_type_be(type))));
2386 if (!OidIsValid(pt->typreceive))
2388 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2389 errmsg("no binary input function available for type %s",
2390 format_type_be(type))));
2392 *typReceive = pt->typreceive;
2393 *typIOParam = getTypeIOParam(typeTuple);
2395 ReleaseSysCache(typeTuple);
2399 * getTypeBinaryOutputInfo
2401 * Get info needed for binary output of values of a type
2404 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2406 HeapTuple typeTuple;
2409 typeTuple = SearchSysCache(TYPEOID,
2410 ObjectIdGetDatum(type),
2412 if (!HeapTupleIsValid(typeTuple))
2413 elog(ERROR, "cache lookup failed for type %u", type);
2414 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2416 if (!pt->typisdefined)
2418 (errcode(ERRCODE_UNDEFINED_OBJECT),
2419 errmsg("type %s is only a shell",
2420 format_type_be(type))));
2421 if (!OidIsValid(pt->typsend))
2423 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2424 errmsg("no binary output function available for type %s",
2425 format_type_be(type))));
2427 *typSend = pt->typsend;
2428 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2430 ReleaseSysCache(typeTuple);
2436 * Given the type OID, return the type's typmodin procedure, if any.
2439 get_typmodin(Oid typid)
2443 tp = SearchSysCache(TYPEOID,
2444 ObjectIdGetDatum(typid),
2446 if (HeapTupleIsValid(tp))
2448 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2451 result = typtup->typmodin;
2452 ReleaseSysCache(tp);
2463 * Given the type OID, return the type's typmodout procedure, if any.
2466 get_typmodout(Oid typid)
2470 tp = SearchSysCache(TYPEOID,
2471 ObjectIdGetDatum(typid),
2473 if (HeapTupleIsValid(tp))
2475 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2478 result = typtup->typmodout;
2479 ReleaseSysCache(tp);
2485 #endif /* NOT_USED */
2488 /* ---------- STATISTICS CACHE ---------- */
2493 * Given the table and attribute number of a column, get the average
2494 * width of entries in the column. Return zero if no data available.
2497 get_attavgwidth(Oid relid, AttrNumber attnum)
2501 tp = SearchSysCache(STATRELATT,
2502 ObjectIdGetDatum(relid),
2503 Int16GetDatum(attnum),
2505 if (HeapTupleIsValid(tp))
2507 int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2509 ReleaseSysCache(tp);
2519 * Extract the contents of a "slot" of a pg_statistic tuple.
2520 * Returns TRUE if requested slot type was found, else FALSE.
2522 * Unlike other routines in this file, this takes a pointer to an
2523 * already-looked-up tuple in the pg_statistic cache. We do this since
2524 * most callers will want to extract more than one value from the cache
2525 * entry, and we don't want to repeat the cache lookup unnecessarily.
2527 * statstuple: pg_statistics tuple to be examined.
2528 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2529 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2530 * reqkind: STAKIND code for desired statistics slot kind.
2531 * reqop: STAOP value wanted, or InvalidOid if don't care.
2532 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2533 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2535 * If assigned, values and numbers are set to point to palloc'd arrays.
2536 * If the attribute type is pass-by-reference, the values referenced by
2537 * the values array are themselves palloc'd. The palloc'd stuff can be
2538 * freed by calling free_attstatsslot.
2541 get_attstatsslot(HeapTuple statstuple,
2542 Oid atttype, int32 atttypmod,
2543 int reqkind, Oid reqop,
2544 Datum **values, int *nvalues,
2545 float4 **numbers, int *nnumbers)
2547 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2552 ArrayType *statarray;
2554 HeapTuple typeTuple;
2555 Form_pg_type typeForm;
2557 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2559 if ((&stats->stakind1)[i] == reqkind &&
2560 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2563 if (i >= STATISTIC_NUM_SLOTS)
2564 return false; /* not there */
2568 val = SysCacheGetAttr(STATRELATT, statstuple,
2569 Anum_pg_statistic_stavalues1 + i,
2572 elog(ERROR, "stavalues is null");
2573 statarray = DatumGetArrayTypeP(val);
2575 /* Need to get info about the array element type */
2576 typeTuple = SearchSysCache(TYPEOID,
2577 ObjectIdGetDatum(atttype),
2579 if (!HeapTupleIsValid(typeTuple))
2580 elog(ERROR, "cache lookup failed for type %u", atttype);
2581 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2583 /* Deconstruct array into Datum elements; NULLs not expected */
2584 deconstruct_array(statarray,
2589 values, NULL, nvalues);
2592 * If the element type is pass-by-reference, we now have a bunch of
2593 * Datums that are pointers into the syscache value. Copy them to
2594 * avoid problems if syscache decides to drop the entry.
2596 if (!typeForm->typbyval)
2598 for (j = 0; j < *nvalues; j++)
2600 (*values)[j] = datumCopy((*values)[j],
2606 ReleaseSysCache(typeTuple);
2609 * Free statarray if it's a detoasted copy.
2611 if ((Pointer) statarray != DatumGetPointer(val))
2617 val = SysCacheGetAttr(STATRELATT, statstuple,
2618 Anum_pg_statistic_stanumbers1 + i,
2621 elog(ERROR, "stanumbers is null");
2622 statarray = DatumGetArrayTypeP(val);
2625 * We expect the array to be a 1-D float4 array; verify that. We don't
2626 * need to use deconstruct_array() since the array data is just going
2627 * to look like a C array of float4 values.
2629 narrayelem = ARR_DIMS(statarray)[0];
2630 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2631 ARR_HASNULL(statarray) ||
2632 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2633 elog(ERROR, "stanumbers is not a 1-D float4 array");
2634 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2635 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2636 *nnumbers = narrayelem;
2639 * Free statarray if it's a detoasted copy.
2641 if ((Pointer) statarray != DatumGetPointer(val))
2650 * Free data allocated by get_attstatsslot
2652 * atttype need be valid only if values != NULL.
2655 free_attstatsslot(Oid atttype,
2656 Datum *values, int nvalues,
2657 float4 *numbers, int nnumbers)
2661 if (!get_typbyval(atttype))
2665 for (i = 0; i < nvalues; i++)
2666 pfree(DatumGetPointer(values[i]));
2674 /* ---------- PG_NAMESPACE CACHE ---------- */
2677 * get_namespace_name
2678 * Returns the name of a given namespace
2680 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2683 get_namespace_name(Oid nspid)
2687 tp = SearchSysCache(NAMESPACEOID,
2688 ObjectIdGetDatum(nspid),
2690 if (HeapTupleIsValid(tp))
2692 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2695 result = pstrdup(NameStr(nsptup->nspname));
2696 ReleaseSysCache(tp);
2703 /* ---------- PG_AUTHID CACHE ---------- */
2707 * Given a role name, look up the role's OID.
2708 * Returns InvalidOid if no such role.
2711 get_roleid(const char *rolname)
2713 return GetSysCacheOid(AUTHNAME,
2714 PointerGetDatum(rolname),
2719 * get_roleid_checked
2720 * Given a role name, look up the role's OID.
2721 * ereports if no such role.
2724 get_roleid_checked(const char *rolname)
2728 roleid = get_roleid(rolname);
2729 if (!OidIsValid(roleid))
2731 (errcode(ERRCODE_UNDEFINED_OBJECT),
2732 errmsg("role \"%s\" does not exist", rolname)));