1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
18 #include "access/hash.h"
19 #include "access/nbtree.h"
20 #include "bootstrap/bootstrap.h"
21 #include "catalog/pg_amop.h"
22 #include "catalog/pg_amproc.h"
23 #include "catalog/pg_constraint.h"
24 #include "catalog/pg_namespace.h"
25 #include "catalog/pg_opclass.h"
26 #include "catalog/pg_operator.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_statistic.h"
29 #include "catalog/pg_type.h"
30 #include "miscadmin.h"
31 #include "nodes/makefuncs.h"
32 #include "utils/array.h"
33 #include "utils/builtins.h"
34 #include "utils/datum.h"
35 #include "utils/lsyscache.h"
36 #include "utils/syscache.h"
38 /* Hook for plugins to get control in get_attavgwidth() */
39 get_attavgwidth_hook_type get_attavgwidth_hook
= NULL
;
42 /* ---------- AMOP CACHES ---------- */
47 * Return t iff operator 'opno' is in operator family 'opfamily'.
50 op_in_opfamily(Oid opno
, Oid opfamily
)
52 return SearchSysCacheExists(AMOPOPID
,
53 ObjectIdGetDatum(opno
),
54 ObjectIdGetDatum(opfamily
),
59 * get_op_opfamily_strategy
61 * Get the operator's strategy number within the specified opfamily,
62 * or 0 if it's not a member of the opfamily.
65 get_op_opfamily_strategy(Oid opno
, Oid opfamily
)
68 Form_pg_amop amop_tup
;
71 tp
= SearchSysCache(AMOPOPID
,
72 ObjectIdGetDatum(opno
),
73 ObjectIdGetDatum(opfamily
),
75 if (!HeapTupleIsValid(tp
))
77 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
78 result
= amop_tup
->amopstrategy
;
84 * get_op_opfamily_properties
86 * Get the operator's strategy number and declared input data types
87 * within the specified opfamily.
89 * Caller should already have verified that opno is a member of opfamily,
90 * therefore we raise an error if the tuple is not found.
93 get_op_opfamily_properties(Oid opno
, Oid opfamily
,
99 Form_pg_amop amop_tup
;
101 tp
= SearchSysCache(AMOPOPID
,
102 ObjectIdGetDatum(opno
),
103 ObjectIdGetDatum(opfamily
),
105 if (!HeapTupleIsValid(tp
))
106 elog(ERROR
, "operator %u is not a member of opfamily %u",
108 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
109 *strategy
= amop_tup
->amopstrategy
;
110 *lefttype
= amop_tup
->amoplefttype
;
111 *righttype
= amop_tup
->amoprighttype
;
116 * get_opfamily_member
117 * Get the OID of the operator that implements the specified strategy
118 * with the specified datatypes for the specified opfamily.
120 * Returns InvalidOid if there is no pg_amop entry for the given keys.
123 get_opfamily_member(Oid opfamily
, Oid lefttype
, Oid righttype
,
127 Form_pg_amop amop_tup
;
130 tp
= SearchSysCache(AMOPSTRATEGY
,
131 ObjectIdGetDatum(opfamily
),
132 ObjectIdGetDatum(lefttype
),
133 ObjectIdGetDatum(righttype
),
134 Int16GetDatum(strategy
));
135 if (!HeapTupleIsValid(tp
))
137 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
138 result
= amop_tup
->amopopr
;
144 * get_ordering_op_properties
145 * Given the OID of an ordering operator (a btree "<" or ">" operator),
146 * determine its opfamily, its declared input datatype, and its
147 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
149 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
150 * (This indicates that the operator is not a valid ordering operator.)
152 * Note: the operator could be registered in multiple families, for example
153 * if someone were to build a "reverse sort" opfamily. This would result in
154 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
155 * or NULLS LAST, as well as inefficient planning due to failure to match up
156 * pathkeys that should be the same. So we want a determinate result here.
157 * Because of the way the syscache search works, we'll use the interpretation
158 * associated with the opfamily with smallest OID, which is probably
159 * determinate enough. Since there is no longer any particularly good reason
160 * to build reverse-sort opfamilies, it doesn't seem worth expending any
161 * additional effort on ensuring consistency.
164 get_ordering_op_properties(Oid opno
,
165 Oid
*opfamily
, Oid
*opcintype
, int16
*strategy
)
171 /* ensure outputs are initialized on failure */
172 *opfamily
= InvalidOid
;
173 *opcintype
= InvalidOid
;
177 * Search pg_amop to see if the target operator is registered as the "<"
178 * or ">" operator of any btree opfamily.
180 catlist
= SearchSysCacheList(AMOPOPID
, 1,
181 ObjectIdGetDatum(opno
),
184 for (i
= 0; i
< catlist
->n_members
; i
++)
186 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
187 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
190 if (aform
->amopmethod
!= BTREE_AM_OID
)
193 if (aform
->amopstrategy
== BTLessStrategyNumber
||
194 aform
->amopstrategy
== BTGreaterStrategyNumber
)
196 /* Found it ... should have consistent input types */
197 if (aform
->amoplefttype
== aform
->amoprighttype
)
199 /* Found a suitable opfamily, return info */
200 *opfamily
= aform
->amopfamily
;
201 *opcintype
= aform
->amoplefttype
;
202 *strategy
= aform
->amopstrategy
;
209 ReleaseSysCacheList(catlist
);
215 * get_compare_function_for_ordering_op
216 * Get the OID of the datatype-specific btree comparison function
217 * associated with an ordering operator (a "<" or ">" operator).
219 * *cmpfunc receives the comparison function OID.
220 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
221 * (indicating the comparison result must be negated before use).
223 * Returns TRUE if successful, FALSE if no btree function can be found.
224 * (This indicates that the operator is not a valid ordering operator.)
227 get_compare_function_for_ordering_op(Oid opno
, Oid
*cmpfunc
, bool *reverse
)
233 /* Find the operator in pg_amop */
234 if (get_ordering_op_properties(opno
,
235 &opfamily
, &opcintype
, &strategy
))
237 /* Found a suitable opfamily, get matching support function */
238 *cmpfunc
= get_opfamily_proc(opfamily
,
243 if (!OidIsValid(*cmpfunc
)) /* should not happen */
244 elog(ERROR
, "missing support function %d(%u,%u) in opfamily %u",
245 BTORDER_PROC
, opcintype
, opcintype
, opfamily
);
246 *reverse
= (strategy
== BTGreaterStrategyNumber
);
250 /* ensure outputs are set on failure */
251 *cmpfunc
= InvalidOid
;
258 * get_equality_op_for_ordering_op
259 * Get the OID of the datatype-specific btree equality operator
260 * associated with an ordering operator (a "<" or ">" operator).
262 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
265 * Returns InvalidOid if no matching equality operator can be found.
266 * (This indicates that the operator is not a valid ordering operator.)
269 get_equality_op_for_ordering_op(Oid opno
, bool *reverse
)
271 Oid result
= InvalidOid
;
276 /* Find the operator in pg_amop */
277 if (get_ordering_op_properties(opno
,
278 &opfamily
, &opcintype
, &strategy
))
280 /* Found a suitable opfamily, get matching equality operator */
281 result
= get_opfamily_member(opfamily
,
284 BTEqualStrategyNumber
);
286 *reverse
= (strategy
== BTGreaterStrategyNumber
);
293 * get_ordering_op_for_equality_op
294 * Get the OID of a datatype-specific btree ordering operator
295 * associated with an equality operator. (If there are multiple
296 * possibilities, assume any one will do.)
298 * This function is used when we have to sort data before unique-ifying,
299 * and don't much care which sorting op is used as long as it's compatible
300 * with the intended equality operator. Since we need a sorting operator,
301 * it should be single-data-type even if the given operator is cross-type.
302 * The caller specifies whether to find an op for the LHS or RHS data type.
304 * Returns InvalidOid if no matching ordering operator can be found.
307 get_ordering_op_for_equality_op(Oid opno
, bool use_lhs_type
)
309 Oid result
= InvalidOid
;
314 * Search pg_amop to see if the target operator is registered as the "="
315 * operator of any btree opfamily.
317 catlist
= SearchSysCacheList(AMOPOPID
, 1,
318 ObjectIdGetDatum(opno
),
321 for (i
= 0; i
< catlist
->n_members
; i
++)
323 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
324 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
327 if (aform
->amopmethod
!= BTREE_AM_OID
)
330 if (aform
->amopstrategy
== BTEqualStrategyNumber
)
332 /* Found a suitable opfamily, get matching ordering operator */
335 typid
= use_lhs_type
? aform
->amoplefttype
: aform
->amoprighttype
;
336 result
= get_opfamily_member(aform
->amopfamily
,
338 BTLessStrategyNumber
);
339 if (OidIsValid(result
))
341 /* failure probably shouldn't happen, but keep looking if so */
345 ReleaseSysCacheList(catlist
);
351 * get_mergejoin_opfamilies
352 * Given a putatively mergejoinable operator, return a list of the OIDs
353 * of the btree opfamilies in which it represents equality.
355 * It is possible (though at present unusual) for an operator to be equality
356 * in more than one opfamily, hence the result is a list. This also lets us
357 * return NIL if the operator is not found in any opfamilies.
359 * The planner currently uses simple equal() tests to compare the lists
360 * returned by this function, which makes the list order relevant, though
361 * strictly speaking it should not be. Because of the way syscache list
362 * searches are handled, in normal operation the result will be sorted by OID
363 * so everything works fine. If running with system index usage disabled,
364 * the result ordering is unspecified and hence the planner might fail to
365 * recognize optimization opportunities ... but that's hardly a scenario in
366 * which performance is good anyway, so there's no point in expending code
367 * or cycles here to guarantee the ordering in that case.
370 get_mergejoin_opfamilies(Oid opno
)
377 * Search pg_amop to see if the target operator is registered as the "="
378 * operator of any btree opfamily.
380 catlist
= SearchSysCacheList(AMOPOPID
, 1,
381 ObjectIdGetDatum(opno
),
384 for (i
= 0; i
< catlist
->n_members
; i
++)
386 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
387 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
389 /* must be btree equality */
390 if (aform
->amopmethod
== BTREE_AM_OID
&&
391 aform
->amopstrategy
== BTEqualStrategyNumber
)
392 result
= lappend_oid(result
, aform
->amopfamily
);
395 ReleaseSysCacheList(catlist
);
401 * get_compatible_hash_operators
402 * Get the OID(s) of hash equality operator(s) compatible with the given
403 * operator, but operating on its LHS and/or RHS datatype.
405 * An operator for the LHS type is sought and returned into *lhs_opno if
406 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
407 * and returned into *rhs_opno if rhs_opno isn't NULL.
409 * If the given operator is not cross-type, the results should be the same
410 * operator, but in cross-type situations they will be different.
412 * Returns true if able to find the requested operator(s), false if not.
413 * (This indicates that the operator should not have been marked oprcanhash.)
416 get_compatible_hash_operators(Oid opno
,
417 Oid
*lhs_opno
, Oid
*rhs_opno
)
423 /* Ensure output args are initialized on failure */
425 *lhs_opno
= InvalidOid
;
427 *rhs_opno
= InvalidOid
;
430 * Search pg_amop to see if the target operator is registered as the "="
431 * operator of any hash opfamily. If the operator is registered in
432 * multiple opfamilies, assume we can use any one.
434 catlist
= SearchSysCacheList(AMOPOPID
, 1,
435 ObjectIdGetDatum(opno
),
438 for (i
= 0; i
< catlist
->n_members
; i
++)
440 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
441 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
443 if (aform
->amopmethod
== HASH_AM_OID
&&
444 aform
->amopstrategy
== HTEqualStrategyNumber
)
446 /* No extra lookup needed if given operator is single-type */
447 if (aform
->amoplefttype
== aform
->amoprighttype
)
458 * Get the matching single-type operator(s). Failure probably
459 * shouldn't happen --- it implies a bogus opfamily --- but
460 * continue looking if so.
464 *lhs_opno
= get_opfamily_member(aform
->amopfamily
,
467 HTEqualStrategyNumber
);
468 if (!OidIsValid(*lhs_opno
))
470 /* Matching LHS found, done if caller doesn't want RHS */
479 *rhs_opno
= get_opfamily_member(aform
->amopfamily
,
480 aform
->amoprighttype
,
481 aform
->amoprighttype
,
482 HTEqualStrategyNumber
);
483 if (!OidIsValid(*rhs_opno
))
485 /* Forget any LHS operator from this opfamily */
487 *lhs_opno
= InvalidOid
;
490 /* Matching RHS found, so done */
497 ReleaseSysCacheList(catlist
);
503 * get_op_hash_functions
504 * Get the OID(s) of hash support function(s) compatible with the given
505 * operator, operating on its LHS and/or RHS datatype as required.
507 * A function for the LHS type is sought and returned into *lhs_procno if
508 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
509 * and returned into *rhs_procno if rhs_procno isn't NULL.
511 * If the given operator is not cross-type, the results should be the same
512 * function, but in cross-type situations they will be different.
514 * Returns true if able to find the requested function(s), false if not.
515 * (This indicates that the operator should not have been marked oprcanhash.)
518 get_op_hash_functions(Oid opno
,
519 RegProcedure
*lhs_procno
, RegProcedure
*rhs_procno
)
525 /* Ensure output args are initialized on failure */
527 *lhs_procno
= InvalidOid
;
529 *rhs_procno
= InvalidOid
;
532 * Search pg_amop to see if the target operator is registered as the "="
533 * operator of any hash opfamily. If the operator is registered in
534 * multiple opfamilies, assume we can use any one.
536 catlist
= SearchSysCacheList(AMOPOPID
, 1,
537 ObjectIdGetDatum(opno
),
540 for (i
= 0; i
< catlist
->n_members
; i
++)
542 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
543 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
545 if (aform
->amopmethod
== HASH_AM_OID
&&
546 aform
->amopstrategy
== HTEqualStrategyNumber
)
549 * Get the matching support function(s). Failure probably
550 * shouldn't happen --- it implies a bogus opfamily --- but
551 * continue looking if so.
555 *lhs_procno
= get_opfamily_proc(aform
->amopfamily
,
559 if (!OidIsValid(*lhs_procno
))
561 /* Matching LHS found, done if caller doesn't want RHS */
567 /* Only one lookup needed if given operator is single-type */
568 if (aform
->amoplefttype
== aform
->amoprighttype
)
570 *rhs_procno
= *lhs_procno
;
577 *rhs_procno
= get_opfamily_proc(aform
->amopfamily
,
578 aform
->amoprighttype
,
579 aform
->amoprighttype
,
581 if (!OidIsValid(*rhs_procno
))
583 /* Forget any LHS function from this opfamily */
585 *lhs_procno
= InvalidOid
;
588 /* Matching RHS found, so done */
595 ReleaseSysCacheList(catlist
);
601 * get_op_btree_interpretation
602 * Given an operator's OID, find out which btree opfamilies it belongs to,
603 * and what strategy number it has within each one. The results are
604 * returned as an OID list and a parallel integer list.
606 * In addition to the normal btree operators, we consider a <> operator to be
607 * a "member" of an opfamily if its negator is an equality operator of the
608 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
611 get_op_btree_interpretation(Oid opno
, List
**opfamilies
, List
**opstrats
)
621 * Find all the pg_amop entries containing the operator.
623 catlist
= SearchSysCacheList(AMOPOPID
, 1,
624 ObjectIdGetDatum(opno
),
628 * If we can't find any opfamily containing the op, perhaps it is a <>
629 * operator. See if it has a negator that is in an opfamily.
632 if (catlist
->n_members
== 0)
634 Oid op_negator
= get_negator(opno
);
636 if (OidIsValid(op_negator
))
639 ReleaseSysCacheList(catlist
);
640 catlist
= SearchSysCacheList(AMOPOPID
, 1,
641 ObjectIdGetDatum(op_negator
),
646 /* Now search the opfamilies */
647 for (i
= 0; i
< catlist
->n_members
; i
++)
649 HeapTuple op_tuple
= &catlist
->members
[i
]->tuple
;
650 Form_pg_amop op_form
= (Form_pg_amop
) GETSTRUCT(op_tuple
);
652 StrategyNumber op_strategy
;
655 if (op_form
->amopmethod
!= BTREE_AM_OID
)
658 /* Get the operator's btree strategy number */
659 opfamily_id
= op_form
->amopfamily
;
660 op_strategy
= (StrategyNumber
) op_form
->amopstrategy
;
661 Assert(op_strategy
>= 1 && op_strategy
<= 5);
665 /* Only consider negators that are = */
666 if (op_strategy
!= BTEqualStrategyNumber
)
668 op_strategy
= ROWCOMPARE_NE
;
671 *opfamilies
= lappend_oid(*opfamilies
, opfamily_id
);
672 *opstrats
= lappend_int(*opstrats
, op_strategy
);
675 ReleaseSysCacheList(catlist
);
679 * equality_ops_are_compatible
680 * Return TRUE if the two given equality operators have compatible
683 * This is trivially true if they are the same operator. Otherwise,
684 * we look to see if they can be found in the same btree or hash opfamily.
685 * Either finding allows us to assume that they have compatible notions
686 * of equality. (The reason we need to do these pushups is that one might
687 * be a cross-type operator; for instance int24eq vs int4eq.)
690 equality_ops_are_compatible(Oid opno1
, Oid opno2
)
696 /* Easy if they're the same operator */
701 * We search through all the pg_amop entries for opno1.
703 catlist
= SearchSysCacheList(AMOPOPID
, 1,
704 ObjectIdGetDatum(opno1
),
708 for (i
= 0; i
< catlist
->n_members
; i
++)
710 HeapTuple op_tuple
= &catlist
->members
[i
]->tuple
;
711 Form_pg_amop op_form
= (Form_pg_amop
) GETSTRUCT(op_tuple
);
713 /* must be btree or hash */
714 if (op_form
->amopmethod
== BTREE_AM_OID
||
715 op_form
->amopmethod
== HASH_AM_OID
)
717 if (op_in_opfamily(opno2
, op_form
->amopfamily
))
725 ReleaseSysCacheList(catlist
);
731 /* ---------- AMPROC CACHES ---------- */
735 * Get the OID of the specified support function
736 * for the specified opfamily and datatypes.
738 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
741 get_opfamily_proc(Oid opfamily
, Oid lefttype
, Oid righttype
, int16 procnum
)
744 Form_pg_amproc amproc_tup
;
747 tp
= SearchSysCache(AMPROCNUM
,
748 ObjectIdGetDatum(opfamily
),
749 ObjectIdGetDatum(lefttype
),
750 ObjectIdGetDatum(righttype
),
751 Int16GetDatum(procnum
));
752 if (!HeapTupleIsValid(tp
))
754 amproc_tup
= (Form_pg_amproc
) GETSTRUCT(tp
);
755 result
= amproc_tup
->amproc
;
761 /* ---------- ATTRIBUTE CACHES ---------- */
765 * Given the relation id and the attribute number,
766 * return the "attname" field from the attribute relation.
768 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
771 get_attname(Oid relid
, AttrNumber attnum
)
775 tp
= SearchSysCache(ATTNUM
,
776 ObjectIdGetDatum(relid
),
777 Int16GetDatum(attnum
),
779 if (HeapTupleIsValid(tp
))
781 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
784 result
= pstrdup(NameStr(att_tup
->attname
));
793 * get_relid_attribute_name
795 * Same as above routine get_attname(), except that error
796 * is handled by elog() instead of returning NULL.
799 get_relid_attribute_name(Oid relid
, AttrNumber attnum
)
803 attname
= get_attname(relid
, attnum
);
805 elog(ERROR
, "cache lookup failed for attribute %d of relation %u",
813 * Given the relation id and the attribute name,
814 * return the "attnum" field from the attribute relation.
816 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
819 get_attnum(Oid relid
, const char *attname
)
823 tp
= SearchSysCacheAttName(relid
, attname
);
824 if (HeapTupleIsValid(tp
))
826 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
829 result
= att_tup
->attnum
;
834 return InvalidAttrNumber
;
840 * Given the relation OID and the attribute number with the relation,
841 * return the attribute type OID.
844 get_atttype(Oid relid
, AttrNumber attnum
)
848 tp
= SearchSysCache(ATTNUM
,
849 ObjectIdGetDatum(relid
),
850 Int16GetDatum(attnum
),
852 if (HeapTupleIsValid(tp
))
854 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
857 result
= att_tup
->atttypid
;
868 * Given the relation id and the attribute number,
869 * return the "atttypmod" field from the attribute relation.
872 get_atttypmod(Oid relid
, AttrNumber attnum
)
876 tp
= SearchSysCache(ATTNUM
,
877 ObjectIdGetDatum(relid
),
878 Int16GetDatum(attnum
),
880 if (HeapTupleIsValid(tp
))
882 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
885 result
= att_tup
->atttypmod
;
896 * A two-fer: given the relation id and the attribute number,
897 * fetch both type OID and atttypmod in a single cache lookup.
899 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
900 * raises an error if it can't obtain the information.
903 get_atttypetypmod(Oid relid
, AttrNumber attnum
,
904 Oid
*typid
, int32
*typmod
)
907 Form_pg_attribute att_tup
;
909 tp
= SearchSysCache(ATTNUM
,
910 ObjectIdGetDatum(relid
),
911 Int16GetDatum(attnum
),
913 if (!HeapTupleIsValid(tp
))
914 elog(ERROR
, "cache lookup failed for attribute %d of relation %u",
916 att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
918 *typid
= att_tup
->atttypid
;
919 *typmod
= att_tup
->atttypmod
;
923 /* ---------- CONSTRAINT CACHE ---------- */
926 * get_constraint_name
927 * Returns the name of a given pg_constraint entry.
929 * Returns a palloc'd copy of the string, or NULL if no such constraint.
931 * NOTE: since constraint name is not unique, be wary of code that uses this
932 * for anything except preparing error messages.
935 get_constraint_name(Oid conoid
)
939 tp
= SearchSysCache(CONSTROID
,
940 ObjectIdGetDatum(conoid
),
942 if (HeapTupleIsValid(tp
))
944 Form_pg_constraint contup
= (Form_pg_constraint
) GETSTRUCT(tp
);
947 result
= pstrdup(NameStr(contup
->conname
));
955 /* ---------- OPCLASS CACHE ---------- */
960 * Returns the OID of the operator family the opclass belongs to.
963 get_opclass_family(Oid opclass
)
966 Form_pg_opclass cla_tup
;
969 tp
= SearchSysCache(CLAOID
,
970 ObjectIdGetDatum(opclass
),
972 if (!HeapTupleIsValid(tp
))
973 elog(ERROR
, "cache lookup failed for opclass %u", opclass
);
974 cla_tup
= (Form_pg_opclass
) GETSTRUCT(tp
);
976 result
= cla_tup
->opcfamily
;
982 * get_opclass_input_type
984 * Returns the OID of the datatype the opclass indexes.
987 get_opclass_input_type(Oid opclass
)
990 Form_pg_opclass cla_tup
;
993 tp
= SearchSysCache(CLAOID
,
994 ObjectIdGetDatum(opclass
),
996 if (!HeapTupleIsValid(tp
))
997 elog(ERROR
, "cache lookup failed for opclass %u", opclass
);
998 cla_tup
= (Form_pg_opclass
) GETSTRUCT(tp
);
1000 result
= cla_tup
->opcintype
;
1001 ReleaseSysCache(tp
);
1005 /* ---------- OPERATOR CACHE ---------- */
1010 * Returns the regproc id of the routine used to implement an
1011 * operator given the operator oid.
1014 get_opcode(Oid opno
)
1018 tp
= SearchSysCache(OPEROID
,
1019 ObjectIdGetDatum(opno
),
1021 if (HeapTupleIsValid(tp
))
1023 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1024 RegProcedure result
;
1026 result
= optup
->oprcode
;
1027 ReleaseSysCache(tp
);
1031 return (RegProcedure
) InvalidOid
;
1036 * returns the name of the operator with the given opno
1038 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1041 get_opname(Oid opno
)
1045 tp
= SearchSysCache(OPEROID
,
1046 ObjectIdGetDatum(opno
),
1048 if (HeapTupleIsValid(tp
))
1050 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1053 result
= pstrdup(NameStr(optup
->oprname
));
1054 ReleaseSysCache(tp
);
1064 * Returns the left and right input datatypes for an operator
1065 * (InvalidOid if not relevant).
1068 op_input_types(Oid opno
, Oid
*lefttype
, Oid
*righttype
)
1071 Form_pg_operator optup
;
1073 tp
= SearchSysCache(OPEROID
,
1074 ObjectIdGetDatum(opno
),
1076 if (!HeapTupleIsValid(tp
)) /* shouldn't happen */
1077 elog(ERROR
, "cache lookup failed for operator %u", opno
);
1078 optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1079 *lefttype
= optup
->oprleft
;
1080 *righttype
= optup
->oprright
;
1081 ReleaseSysCache(tp
);
1087 * Returns true if the operator is potentially mergejoinable. (The planner
1088 * will fail to find any mergejoin plans unless there are suitable btree
1089 * opfamily entries for this operator and associated sortops. The pg_operator
1090 * flag is just a hint to tell the planner whether to bother looking.)
1093 op_mergejoinable(Oid opno
)
1096 bool result
= false;
1098 tp
= SearchSysCache(OPEROID
,
1099 ObjectIdGetDatum(opno
),
1101 if (HeapTupleIsValid(tp
))
1103 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1105 result
= optup
->oprcanmerge
;
1106 ReleaseSysCache(tp
);
1114 * Returns true if the operator is hashjoinable. (There must be a suitable
1115 * hash opfamily entry for this operator if it is so marked.)
1118 op_hashjoinable(Oid opno
)
1121 bool result
= false;
1123 tp
= SearchSysCache(OPEROID
,
1124 ObjectIdGetDatum(opno
),
1126 if (HeapTupleIsValid(tp
))
1128 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1130 result
= optup
->oprcanhash
;
1131 ReleaseSysCache(tp
);
1139 * Get the proisstrict flag for the operator's underlying function.
1144 RegProcedure funcid
= get_opcode(opno
);
1146 if (funcid
== (RegProcedure
) InvalidOid
)
1147 elog(ERROR
, "operator %u does not exist", opno
);
1149 return func_strict((Oid
) funcid
);
1155 * Get the provolatile flag for the operator's underlying function.
1158 op_volatile(Oid opno
)
1160 RegProcedure funcid
= get_opcode(opno
);
1162 if (funcid
== (RegProcedure
) InvalidOid
)
1163 elog(ERROR
, "operator %u does not exist", opno
);
1165 return func_volatile((Oid
) funcid
);
1171 * Returns the corresponding commutator of an operator.
1174 get_commutator(Oid opno
)
1178 tp
= SearchSysCache(OPEROID
,
1179 ObjectIdGetDatum(opno
),
1181 if (HeapTupleIsValid(tp
))
1183 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1186 result
= optup
->oprcom
;
1187 ReleaseSysCache(tp
);
1197 * Returns the corresponding negator of an operator.
1200 get_negator(Oid opno
)
1204 tp
= SearchSysCache(OPEROID
,
1205 ObjectIdGetDatum(opno
),
1207 if (HeapTupleIsValid(tp
))
1209 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1212 result
= optup
->oprnegate
;
1213 ReleaseSysCache(tp
);
1223 * Returns procedure id for computing selectivity of an operator.
1226 get_oprrest(Oid opno
)
1230 tp
= SearchSysCache(OPEROID
,
1231 ObjectIdGetDatum(opno
),
1233 if (HeapTupleIsValid(tp
))
1235 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1236 RegProcedure result
;
1238 result
= optup
->oprrest
;
1239 ReleaseSysCache(tp
);
1243 return (RegProcedure
) InvalidOid
;
1249 * Returns procedure id for computing selectivity of a join.
1252 get_oprjoin(Oid opno
)
1256 tp
= SearchSysCache(OPEROID
,
1257 ObjectIdGetDatum(opno
),
1259 if (HeapTupleIsValid(tp
))
1261 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1262 RegProcedure result
;
1264 result
= optup
->oprjoin
;
1265 ReleaseSysCache(tp
);
1269 return (RegProcedure
) InvalidOid
;
1272 /* ---------- FUNCTION CACHE ---------- */
1276 * returns the name of the function with the given funcid
1278 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1281 get_func_name(Oid funcid
)
1285 tp
= SearchSysCache(PROCOID
,
1286 ObjectIdGetDatum(funcid
),
1288 if (HeapTupleIsValid(tp
))
1290 Form_pg_proc functup
= (Form_pg_proc
) GETSTRUCT(tp
);
1293 result
= pstrdup(NameStr(functup
->proname
));
1294 ReleaseSysCache(tp
);
1303 * Given procedure id, return the function's result type.
1306 get_func_rettype(Oid funcid
)
1311 tp
= SearchSysCache(PROCOID
,
1312 ObjectIdGetDatum(funcid
),
1314 if (!HeapTupleIsValid(tp
))
1315 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1317 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->prorettype
;
1318 ReleaseSysCache(tp
);
1324 * Given procedure id, return the number of arguments.
1327 get_func_nargs(Oid funcid
)
1332 tp
= SearchSysCache(PROCOID
,
1333 ObjectIdGetDatum(funcid
),
1335 if (!HeapTupleIsValid(tp
))
1336 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1338 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->pronargs
;
1339 ReleaseSysCache(tp
);
1344 * get_func_signature
1345 * Given procedure id, return the function's argument and result types.
1346 * (The return value is the result type.)
1348 * The arguments are returned as a palloc'd array.
1351 get_func_signature(Oid funcid
, Oid
**argtypes
, int *nargs
)
1354 Form_pg_proc procstruct
;
1357 tp
= SearchSysCache(PROCOID
,
1358 ObjectIdGetDatum(funcid
),
1360 if (!HeapTupleIsValid(tp
))
1361 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1363 procstruct
= (Form_pg_proc
) GETSTRUCT(tp
);
1365 result
= procstruct
->prorettype
;
1366 *nargs
= (int) procstruct
->pronargs
;
1367 Assert(*nargs
== procstruct
->proargtypes
.dim1
);
1368 *argtypes
= (Oid
*) palloc(*nargs
* sizeof(Oid
));
1369 memcpy(*argtypes
, procstruct
->proargtypes
.values
, *nargs
* sizeof(Oid
));
1371 ReleaseSysCache(tp
);
1377 * Given procedure id, return the function's proretset flag.
1380 get_func_retset(Oid funcid
)
1385 tp
= SearchSysCache(PROCOID
,
1386 ObjectIdGetDatum(funcid
),
1388 if (!HeapTupleIsValid(tp
))
1389 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1391 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->proretset
;
1392 ReleaseSysCache(tp
);
1398 * Given procedure id, return the function's proisstrict flag.
1401 func_strict(Oid funcid
)
1406 tp
= SearchSysCache(PROCOID
,
1407 ObjectIdGetDatum(funcid
),
1409 if (!HeapTupleIsValid(tp
))
1410 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1412 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->proisstrict
;
1413 ReleaseSysCache(tp
);
1419 * Given procedure id, return the function's provolatile flag.
1422 func_volatile(Oid funcid
)
1427 tp
= SearchSysCache(PROCOID
,
1428 ObjectIdGetDatum(funcid
),
1430 if (!HeapTupleIsValid(tp
))
1431 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1433 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->provolatile
;
1434 ReleaseSysCache(tp
);
1440 * Given procedure id, return the function's procost field.
1443 get_func_cost(Oid funcid
)
1448 tp
= SearchSysCache(PROCOID
,
1449 ObjectIdGetDatum(funcid
),
1451 if (!HeapTupleIsValid(tp
))
1452 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1454 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->procost
;
1455 ReleaseSysCache(tp
);
1461 * Given procedure id, return the function's prorows field.
1464 get_func_rows(Oid funcid
)
1469 tp
= SearchSysCache(PROCOID
,
1470 ObjectIdGetDatum(funcid
),
1472 if (!HeapTupleIsValid(tp
))
1473 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1475 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->prorows
;
1476 ReleaseSysCache(tp
);
1480 /* ---------- RELATION CACHE ---------- */
1484 * Given name and namespace of a relation, look up the OID.
1486 * Returns InvalidOid if there is no such relation.
1489 get_relname_relid(const char *relname
, Oid relnamespace
)
1491 return GetSysCacheOid(RELNAMENSP
,
1492 PointerGetDatum(relname
),
1493 ObjectIdGetDatum(relnamespace
),
1501 * Returns the number of attributes for a given relation.
1504 get_relnatts(Oid relid
)
1508 tp
= SearchSysCache(RELOID
,
1509 ObjectIdGetDatum(relid
),
1511 if (HeapTupleIsValid(tp
))
1513 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1516 result
= reltup
->relnatts
;
1517 ReleaseSysCache(tp
);
1521 return InvalidAttrNumber
;
1527 * Returns the name of a given relation.
1529 * Returns a palloc'd copy of the string, or NULL if no such relation.
1531 * NOTE: since relation name is not unique, be wary of code that uses this
1532 * for anything except preparing error messages.
1535 get_rel_name(Oid relid
)
1539 tp
= SearchSysCache(RELOID
,
1540 ObjectIdGetDatum(relid
),
1542 if (HeapTupleIsValid(tp
))
1544 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1547 result
= pstrdup(NameStr(reltup
->relname
));
1548 ReleaseSysCache(tp
);
1558 * Returns the pg_namespace OID associated with a given relation.
1561 get_rel_namespace(Oid relid
)
1565 tp
= SearchSysCache(RELOID
,
1566 ObjectIdGetDatum(relid
),
1568 if (HeapTupleIsValid(tp
))
1570 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1573 result
= reltup
->relnamespace
;
1574 ReleaseSysCache(tp
);
1584 * Returns the pg_type OID associated with a given relation.
1586 * Note: not all pg_class entries have associated pg_type OIDs; so be
1587 * careful to check for InvalidOid result.
1590 get_rel_type_id(Oid relid
)
1594 tp
= SearchSysCache(RELOID
,
1595 ObjectIdGetDatum(relid
),
1597 if (HeapTupleIsValid(tp
))
1599 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1602 result
= reltup
->reltype
;
1603 ReleaseSysCache(tp
);
1613 * Returns the relkind associated with a given relation.
1616 get_rel_relkind(Oid relid
)
1620 tp
= SearchSysCache(RELOID
,
1621 ObjectIdGetDatum(relid
),
1623 if (HeapTupleIsValid(tp
))
1625 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1628 result
= reltup
->relkind
;
1629 ReleaseSysCache(tp
);
1637 * get_rel_tablespace
1639 * Returns the pg_tablespace OID associated with a given relation.
1641 * Note: InvalidOid might mean either that we couldn't find the relation,
1642 * or that it is in the database's default tablespace.
1645 get_rel_tablespace(Oid relid
)
1649 tp
= SearchSysCache(RELOID
,
1650 ObjectIdGetDatum(relid
),
1652 if (HeapTupleIsValid(tp
))
1654 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1657 result
= reltup
->reltablespace
;
1658 ReleaseSysCache(tp
);
1666 /* ---------- TYPE CACHE ---------- */
1671 * Given the type OID, determine whether the type is defined
1672 * (if not, it's only a shell).
1675 get_typisdefined(Oid typid
)
1679 tp
= SearchSysCache(TYPEOID
,
1680 ObjectIdGetDatum(typid
),
1682 if (HeapTupleIsValid(tp
))
1684 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
1687 result
= typtup
->typisdefined
;
1688 ReleaseSysCache(tp
);
1698 * Given the type OID, return the length of the type.
1701 get_typlen(Oid typid
)
1705 tp
= SearchSysCache(TYPEOID
,
1706 ObjectIdGetDatum(typid
),
1708 if (HeapTupleIsValid(tp
))
1710 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
1713 result
= typtup
->typlen
;
1714 ReleaseSysCache(tp
);
1724 * Given the type OID, determine whether the type is returned by value or
1725 * not. Returns true if by value, false if by reference.
1728 get_typbyval(Oid typid
)
1732 tp
= SearchSysCache(TYPEOID
,
1733 ObjectIdGetDatum(typid
),
1735 if (HeapTupleIsValid(tp
))
1737 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
1740 result
= typtup
->typbyval
;
1741 ReleaseSysCache(tp
);
1751 * A two-fer: given the type OID, return both typlen and typbyval.
1753 * Since both pieces of info are needed to know how to copy a Datum,
1754 * many places need both. Might as well get them with one cache lookup
1755 * instead of two. Also, this routine raises an error instead of
1756 * returning a bogus value when given a bad type OID.
1759 get_typlenbyval(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 ReleaseSysCache(tp
);
1776 * get_typlenbyvalalign
1778 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1781 get_typlenbyvalalign(Oid typid
, int16
*typlen
, bool *typbyval
,
1785 Form_pg_type typtup
;
1787 tp
= SearchSysCache(TYPEOID
,
1788 ObjectIdGetDatum(typid
),
1790 if (!HeapTupleIsValid(tp
))
1791 elog(ERROR
, "cache lookup failed for type %u", typid
);
1792 typtup
= (Form_pg_type
) GETSTRUCT(tp
);
1793 *typlen
= typtup
->typlen
;
1794 *typbyval
= typtup
->typbyval
;
1795 *typalign
= typtup
->typalign
;
1796 ReleaseSysCache(tp
);
1801 * Given a pg_type row, select the type OID to pass to I/O functions
1803 * Formerly, all I/O functions were passed pg_type.typelem as their second
1804 * parameter, but we now have a more complex rule about what to pass.
1805 * This knowledge is intended to be centralized here --- direct references
1806 * to typelem elsewhere in the code are wrong, if they are associated with
1807 * I/O calls and not with actual subscripting operations! (But see
1808 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1810 * As of PostgreSQL 8.1, output functions receive only the value itself
1811 * and not any auxiliary parameters, so the name of this routine is now
1812 * a bit of a misnomer ... it should be getTypeInputParam.
1815 getTypeIOParam(HeapTuple typeTuple
)
1817 Form_pg_type typeStruct
= (Form_pg_type
) GETSTRUCT(typeTuple
);
1820 * Array types get their typelem as parameter; everybody else gets their
1821 * own type OID as parameter. (As of 8.2, domains must get their own OID
1822 * even if their base type is an array.)
1824 if (typeStruct
->typtype
== TYPTYPE_BASE
&& OidIsValid(typeStruct
->typelem
))
1825 return typeStruct
->typelem
;
1827 return HeapTupleGetOid(typeTuple
);
1833 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1834 * typdelim, typioparam, and IO function OID. The IO function
1835 * returned is controlled by IOFuncSelector
1838 get_type_io_data(Oid typid
,
1839 IOFuncSelector which_func
,
1847 HeapTuple typeTuple
;
1848 Form_pg_type typeStruct
;
1851 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1852 * use array_in and array_out during bootstrap.
1854 if (IsBootstrapProcessingMode())
1859 boot_get_type_io_data(typid
,
1876 elog(ERROR
, "binary I/O not supported during bootstrap");
1882 typeTuple
= SearchSysCache(TYPEOID
,
1883 ObjectIdGetDatum(typid
),
1885 if (!HeapTupleIsValid(typeTuple
))
1886 elog(ERROR
, "cache lookup failed for type %u", typid
);
1887 typeStruct
= (Form_pg_type
) GETSTRUCT(typeTuple
);
1889 *typlen
= typeStruct
->typlen
;
1890 *typbyval
= typeStruct
->typbyval
;
1891 *typalign
= typeStruct
->typalign
;
1892 *typdelim
= typeStruct
->typdelim
;
1893 *typioparam
= getTypeIOParam(typeTuple
);
1897 *func
= typeStruct
->typinput
;
1900 *func
= typeStruct
->typoutput
;
1902 case IOFunc_receive
:
1903 *func
= typeStruct
->typreceive
;
1906 *func
= typeStruct
->typsend
;
1909 ReleaseSysCache(typeTuple
);
1914 get_typalign(Oid typid
)
1918 tp
= SearchSysCache(TYPEOID
,
1919 ObjectIdGetDatum(typid
),
1921 if (HeapTupleIsValid(tp
))
1923 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
1926 result
= typtup
->typalign
;
1927 ReleaseSysCache(tp
);
1936 get_typstorage(Oid typid
)
1940 tp
= SearchSysCache(TYPEOID
,
1941 ObjectIdGetDatum(typid
),
1943 if (HeapTupleIsValid(tp
))
1945 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
1948 result
= typtup
->typstorage
;
1949 ReleaseSysCache(tp
);
1958 * Given a type OID, return the type's default value, if any.
1960 * The result is a palloc'd expression node tree, or NULL if there
1961 * is no defined default for the datatype.
1963 * NB: caller should be prepared to coerce result to correct datatype;
1964 * the returned expression tree might produce something of the wrong type.
1967 get_typdefault(Oid typid
)
1969 HeapTuple typeTuple
;
1975 typeTuple
= SearchSysCache(TYPEOID
,
1976 ObjectIdGetDatum(typid
),
1978 if (!HeapTupleIsValid(typeTuple
))
1979 elog(ERROR
, "cache lookup failed for type %u", typid
);
1980 type
= (Form_pg_type
) GETSTRUCT(typeTuple
);
1983 * typdefault and typdefaultbin are potentially null, so don't try to
1984 * access 'em as struct fields. Must do it the hard way with
1987 datum
= SysCacheGetAttr(TYPEOID
,
1989 Anum_pg_type_typdefaultbin
,
1994 /* We have an expression default */
1995 expr
= stringToNode(TextDatumGetCString(datum
));
1999 /* Perhaps we have a plain literal default */
2000 datum
= SysCacheGetAttr(TYPEOID
,
2002 Anum_pg_type_typdefault
,
2007 char *strDefaultVal
;
2009 /* Convert text datum to C string */
2010 strDefaultVal
= TextDatumGetCString(datum
);
2011 /* Convert C string to a value of the given type */
2012 datum
= OidInputFunctionCall(type
->typinput
, strDefaultVal
,
2013 getTypeIOParam(typeTuple
), -1);
2014 /* Build a Const node containing the value */
2015 expr
= (Node
*) makeConst(typid
,
2021 pfree(strDefaultVal
);
2030 ReleaseSysCache(typeTuple
);
2037 * If the given type is a domain, return its base type;
2038 * otherwise return the type's own OID.
2041 getBaseType(Oid typid
)
2045 return getBaseTypeAndTypmod(typid
, &typmod
);
2049 * getBaseTypeAndTypmod
2050 * If the given type is a domain, return its base type and typmod;
2051 * otherwise return the type's own OID, and leave *typmod unchanged.
2053 * Note that the "applied typmod" should be -1 for every domain level
2054 * above the bottommost; therefore, if the passed-in typid is indeed
2055 * a domain, *typmod should be -1.
2058 getBaseTypeAndTypmod(Oid typid
, int32
*typmod
)
2061 * We loop to find the bottom base type in a stack of domains.
2066 Form_pg_type typTup
;
2068 tup
= SearchSysCache(TYPEOID
,
2069 ObjectIdGetDatum(typid
),
2071 if (!HeapTupleIsValid(tup
))
2072 elog(ERROR
, "cache lookup failed for type %u", typid
);
2073 typTup
= (Form_pg_type
) GETSTRUCT(tup
);
2074 if (typTup
->typtype
!= TYPTYPE_DOMAIN
)
2076 /* Not a domain, so done */
2077 ReleaseSysCache(tup
);
2081 Assert(*typmod
== -1);
2082 typid
= typTup
->typbasetype
;
2083 *typmod
= typTup
->typtypmod
;
2085 ReleaseSysCache(tup
);
2094 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2095 * estimate the average width of values of the type. This is used by
2096 * the planner, which doesn't require absolutely correct results;
2097 * it's OK (and expected) to guess if we don't know for sure.
2100 get_typavgwidth(Oid typid
, int32 typmod
)
2102 int typlen
= get_typlen(typid
);
2106 * Easy if it's a fixed-width type
2112 * type_maximum_size knows the encoding of typmod for some datatypes;
2113 * don't duplicate that knowledge here.
2115 maxwidth
= type_maximum_size(typid
, typmod
);
2119 * For BPCHAR, the max width is also the only width. Otherwise we
2120 * need to guess about the typical data width given the max. A sliding
2121 * scale for percentage of max width seems reasonable.
2123 if (typid
== BPCHAROID
)
2126 return maxwidth
; /* assume full width */
2127 if (maxwidth
< 1000)
2128 return 32 + (maxwidth
- 32) / 2; /* assume 50% */
2131 * Beyond 1000, assume we're looking at something like
2132 * "varchar(10000)" where the limit isn't actually reached often, and
2133 * use a fixed estimate.
2135 return 32 + (1000 - 32) / 2;
2139 * Ooops, we have no idea ... wild guess time.
2147 * Given the type OID, find if it is a basic type, a complex type, etc.
2148 * It returns the null char if the cache lookup fails...
2151 get_typtype(Oid typid
)
2155 tp
= SearchSysCache(TYPEOID
,
2156 ObjectIdGetDatum(typid
),
2158 if (HeapTupleIsValid(tp
))
2160 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2163 result
= typtup
->typtype
;
2164 ReleaseSysCache(tp
);
2174 * Convenience function to determine whether a type OID represents
2175 * a "rowtype" type --- either RECORD or a named composite type.
2178 type_is_rowtype(Oid typid
)
2180 return (typid
== RECORDOID
|| get_typtype(typid
) == TYPTYPE_COMPOSITE
);
2185 * Returns true if the given type is an enum type.
2188 type_is_enum(Oid typid
)
2190 return (get_typtype(typid
) == TYPTYPE_ENUM
);
2194 * get_type_category_preferred
2196 * Given the type OID, fetch its category and preferred-type status.
2197 * Throws error on failure.
2200 get_type_category_preferred(Oid typid
, char *typcategory
, bool *typispreferred
)
2203 Form_pg_type typtup
;
2205 tp
= SearchSysCache(TYPEOID
,
2206 ObjectIdGetDatum(typid
),
2208 if (!HeapTupleIsValid(tp
))
2209 elog(ERROR
, "cache lookup failed for type %u", typid
);
2210 typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2211 *typcategory
= typtup
->typcategory
;
2212 *typispreferred
= typtup
->typispreferred
;
2213 ReleaseSysCache(tp
);
2219 * Given the type OID, get the typrelid (InvalidOid if not a complex
2223 get_typ_typrelid(Oid typid
)
2227 tp
= SearchSysCache(TYPEOID
,
2228 ObjectIdGetDatum(typid
),
2230 if (HeapTupleIsValid(tp
))
2232 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2235 result
= typtup
->typrelid
;
2236 ReleaseSysCache(tp
);
2246 * Given the type OID, get the typelem (InvalidOid if not an array type).
2248 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2249 * returned if the input is a fixed-length array type.
2252 get_element_type(Oid typid
)
2256 tp
= SearchSysCache(TYPEOID
,
2257 ObjectIdGetDatum(typid
),
2259 if (HeapTupleIsValid(tp
))
2261 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2264 if (typtup
->typlen
== -1)
2265 result
= typtup
->typelem
;
2267 result
= InvalidOid
;
2268 ReleaseSysCache(tp
);
2278 * Given the type OID, get the corresponding "true" array type.
2279 * Returns InvalidOid if no array type can be found.
2282 get_array_type(Oid typid
)
2285 Oid result
= InvalidOid
;
2287 tp
= SearchSysCache(TYPEOID
,
2288 ObjectIdGetDatum(typid
),
2290 if (HeapTupleIsValid(tp
))
2292 result
= ((Form_pg_type
) GETSTRUCT(tp
))->typarray
;
2293 ReleaseSysCache(tp
);
2301 * Get info needed for converting values of a type to internal form
2304 getTypeInputInfo(Oid type
, Oid
*typInput
, Oid
*typIOParam
)
2306 HeapTuple typeTuple
;
2309 typeTuple
= SearchSysCache(TYPEOID
,
2310 ObjectIdGetDatum(type
),
2312 if (!HeapTupleIsValid(typeTuple
))
2313 elog(ERROR
, "cache lookup failed for type %u", type
);
2314 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2316 if (!pt
->typisdefined
)
2318 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2319 errmsg("type %s is only a shell",
2320 format_type_be(type
))));
2321 if (!OidIsValid(pt
->typinput
))
2323 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2324 errmsg("no input function available for type %s",
2325 format_type_be(type
))));
2327 *typInput
= pt
->typinput
;
2328 *typIOParam
= getTypeIOParam(typeTuple
);
2330 ReleaseSysCache(typeTuple
);
2336 * Get info needed for printing values of a type
2339 getTypeOutputInfo(Oid type
, Oid
*typOutput
, bool *typIsVarlena
)
2341 HeapTuple typeTuple
;
2344 typeTuple
= SearchSysCache(TYPEOID
,
2345 ObjectIdGetDatum(type
),
2347 if (!HeapTupleIsValid(typeTuple
))
2348 elog(ERROR
, "cache lookup failed for type %u", type
);
2349 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2351 if (!pt
->typisdefined
)
2353 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2354 errmsg("type %s is only a shell",
2355 format_type_be(type
))));
2356 if (!OidIsValid(pt
->typoutput
))
2358 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2359 errmsg("no output function available for type %s",
2360 format_type_be(type
))));
2362 *typOutput
= pt
->typoutput
;
2363 *typIsVarlena
= (!pt
->typbyval
) && (pt
->typlen
== -1);
2365 ReleaseSysCache(typeTuple
);
2369 * getTypeBinaryInputInfo
2371 * Get info needed for binary input of values of a type
2374 getTypeBinaryInputInfo(Oid type
, Oid
*typReceive
, Oid
*typIOParam
)
2376 HeapTuple typeTuple
;
2379 typeTuple
= SearchSysCache(TYPEOID
,
2380 ObjectIdGetDatum(type
),
2382 if (!HeapTupleIsValid(typeTuple
))
2383 elog(ERROR
, "cache lookup failed for type %u", type
);
2384 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2386 if (!pt
->typisdefined
)
2388 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2389 errmsg("type %s is only a shell",
2390 format_type_be(type
))));
2391 if (!OidIsValid(pt
->typreceive
))
2393 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2394 errmsg("no binary input function available for type %s",
2395 format_type_be(type
))));
2397 *typReceive
= pt
->typreceive
;
2398 *typIOParam
= getTypeIOParam(typeTuple
);
2400 ReleaseSysCache(typeTuple
);
2404 * getTypeBinaryOutputInfo
2406 * Get info needed for binary output of values of a type
2409 getTypeBinaryOutputInfo(Oid type
, Oid
*typSend
, bool *typIsVarlena
)
2411 HeapTuple typeTuple
;
2414 typeTuple
= SearchSysCache(TYPEOID
,
2415 ObjectIdGetDatum(type
),
2417 if (!HeapTupleIsValid(typeTuple
))
2418 elog(ERROR
, "cache lookup failed for type %u", type
);
2419 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2421 if (!pt
->typisdefined
)
2423 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2424 errmsg("type %s is only a shell",
2425 format_type_be(type
))));
2426 if (!OidIsValid(pt
->typsend
))
2428 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2429 errmsg("no binary output function available for type %s",
2430 format_type_be(type
))));
2432 *typSend
= pt
->typsend
;
2433 *typIsVarlena
= (!pt
->typbyval
) && (pt
->typlen
== -1);
2435 ReleaseSysCache(typeTuple
);
2441 * Given the type OID, return the type's typmodin procedure, if any.
2444 get_typmodin(Oid typid
)
2448 tp
= SearchSysCache(TYPEOID
,
2449 ObjectIdGetDatum(typid
),
2451 if (HeapTupleIsValid(tp
))
2453 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2456 result
= typtup
->typmodin
;
2457 ReleaseSysCache(tp
);
2468 * Given the type OID, return the type's typmodout procedure, if any.
2471 get_typmodout(Oid typid
)
2475 tp
= SearchSysCache(TYPEOID
,
2476 ObjectIdGetDatum(typid
),
2478 if (HeapTupleIsValid(tp
))
2480 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2483 result
= typtup
->typmodout
;
2484 ReleaseSysCache(tp
);
2490 #endif /* NOT_USED */
2493 /* ---------- STATISTICS CACHE ---------- */
2498 * Given the table and attribute number of a column, get the average
2499 * width of entries in the column. Return zero if no data available.
2501 * Calling a hook at this point looks somewhat strange, but is required
2502 * because the optimizer calls this function without any other way for
2503 * plug-ins to control the result.
2506 get_attavgwidth(Oid relid
, AttrNumber attnum
)
2511 if (get_attavgwidth_hook
)
2513 stawidth
= (*get_attavgwidth_hook
) (relid
, attnum
);
2517 tp
= SearchSysCache(STATRELATT
,
2518 ObjectIdGetDatum(relid
),
2519 Int16GetDatum(attnum
),
2521 if (HeapTupleIsValid(tp
))
2523 stawidth
= ((Form_pg_statistic
) GETSTRUCT(tp
))->stawidth
;
2524 ReleaseSysCache(tp
);
2534 * Extract the contents of a "slot" of a pg_statistic tuple.
2535 * Returns TRUE if requested slot type was found, else FALSE.
2537 * Unlike other routines in this file, this takes a pointer to an
2538 * already-looked-up tuple in the pg_statistic cache. We do this since
2539 * most callers will want to extract more than one value from the cache
2540 * entry, and we don't want to repeat the cache lookup unnecessarily.
2541 * Also, this API allows this routine to be used with statistics tuples
2542 * that have been provided by a stats hook and didn't really come from
2545 * statstuple: pg_statistics tuple to be examined.
2546 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2547 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2548 * reqkind: STAKIND code for desired statistics slot kind.
2549 * reqop: STAOP value wanted, or InvalidOid if don't care.
2550 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2551 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2553 * If assigned, values and numbers are set to point to palloc'd arrays.
2554 * If the attribute type is pass-by-reference, the values referenced by
2555 * the values array are themselves palloc'd. The palloc'd stuff can be
2556 * freed by calling free_attstatsslot.
2559 get_attstatsslot(HeapTuple statstuple
,
2560 Oid atttype
, int32 atttypmod
,
2561 int reqkind
, Oid reqop
,
2562 Datum
**values
, int *nvalues
,
2563 float4
**numbers
, int *nnumbers
)
2565 Form_pg_statistic stats
= (Form_pg_statistic
) GETSTRUCT(statstuple
);
2570 ArrayType
*statarray
;
2572 HeapTuple typeTuple
;
2573 Form_pg_type typeForm
;
2575 for (i
= 0; i
< STATISTIC_NUM_SLOTS
; i
++)
2577 if ((&stats
->stakind1
)[i
] == reqkind
&&
2578 (reqop
== InvalidOid
|| (&stats
->staop1
)[i
] == reqop
))
2581 if (i
>= STATISTIC_NUM_SLOTS
)
2582 return false; /* not there */
2586 val
= SysCacheGetAttr(STATRELATT
, statstuple
,
2587 Anum_pg_statistic_stavalues1
+ i
,
2590 elog(ERROR
, "stavalues is null");
2591 statarray
= DatumGetArrayTypeP(val
);
2593 /* Need to get info about the array element type */
2594 typeTuple
= SearchSysCache(TYPEOID
,
2595 ObjectIdGetDatum(atttype
),
2597 if (!HeapTupleIsValid(typeTuple
))
2598 elog(ERROR
, "cache lookup failed for type %u", atttype
);
2599 typeForm
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2601 /* Deconstruct array into Datum elements; NULLs not expected */
2602 deconstruct_array(statarray
,
2607 values
, NULL
, nvalues
);
2610 * If the element type is pass-by-reference, we now have a bunch of
2611 * Datums that are pointers into the syscache value. Copy them to
2612 * avoid problems if syscache decides to drop the entry.
2614 if (!typeForm
->typbyval
)
2616 for (j
= 0; j
< *nvalues
; j
++)
2618 (*values
)[j
] = datumCopy((*values
)[j
],
2624 ReleaseSysCache(typeTuple
);
2627 * Free statarray if it's a detoasted copy.
2629 if ((Pointer
) statarray
!= DatumGetPointer(val
))
2635 val
= SysCacheGetAttr(STATRELATT
, statstuple
,
2636 Anum_pg_statistic_stanumbers1
+ i
,
2639 elog(ERROR
, "stanumbers is null");
2640 statarray
= DatumGetArrayTypeP(val
);
2643 * We expect the array to be a 1-D float4 array; verify that. We don't
2644 * need to use deconstruct_array() since the array data is just going
2645 * to look like a C array of float4 values.
2647 narrayelem
= ARR_DIMS(statarray
)[0];
2648 if (ARR_NDIM(statarray
) != 1 || narrayelem
<= 0 ||
2649 ARR_HASNULL(statarray
) ||
2650 ARR_ELEMTYPE(statarray
) != FLOAT4OID
)
2651 elog(ERROR
, "stanumbers is not a 1-D float4 array");
2652 *numbers
= (float4
*) palloc(narrayelem
* sizeof(float4
));
2653 memcpy(*numbers
, ARR_DATA_PTR(statarray
), narrayelem
* sizeof(float4
));
2654 *nnumbers
= narrayelem
;
2657 * Free statarray if it's a detoasted copy.
2659 if ((Pointer
) statarray
!= DatumGetPointer(val
))
2668 * Free data allocated by get_attstatsslot
2670 * atttype need be valid only if values != NULL.
2673 free_attstatsslot(Oid atttype
,
2674 Datum
*values
, int nvalues
,
2675 float4
*numbers
, int nnumbers
)
2679 if (!get_typbyval(atttype
))
2683 for (i
= 0; i
< nvalues
; i
++)
2684 pfree(DatumGetPointer(values
[i
]));
2692 /* ---------- PG_NAMESPACE CACHE ---------- */
2695 * get_namespace_name
2696 * Returns the name of a given namespace
2698 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2701 get_namespace_name(Oid nspid
)
2705 tp
= SearchSysCache(NAMESPACEOID
,
2706 ObjectIdGetDatum(nspid
),
2708 if (HeapTupleIsValid(tp
))
2710 Form_pg_namespace nsptup
= (Form_pg_namespace
) GETSTRUCT(tp
);
2713 result
= pstrdup(NameStr(nsptup
->nspname
));
2714 ReleaseSysCache(tp
);
2721 /* ---------- PG_AUTHID CACHE ---------- */
2725 * Given a role name, look up the role's OID.
2726 * Returns InvalidOid if no such role.
2729 get_roleid(const char *rolname
)
2731 return GetSysCacheOid(AUTHNAME
,
2732 PointerGetDatum(rolname
),
2737 * get_roleid_checked
2738 * Given a role name, look up the role's OID.
2739 * ereports if no such role.
2742 get_roleid_checked(const char *rolname
)
2746 roleid
= get_roleid(rolname
);
2747 if (!OidIsValid(roleid
))
2749 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2750 errmsg("role \"%s\" does not exist", rolname
)));