1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/utils/cache/lsyscache.c
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
18 #include "access/hash.h"
19 #include "access/htup_details.h"
20 #include "bootstrap/bootstrap.h"
21 #include "catalog/namespace.h"
22 #include "catalog/pg_am.h"
23 #include "catalog/pg_amop.h"
24 #include "catalog/pg_amproc.h"
25 #include "catalog/pg_cast.h"
26 #include "catalog/pg_class.h"
27 #include "catalog/pg_collation.h"
28 #include "catalog/pg_constraint.h"
29 #include "catalog/pg_index.h"
30 #include "catalog/pg_language.h"
31 #include "catalog/pg_namespace.h"
32 #include "catalog/pg_opclass.h"
33 #include "catalog/pg_operator.h"
34 #include "catalog/pg_proc.h"
35 #include "catalog/pg_publication.h"
36 #include "catalog/pg_range.h"
37 #include "catalog/pg_statistic.h"
38 #include "catalog/pg_subscription.h"
39 #include "catalog/pg_transform.h"
40 #include "catalog/pg_type.h"
41 #include "miscadmin.h"
42 #include "nodes/makefuncs.h"
43 #include "utils/array.h"
44 #include "utils/builtins.h"
45 #include "utils/catcache.h"
46 #include "utils/datum.h"
47 #include "utils/fmgroids.h"
48 #include "utils/lsyscache.h"
49 #include "utils/syscache.h"
50 #include "utils/typcache.h"
52 /* Hook for plugins to get control in get_attavgwidth() */
53 get_attavgwidth_hook_type get_attavgwidth_hook
= NULL
;
56 /* ---------- AMOP CACHES ---------- */
61 * Return t iff operator 'opno' is in operator family 'opfamily'.
63 * This function only considers search operators, not ordering operators.
66 op_in_opfamily(Oid opno
, Oid opfamily
)
68 return SearchSysCacheExists3(AMOPOPID
,
69 ObjectIdGetDatum(opno
),
70 CharGetDatum(AMOP_SEARCH
),
71 ObjectIdGetDatum(opfamily
));
75 * get_op_opfamily_strategy
77 * Get the operator's strategy number within the specified opfamily,
78 * or 0 if it's not a member of the opfamily.
80 * This function only considers search operators, not ordering operators.
83 get_op_opfamily_strategy(Oid opno
, Oid opfamily
)
86 Form_pg_amop amop_tup
;
89 tp
= SearchSysCache3(AMOPOPID
,
90 ObjectIdGetDatum(opno
),
91 CharGetDatum(AMOP_SEARCH
),
92 ObjectIdGetDatum(opfamily
));
93 if (!HeapTupleIsValid(tp
))
95 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
96 result
= amop_tup
->amopstrategy
;
102 * get_op_opfamily_sortfamily
104 * If the operator is an ordering operator within the specified opfamily,
105 * return its amopsortfamily OID; else return InvalidOid.
108 get_op_opfamily_sortfamily(Oid opno
, Oid opfamily
)
111 Form_pg_amop amop_tup
;
114 tp
= SearchSysCache3(AMOPOPID
,
115 ObjectIdGetDatum(opno
),
116 CharGetDatum(AMOP_ORDER
),
117 ObjectIdGetDatum(opfamily
));
118 if (!HeapTupleIsValid(tp
))
120 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
121 result
= amop_tup
->amopsortfamily
;
127 * get_op_opfamily_properties
129 * Get the operator's strategy number and declared input data types
130 * within the specified opfamily.
132 * Caller should already have verified that opno is a member of opfamily,
133 * therefore we raise an error if the tuple is not found.
136 get_op_opfamily_properties(Oid opno
, Oid opfamily
, bool ordering_op
,
142 Form_pg_amop amop_tup
;
144 tp
= SearchSysCache3(AMOPOPID
,
145 ObjectIdGetDatum(opno
),
146 CharGetDatum(ordering_op
? AMOP_ORDER
: AMOP_SEARCH
),
147 ObjectIdGetDatum(opfamily
));
148 if (!HeapTupleIsValid(tp
))
149 elog(ERROR
, "operator %u is not a member of opfamily %u",
151 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
152 *strategy
= amop_tup
->amopstrategy
;
153 *lefttype
= amop_tup
->amoplefttype
;
154 *righttype
= amop_tup
->amoprighttype
;
159 * get_opfamily_member
160 * Get the OID of the operator that implements the specified strategy
161 * with the specified datatypes for the specified opfamily.
163 * Returns InvalidOid if there is no pg_amop entry for the given keys.
166 get_opfamily_member(Oid opfamily
, Oid lefttype
, Oid righttype
,
170 Form_pg_amop amop_tup
;
173 tp
= SearchSysCache4(AMOPSTRATEGY
,
174 ObjectIdGetDatum(opfamily
),
175 ObjectIdGetDatum(lefttype
),
176 ObjectIdGetDatum(righttype
),
177 Int16GetDatum(strategy
));
178 if (!HeapTupleIsValid(tp
))
180 amop_tup
= (Form_pg_amop
) GETSTRUCT(tp
);
181 result
= amop_tup
->amopopr
;
187 * get_ordering_op_properties
188 * Given the OID of an ordering operator (a btree "<" or ">" operator),
189 * determine its opfamily, its declared input datatype, and its
190 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
192 * Returns true if successful, false if no matching pg_amop entry exists.
193 * (This indicates that the operator is not a valid ordering operator.)
195 * Note: the operator could be registered in multiple families, for example
196 * if someone were to build a "reverse sort" opfamily. This would result in
197 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
198 * or NULLS LAST, as well as inefficient planning due to failure to match up
199 * pathkeys that should be the same. So we want a determinate result here.
200 * Because of the way the syscache search works, we'll use the interpretation
201 * associated with the opfamily with smallest OID, which is probably
202 * determinate enough. Since there is no longer any particularly good reason
203 * to build reverse-sort opfamilies, it doesn't seem worth expending any
204 * additional effort on ensuring consistency.
207 get_ordering_op_properties(Oid opno
,
208 Oid
*opfamily
, Oid
*opcintype
, int16
*strategy
)
214 /* ensure outputs are initialized on failure */
215 *opfamily
= InvalidOid
;
216 *opcintype
= InvalidOid
;
220 * Search pg_amop to see if the target operator is registered as the "<"
221 * or ">" operator of any btree opfamily.
223 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno
));
225 for (i
= 0; i
< catlist
->n_members
; i
++)
227 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
228 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
231 if (aform
->amopmethod
!= BTREE_AM_OID
)
234 if (aform
->amopstrategy
== BTLessStrategyNumber
||
235 aform
->amopstrategy
== BTGreaterStrategyNumber
)
237 /* Found it ... should have consistent input types */
238 if (aform
->amoplefttype
== aform
->amoprighttype
)
240 /* Found a suitable opfamily, return info */
241 *opfamily
= aform
->amopfamily
;
242 *opcintype
= aform
->amoplefttype
;
243 *strategy
= aform
->amopstrategy
;
250 ReleaseSysCacheList(catlist
);
256 * get_equality_op_for_ordering_op
257 * Get the OID of the datatype-specific btree equality operator
258 * associated with an ordering operator (a "<" or ">" operator).
260 * If "reverse" isn't NULL, also set *reverse to false if the operator is "<",
263 * Returns InvalidOid if no matching equality operator can be found.
264 * (This indicates that the operator is not a valid ordering operator.)
267 get_equality_op_for_ordering_op(Oid opno
, bool *reverse
)
269 Oid result
= InvalidOid
;
274 /* Find the operator in pg_amop */
275 if (get_ordering_op_properties(opno
,
276 &opfamily
, &opcintype
, &strategy
))
278 /* Found a suitable opfamily, get matching equality operator */
279 result
= get_opfamily_member(opfamily
,
282 BTEqualStrategyNumber
);
284 *reverse
= (strategy
== BTGreaterStrategyNumber
);
291 * get_ordering_op_for_equality_op
292 * Get the OID of a datatype-specific btree ordering operator
293 * associated with an equality operator. (If there are multiple
294 * possibilities, assume any one will do.)
296 * This function is used when we have to sort data before unique-ifying,
297 * and don't much care which sorting op is used as long as it's compatible
298 * with the intended equality operator. Since we need a sorting operator,
299 * it should be single-data-type even if the given operator is cross-type.
300 * The caller specifies whether to find an op for the LHS or RHS data type.
302 * Returns InvalidOid if no matching ordering operator can be found.
305 get_ordering_op_for_equality_op(Oid opno
, bool use_lhs_type
)
307 Oid result
= InvalidOid
;
312 * Search pg_amop to see if the target operator is registered as the "="
313 * operator of any btree opfamily.
315 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno
));
317 for (i
= 0; i
< catlist
->n_members
; i
++)
319 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
320 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
323 if (aform
->amopmethod
!= BTREE_AM_OID
)
326 if (aform
->amopstrategy
== BTEqualStrategyNumber
)
328 /* Found a suitable opfamily, get matching ordering operator */
331 typid
= use_lhs_type
? aform
->amoplefttype
: aform
->amoprighttype
;
332 result
= get_opfamily_member(aform
->amopfamily
,
334 BTLessStrategyNumber
);
335 if (OidIsValid(result
))
337 /* failure probably shouldn't happen, but keep looking if so */
341 ReleaseSysCacheList(catlist
);
347 * get_mergejoin_opfamilies
348 * Given a putatively mergejoinable operator, return a list of the OIDs
349 * of the btree opfamilies in which it represents equality.
351 * It is possible (though at present unusual) for an operator to be equality
352 * in more than one opfamily, hence the result is a list. This also lets us
353 * return NIL if the operator is not found in any opfamilies.
355 * The planner currently uses simple equal() tests to compare the lists
356 * returned by this function, which makes the list order relevant, though
357 * strictly speaking it should not be. Because of the way syscache list
358 * searches are handled, in normal operation the result will be sorted by OID
359 * so everything works fine. If running with system index usage disabled,
360 * the result ordering is unspecified and hence the planner might fail to
361 * recognize optimization opportunities ... but that's hardly a scenario in
362 * which performance is good anyway, so there's no point in expending code
363 * or cycles here to guarantee the ordering in that case.
366 get_mergejoin_opfamilies(Oid opno
)
373 * Search pg_amop to see if the target operator is registered as the "="
374 * operator of any btree opfamily.
376 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno
));
378 for (i
= 0; i
< catlist
->n_members
; i
++)
380 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
381 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
383 /* must be btree equality */
384 if (aform
->amopmethod
== BTREE_AM_OID
&&
385 aform
->amopstrategy
== BTEqualStrategyNumber
)
386 result
= lappend_oid(result
, aform
->amopfamily
);
389 ReleaseSysCacheList(catlist
);
395 * get_compatible_hash_operators
396 * Get the OID(s) of hash equality operator(s) compatible with the given
397 * operator, but operating on its LHS and/or RHS datatype.
399 * An operator for the LHS type is sought and returned into *lhs_opno if
400 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
401 * and returned into *rhs_opno if rhs_opno isn't NULL.
403 * If the given operator is not cross-type, the results should be the same
404 * operator, but in cross-type situations they will be different.
406 * Returns true if able to find the requested operator(s), false if not.
407 * (This indicates that the operator should not have been marked oprcanhash.)
410 get_compatible_hash_operators(Oid opno
,
411 Oid
*lhs_opno
, Oid
*rhs_opno
)
417 /* Ensure output args are initialized on failure */
419 *lhs_opno
= InvalidOid
;
421 *rhs_opno
= InvalidOid
;
424 * Search pg_amop to see if the target operator is registered as the "="
425 * operator of any hash opfamily. If the operator is registered in
426 * multiple opfamilies, assume we can use any one.
428 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno
));
430 for (i
= 0; i
< catlist
->n_members
; i
++)
432 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
433 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
435 if (aform
->amopmethod
== HASH_AM_OID
&&
436 aform
->amopstrategy
== HTEqualStrategyNumber
)
438 /* No extra lookup needed if given operator is single-type */
439 if (aform
->amoplefttype
== aform
->amoprighttype
)
450 * Get the matching single-type operator(s). Failure probably
451 * shouldn't happen --- it implies a bogus opfamily --- but
452 * continue looking if so.
456 *lhs_opno
= get_opfamily_member(aform
->amopfamily
,
459 HTEqualStrategyNumber
);
460 if (!OidIsValid(*lhs_opno
))
462 /* Matching LHS found, done if caller doesn't want RHS */
471 *rhs_opno
= get_opfamily_member(aform
->amopfamily
,
472 aform
->amoprighttype
,
473 aform
->amoprighttype
,
474 HTEqualStrategyNumber
);
475 if (!OidIsValid(*rhs_opno
))
477 /* Forget any LHS operator from this opfamily */
479 *lhs_opno
= InvalidOid
;
482 /* Matching RHS found, so done */
489 ReleaseSysCacheList(catlist
);
495 * get_op_hash_functions
496 * Get the OID(s) of the standard hash support function(s) compatible with
497 * the given operator, operating on its LHS and/or RHS datatype as required.
499 * A function for the LHS type is sought and returned into *lhs_procno if
500 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
501 * and returned into *rhs_procno if rhs_procno isn't NULL.
503 * If the given operator is not cross-type, the results should be the same
504 * function, but in cross-type situations they will be different.
506 * Returns true if able to find the requested function(s), false if not.
507 * (This indicates that the operator should not have been marked oprcanhash.)
510 get_op_hash_functions(Oid opno
,
511 RegProcedure
*lhs_procno
, RegProcedure
*rhs_procno
)
517 /* Ensure output args are initialized on failure */
519 *lhs_procno
= InvalidOid
;
521 *rhs_procno
= InvalidOid
;
524 * Search pg_amop to see if the target operator is registered as the "="
525 * operator of any hash opfamily. If the operator is registered in
526 * multiple opfamilies, assume we can use any one.
528 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno
));
530 for (i
= 0; i
< catlist
->n_members
; i
++)
532 HeapTuple tuple
= &catlist
->members
[i
]->tuple
;
533 Form_pg_amop aform
= (Form_pg_amop
) GETSTRUCT(tuple
);
535 if (aform
->amopmethod
== HASH_AM_OID
&&
536 aform
->amopstrategy
== HTEqualStrategyNumber
)
539 * Get the matching support function(s). Failure probably
540 * shouldn't happen --- it implies a bogus opfamily --- but
541 * continue looking if so.
545 *lhs_procno
= get_opfamily_proc(aform
->amopfamily
,
549 if (!OidIsValid(*lhs_procno
))
551 /* Matching LHS found, done if caller doesn't want RHS */
557 /* Only one lookup needed if given operator is single-type */
558 if (aform
->amoplefttype
== aform
->amoprighttype
)
560 *rhs_procno
= *lhs_procno
;
567 *rhs_procno
= get_opfamily_proc(aform
->amopfamily
,
568 aform
->amoprighttype
,
569 aform
->amoprighttype
,
571 if (!OidIsValid(*rhs_procno
))
573 /* Forget any LHS function from this opfamily */
575 *lhs_procno
= InvalidOid
;
578 /* Matching RHS found, so done */
585 ReleaseSysCacheList(catlist
);
591 * get_op_btree_interpretation
592 * Given an operator's OID, find out which btree opfamilies it belongs to,
593 * and what properties it has within each one. The results are returned
594 * as a palloc'd list of OpBtreeInterpretation structs.
596 * In addition to the normal btree operators, we consider a <> operator to be
597 * a "member" of an opfamily if its negator is an equality operator of the
598 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
601 get_op_btree_interpretation(Oid opno
)
604 OpBtreeInterpretation
*thisresult
;
609 * Find all the pg_amop entries containing the operator.
611 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno
));
613 for (i
= 0; i
< catlist
->n_members
; i
++)
615 HeapTuple op_tuple
= &catlist
->members
[i
]->tuple
;
616 Form_pg_amop op_form
= (Form_pg_amop
) GETSTRUCT(op_tuple
);
617 StrategyNumber op_strategy
;
620 if (op_form
->amopmethod
!= BTREE_AM_OID
)
623 /* Get the operator's btree strategy number */
624 op_strategy
= (StrategyNumber
) op_form
->amopstrategy
;
625 Assert(op_strategy
>= 1 && op_strategy
<= 5);
627 thisresult
= (OpBtreeInterpretation
*)
628 palloc(sizeof(OpBtreeInterpretation
));
629 thisresult
->opfamily_id
= op_form
->amopfamily
;
630 thisresult
->strategy
= op_strategy
;
631 thisresult
->oplefttype
= op_form
->amoplefttype
;
632 thisresult
->oprighttype
= op_form
->amoprighttype
;
633 result
= lappend(result
, thisresult
);
636 ReleaseSysCacheList(catlist
);
639 * If we didn't find any btree opfamily containing the operator, perhaps
640 * it is a <> operator. See if it has a negator that is in an opfamily.
644 Oid op_negator
= get_negator(opno
);
646 if (OidIsValid(op_negator
))
648 catlist
= SearchSysCacheList1(AMOPOPID
,
649 ObjectIdGetDatum(op_negator
));
651 for (i
= 0; i
< catlist
->n_members
; i
++)
653 HeapTuple op_tuple
= &catlist
->members
[i
]->tuple
;
654 Form_pg_amop op_form
= (Form_pg_amop
) GETSTRUCT(op_tuple
);
655 StrategyNumber op_strategy
;
658 if (op_form
->amopmethod
!= BTREE_AM_OID
)
661 /* Get the operator's btree strategy number */
662 op_strategy
= (StrategyNumber
) op_form
->amopstrategy
;
663 Assert(op_strategy
>= 1 && op_strategy
<= 5);
665 /* Only consider negators that are = */
666 if (op_strategy
!= BTEqualStrategyNumber
)
669 /* OK, report it with "strategy" ROWCOMPARE_NE */
670 thisresult
= (OpBtreeInterpretation
*)
671 palloc(sizeof(OpBtreeInterpretation
));
672 thisresult
->opfamily_id
= op_form
->amopfamily
;
673 thisresult
->strategy
= ROWCOMPARE_NE
;
674 thisresult
->oplefttype
= op_form
->amoplefttype
;
675 thisresult
->oprighttype
= op_form
->amoprighttype
;
676 result
= lappend(result
, thisresult
);
679 ReleaseSysCacheList(catlist
);
687 * equality_ops_are_compatible
688 * Return true if the two given equality operators have compatible
691 * This is trivially true if they are the same operator. Otherwise,
692 * we look to see if they can be found in the same btree or hash opfamily.
693 * Either finding allows us to assume that they have compatible notions
694 * of equality. (The reason we need to do these pushups is that one might
695 * be a cross-type operator; for instance int24eq vs int4eq.)
698 equality_ops_are_compatible(Oid opno1
, Oid opno2
)
704 /* Easy if they're the same operator */
709 * We search through all the pg_amop entries for opno1.
711 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno1
));
714 for (i
= 0; i
< catlist
->n_members
; i
++)
716 HeapTuple op_tuple
= &catlist
->members
[i
]->tuple
;
717 Form_pg_amop op_form
= (Form_pg_amop
) GETSTRUCT(op_tuple
);
719 /* must be btree or hash */
720 if (op_form
->amopmethod
== BTREE_AM_OID
||
721 op_form
->amopmethod
== HASH_AM_OID
)
723 if (op_in_opfamily(opno2
, op_form
->amopfamily
))
731 ReleaseSysCacheList(catlist
);
737 * comparison_ops_are_compatible
738 * Return true if the two given comparison operators have compatible
741 * This is trivially true if they are the same operator. Otherwise,
742 * we look to see if they can be found in the same btree opfamily.
743 * For example, '<' and '>=' ops match if they belong to the same family.
745 * (This is identical to equality_ops_are_compatible(), except that we
746 * don't bother to examine hash opclasses.)
749 comparison_ops_are_compatible(Oid opno1
, Oid opno2
)
755 /* Easy if they're the same operator */
760 * We search through all the pg_amop entries for opno1.
762 catlist
= SearchSysCacheList1(AMOPOPID
, ObjectIdGetDatum(opno1
));
765 for (i
= 0; i
< catlist
->n_members
; i
++)
767 HeapTuple op_tuple
= &catlist
->members
[i
]->tuple
;
768 Form_pg_amop op_form
= (Form_pg_amop
) GETSTRUCT(op_tuple
);
770 if (op_form
->amopmethod
== BTREE_AM_OID
)
772 if (op_in_opfamily(opno2
, op_form
->amopfamily
))
780 ReleaseSysCacheList(catlist
);
786 /* ---------- AMPROC CACHES ---------- */
790 * Get the OID of the specified support function
791 * for the specified opfamily and datatypes.
793 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
796 get_opfamily_proc(Oid opfamily
, Oid lefttype
, Oid righttype
, int16 procnum
)
799 Form_pg_amproc amproc_tup
;
802 tp
= SearchSysCache4(AMPROCNUM
,
803 ObjectIdGetDatum(opfamily
),
804 ObjectIdGetDatum(lefttype
),
805 ObjectIdGetDatum(righttype
),
806 Int16GetDatum(procnum
));
807 if (!HeapTupleIsValid(tp
))
809 amproc_tup
= (Form_pg_amproc
) GETSTRUCT(tp
);
810 result
= amproc_tup
->amproc
;
816 /* ---------- ATTRIBUTE CACHES ---------- */
820 * Given the relation id and the attribute number, return the "attname"
821 * field from the attribute relation as a palloc'ed string.
823 * If no such attribute exists and missing_ok is true, NULL is returned;
824 * otherwise a not-intended-for-user-consumption error is thrown.
827 get_attname(Oid relid
, AttrNumber attnum
, bool missing_ok
)
831 tp
= SearchSysCache2(ATTNUM
,
832 ObjectIdGetDatum(relid
), Int16GetDatum(attnum
));
833 if (HeapTupleIsValid(tp
))
835 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
838 result
= pstrdup(NameStr(att_tup
->attname
));
844 elog(ERROR
, "cache lookup failed for attribute %d of relation %u",
852 * Given the relation id and the attribute name,
853 * return the "attnum" field from the attribute relation.
855 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
858 get_attnum(Oid relid
, const char *attname
)
862 tp
= SearchSysCacheAttName(relid
, attname
);
863 if (HeapTupleIsValid(tp
))
865 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
868 result
= att_tup
->attnum
;
873 return InvalidAttrNumber
;
879 * Given the relation id and the attribute number,
880 * return the "attgenerated" field from the attribute relation.
882 * Errors if not found.
884 * Since not generated is represented by '\0', this can also be used as a
888 get_attgenerated(Oid relid
, AttrNumber attnum
)
891 Form_pg_attribute att_tup
;
894 tp
= SearchSysCache2(ATTNUM
,
895 ObjectIdGetDatum(relid
),
896 Int16GetDatum(attnum
));
897 if (!HeapTupleIsValid(tp
))
898 elog(ERROR
, "cache lookup failed for attribute %d of relation %u",
900 att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
901 result
= att_tup
->attgenerated
;
909 * Given the relation OID and the attribute number with the relation,
910 * return the attribute type OID.
913 get_atttype(Oid relid
, AttrNumber attnum
)
917 tp
= SearchSysCache2(ATTNUM
,
918 ObjectIdGetDatum(relid
),
919 Int16GetDatum(attnum
));
920 if (HeapTupleIsValid(tp
))
922 Form_pg_attribute att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
925 result
= att_tup
->atttypid
;
934 * get_atttypetypmodcoll
936 * A three-fer: given the relation id and the attribute number,
937 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
939 * Unlike the otherwise-similar get_atttype, this routine
940 * raises an error if it can't obtain the information.
943 get_atttypetypmodcoll(Oid relid
, AttrNumber attnum
,
944 Oid
*typid
, int32
*typmod
, Oid
*collid
)
947 Form_pg_attribute att_tup
;
949 tp
= SearchSysCache2(ATTNUM
,
950 ObjectIdGetDatum(relid
),
951 Int16GetDatum(attnum
));
952 if (!HeapTupleIsValid(tp
))
953 elog(ERROR
, "cache lookup failed for attribute %d of relation %u",
955 att_tup
= (Form_pg_attribute
) GETSTRUCT(tp
);
957 *typid
= att_tup
->atttypid
;
958 *typmod
= att_tup
->atttypmod
;
959 *collid
= att_tup
->attcollation
;
966 * Given the relation id and the attribute number,
967 * return the attribute options text[] datum, if any.
970 get_attoptions(Oid relid
, int16 attnum
)
977 tuple
= SearchSysCache2(ATTNUM
,
978 ObjectIdGetDatum(relid
),
979 Int16GetDatum(attnum
));
981 if (!HeapTupleIsValid(tuple
))
982 elog(ERROR
, "cache lookup failed for attribute %d of relation %u",
985 attopts
= SysCacheGetAttr(ATTNAME
, tuple
, Anum_pg_attribute_attoptions
,
991 result
= datumCopy(attopts
, false, -1); /* text[] */
993 ReleaseSysCache(tuple
);
998 /* ---------- PG_CAST CACHE ---------- */
1001 * get_cast_oid - given two type OIDs, look up a cast OID
1003 * If missing_ok is false, throw an error if the cast is not found. If
1004 * true, just return InvalidOid.
1007 get_cast_oid(Oid sourcetypeid
, Oid targettypeid
, bool missing_ok
)
1011 oid
= GetSysCacheOid2(CASTSOURCETARGET
, Anum_pg_cast_oid
,
1012 ObjectIdGetDatum(sourcetypeid
),
1013 ObjectIdGetDatum(targettypeid
));
1014 if (!OidIsValid(oid
) && !missing_ok
)
1016 (errcode(ERRCODE_UNDEFINED_OBJECT
),
1017 errmsg("cast from type %s to type %s does not exist",
1018 format_type_be(sourcetypeid
),
1019 format_type_be(targettypeid
))));
1023 /* ---------- COLLATION CACHE ---------- */
1026 * get_collation_name
1027 * Returns the name of a given pg_collation entry.
1029 * Returns a palloc'd copy of the string, or NULL if no such collation.
1031 * NOTE: since collation name is not unique, be wary of code that uses this
1032 * for anything except preparing error messages.
1035 get_collation_name(Oid colloid
)
1039 tp
= SearchSysCache1(COLLOID
, ObjectIdGetDatum(colloid
));
1040 if (HeapTupleIsValid(tp
))
1042 Form_pg_collation colltup
= (Form_pg_collation
) GETSTRUCT(tp
);
1045 result
= pstrdup(NameStr(colltup
->collname
));
1046 ReleaseSysCache(tp
);
1054 get_collation_isdeterministic(Oid colloid
)
1057 Form_pg_collation colltup
;
1060 tp
= SearchSysCache1(COLLOID
, ObjectIdGetDatum(colloid
));
1061 if (!HeapTupleIsValid(tp
))
1062 elog(ERROR
, "cache lookup failed for collation %u", colloid
);
1063 colltup
= (Form_pg_collation
) GETSTRUCT(tp
);
1064 result
= colltup
->collisdeterministic
;
1065 ReleaseSysCache(tp
);
1069 /* ---------- CONSTRAINT CACHE ---------- */
1072 * get_constraint_name
1073 * Returns the name of a given pg_constraint entry.
1075 * Returns a palloc'd copy of the string, or NULL if no such constraint.
1077 * NOTE: since constraint name is not unique, be wary of code that uses this
1078 * for anything except preparing error messages.
1081 get_constraint_name(Oid conoid
)
1085 tp
= SearchSysCache1(CONSTROID
, ObjectIdGetDatum(conoid
));
1086 if (HeapTupleIsValid(tp
))
1088 Form_pg_constraint contup
= (Form_pg_constraint
) GETSTRUCT(tp
);
1091 result
= pstrdup(NameStr(contup
->conname
));
1092 ReleaseSysCache(tp
);
1100 * get_constraint_index
1101 * Given the OID of a unique, primary-key, or exclusion constraint,
1102 * return the OID of the underlying index.
1104 * Returns InvalidOid if the constraint could not be found or is of
1107 * The intent of this function is to return the index "owned" by the
1108 * specified constraint. Therefore we must check contype, since some
1109 * pg_constraint entries (e.g. for foreign-key constraints) store the
1110 * OID of an index that is referenced but not owned by the constraint.
1113 get_constraint_index(Oid conoid
)
1117 tp
= SearchSysCache1(CONSTROID
, ObjectIdGetDatum(conoid
));
1118 if (HeapTupleIsValid(tp
))
1120 Form_pg_constraint contup
= (Form_pg_constraint
) GETSTRUCT(tp
);
1123 if (contup
->contype
== CONSTRAINT_UNIQUE
||
1124 contup
->contype
== CONSTRAINT_PRIMARY
||
1125 contup
->contype
== CONSTRAINT_EXCLUSION
)
1126 result
= contup
->conindid
;
1128 result
= InvalidOid
;
1129 ReleaseSysCache(tp
);
1137 * get_constraint_type
1138 * Return the pg_constraint.contype value for the given constraint.
1143 get_constraint_type(Oid conoid
)
1148 tp
= SearchSysCache1(CONSTROID
, ObjectIdGetDatum(conoid
));
1149 if (!HeapTupleIsValid(tp
))
1150 elog(ERROR
, "cache lookup failed for constraint %u", conoid
);
1152 contype
= ((Form_pg_constraint
) GETSTRUCT(tp
))->contype
;
1153 ReleaseSysCache(tp
);
1158 /* ---------- LANGUAGE CACHE ---------- */
1161 get_language_name(Oid langoid
, bool missing_ok
)
1165 tp
= SearchSysCache1(LANGOID
, ObjectIdGetDatum(langoid
));
1166 if (HeapTupleIsValid(tp
))
1168 Form_pg_language lantup
= (Form_pg_language
) GETSTRUCT(tp
);
1171 result
= pstrdup(NameStr(lantup
->lanname
));
1172 ReleaseSysCache(tp
);
1177 elog(ERROR
, "cache lookup failed for language %u",
1182 /* ---------- OPCLASS CACHE ---------- */
1185 * get_opclass_family
1187 * Returns the OID of the operator family the opclass belongs to.
1190 get_opclass_family(Oid opclass
)
1193 Form_pg_opclass cla_tup
;
1196 tp
= SearchSysCache1(CLAOID
, ObjectIdGetDatum(opclass
));
1197 if (!HeapTupleIsValid(tp
))
1198 elog(ERROR
, "cache lookup failed for opclass %u", opclass
);
1199 cla_tup
= (Form_pg_opclass
) GETSTRUCT(tp
);
1201 result
= cla_tup
->opcfamily
;
1202 ReleaseSysCache(tp
);
1207 * get_opclass_input_type
1209 * Returns the OID of the datatype the opclass indexes.
1212 get_opclass_input_type(Oid opclass
)
1215 Form_pg_opclass cla_tup
;
1218 tp
= SearchSysCache1(CLAOID
, ObjectIdGetDatum(opclass
));
1219 if (!HeapTupleIsValid(tp
))
1220 elog(ERROR
, "cache lookup failed for opclass %u", opclass
);
1221 cla_tup
= (Form_pg_opclass
) GETSTRUCT(tp
);
1223 result
= cla_tup
->opcintype
;
1224 ReleaseSysCache(tp
);
1229 * get_opclass_opfamily_and_input_type
1231 * Returns the OID of the operator family the opclass belongs to,
1232 * the OID of the datatype the opclass indexes
1235 get_opclass_opfamily_and_input_type(Oid opclass
, Oid
*opfamily
, Oid
*opcintype
)
1238 Form_pg_opclass cla_tup
;
1240 tp
= SearchSysCache1(CLAOID
, ObjectIdGetDatum(opclass
));
1241 if (!HeapTupleIsValid(tp
))
1244 cla_tup
= (Form_pg_opclass
) GETSTRUCT(tp
);
1246 *opfamily
= cla_tup
->opcfamily
;
1247 *opcintype
= cla_tup
->opcintype
;
1249 ReleaseSysCache(tp
);
1255 * get_opclass_method
1257 * Returns the OID of the index access method the opclass belongs to.
1260 get_opclass_method(Oid opclass
)
1263 Form_pg_opclass cla_tup
;
1266 tp
= SearchSysCache1(CLAOID
, ObjectIdGetDatum(opclass
));
1267 if (!HeapTupleIsValid(tp
))
1268 elog(ERROR
, "cache lookup failed for opclass %u", opclass
);
1269 cla_tup
= (Form_pg_opclass
) GETSTRUCT(tp
);
1271 result
= cla_tup
->opcmethod
;
1272 ReleaseSysCache(tp
);
1276 /* ---------- OPERATOR CACHE ---------- */
1281 * Returns the regproc id of the routine used to implement an
1282 * operator given the operator oid.
1285 get_opcode(Oid opno
)
1289 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1290 if (HeapTupleIsValid(tp
))
1292 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1293 RegProcedure result
;
1295 result
= optup
->oprcode
;
1296 ReleaseSysCache(tp
);
1300 return (RegProcedure
) InvalidOid
;
1305 * returns the name of the operator with the given opno
1307 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1310 get_opname(Oid opno
)
1314 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1315 if (HeapTupleIsValid(tp
))
1317 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1320 result
= pstrdup(NameStr(optup
->oprname
));
1321 ReleaseSysCache(tp
);
1330 * Given operator oid, return the operator's result type.
1333 get_op_rettype(Oid opno
)
1337 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1338 if (HeapTupleIsValid(tp
))
1340 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1343 result
= optup
->oprresult
;
1344 ReleaseSysCache(tp
);
1354 * Returns the left and right input datatypes for an operator
1355 * (InvalidOid if not relevant).
1358 op_input_types(Oid opno
, Oid
*lefttype
, Oid
*righttype
)
1361 Form_pg_operator optup
;
1363 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1364 if (!HeapTupleIsValid(tp
)) /* shouldn't happen */
1365 elog(ERROR
, "cache lookup failed for operator %u", opno
);
1366 optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1367 *lefttype
= optup
->oprleft
;
1368 *righttype
= optup
->oprright
;
1369 ReleaseSysCache(tp
);
1375 * Returns true if the operator is potentially mergejoinable. (The planner
1376 * will fail to find any mergejoin plans unless there are suitable btree
1377 * opfamily entries for this operator and associated sortops. The pg_operator
1378 * flag is just a hint to tell the planner whether to bother looking.)
1380 * In some cases (currently only array_eq and record_eq), mergejoinability
1381 * depends on the specific input data type the operator is invoked for, so
1382 * that must be passed as well. We currently assume that only one input's type
1383 * is needed to check this --- by convention, pass the left input's data type.
1386 op_mergejoinable(Oid opno
, Oid inputtype
)
1388 bool result
= false;
1390 TypeCacheEntry
*typentry
;
1393 * For array_eq or record_eq, we can sort if the element or field types
1394 * are all sortable. We could implement all the checks for that here, but
1395 * the typcache already does that and caches the results too, so let's
1396 * rely on the typcache.
1398 if (opno
== ARRAY_EQ_OP
)
1400 typentry
= lookup_type_cache(inputtype
, TYPECACHE_CMP_PROC
);
1401 if (typentry
->cmp_proc
== F_BTARRAYCMP
)
1404 else if (opno
== RECORD_EQ_OP
)
1406 typentry
= lookup_type_cache(inputtype
, TYPECACHE_CMP_PROC
);
1407 if (typentry
->cmp_proc
== F_BTRECORDCMP
)
1412 /* For all other operators, rely on pg_operator.oprcanmerge */
1413 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1414 if (HeapTupleIsValid(tp
))
1416 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1418 result
= optup
->oprcanmerge
;
1419 ReleaseSysCache(tp
);
1428 * Returns true if the operator is hashjoinable. (There must be a suitable
1429 * hash opfamily entry for this operator if it is so marked.)
1431 * In some cases (currently only array_eq), hashjoinability depends on the
1432 * specific input data type the operator is invoked for, so that must be
1433 * passed as well. We currently assume that only one input's type is needed
1434 * to check this --- by convention, pass the left input's data type.
1437 op_hashjoinable(Oid opno
, Oid inputtype
)
1439 bool result
= false;
1441 TypeCacheEntry
*typentry
;
1443 /* As in op_mergejoinable, let the typcache handle the hard cases */
1444 if (opno
== ARRAY_EQ_OP
)
1446 typentry
= lookup_type_cache(inputtype
, TYPECACHE_HASH_PROC
);
1447 if (typentry
->hash_proc
== F_HASH_ARRAY
)
1450 else if (opno
== RECORD_EQ_OP
)
1452 typentry
= lookup_type_cache(inputtype
, TYPECACHE_HASH_PROC
);
1453 if (typentry
->hash_proc
== F_HASH_RECORD
)
1458 /* For all other operators, rely on pg_operator.oprcanhash */
1459 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1460 if (HeapTupleIsValid(tp
))
1462 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1464 result
= optup
->oprcanhash
;
1465 ReleaseSysCache(tp
);
1474 * Get the proisstrict flag for the operator's underlying function.
1479 RegProcedure funcid
= get_opcode(opno
);
1481 if (funcid
== (RegProcedure
) InvalidOid
)
1482 elog(ERROR
, "operator %u does not exist", opno
);
1484 return func_strict((Oid
) funcid
);
1490 * Get the provolatile flag for the operator's underlying function.
1493 op_volatile(Oid opno
)
1495 RegProcedure funcid
= get_opcode(opno
);
1497 if (funcid
== (RegProcedure
) InvalidOid
)
1498 elog(ERROR
, "operator %u does not exist", opno
);
1500 return func_volatile((Oid
) funcid
);
1506 * Returns the corresponding commutator of an operator.
1509 get_commutator(Oid opno
)
1513 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1514 if (HeapTupleIsValid(tp
))
1516 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1519 result
= optup
->oprcom
;
1520 ReleaseSysCache(tp
);
1530 * Returns the corresponding negator of an operator.
1533 get_negator(Oid opno
)
1537 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1538 if (HeapTupleIsValid(tp
))
1540 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1543 result
= optup
->oprnegate
;
1544 ReleaseSysCache(tp
);
1554 * Returns procedure id for computing selectivity of an operator.
1557 get_oprrest(Oid opno
)
1561 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1562 if (HeapTupleIsValid(tp
))
1564 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1565 RegProcedure result
;
1567 result
= optup
->oprrest
;
1568 ReleaseSysCache(tp
);
1572 return (RegProcedure
) InvalidOid
;
1578 * Returns procedure id for computing selectivity of a join.
1581 get_oprjoin(Oid opno
)
1585 tp
= SearchSysCache1(OPEROID
, ObjectIdGetDatum(opno
));
1586 if (HeapTupleIsValid(tp
))
1588 Form_pg_operator optup
= (Form_pg_operator
) GETSTRUCT(tp
);
1589 RegProcedure result
;
1591 result
= optup
->oprjoin
;
1592 ReleaseSysCache(tp
);
1596 return (RegProcedure
) InvalidOid
;
1599 /* ---------- FUNCTION CACHE ---------- */
1603 * returns the name of the function with the given funcid
1605 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1608 get_func_name(Oid funcid
)
1612 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1613 if (HeapTupleIsValid(tp
))
1615 Form_pg_proc functup
= (Form_pg_proc
) GETSTRUCT(tp
);
1618 result
= pstrdup(NameStr(functup
->proname
));
1619 ReleaseSysCache(tp
);
1627 * get_func_namespace
1629 * Returns the pg_namespace OID associated with a given function.
1632 get_func_namespace(Oid funcid
)
1636 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1637 if (HeapTupleIsValid(tp
))
1639 Form_pg_proc functup
= (Form_pg_proc
) GETSTRUCT(tp
);
1642 result
= functup
->pronamespace
;
1643 ReleaseSysCache(tp
);
1652 * Given procedure id, return the function's result type.
1655 get_func_rettype(Oid funcid
)
1660 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1661 if (!HeapTupleIsValid(tp
))
1662 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1664 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->prorettype
;
1665 ReleaseSysCache(tp
);
1671 * Given procedure id, return the number of arguments.
1674 get_func_nargs(Oid funcid
)
1679 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1680 if (!HeapTupleIsValid(tp
))
1681 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1683 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->pronargs
;
1684 ReleaseSysCache(tp
);
1689 * get_func_signature
1690 * Given procedure id, return the function's argument and result types.
1691 * (The return value is the result type.)
1693 * The arguments are returned as a palloc'd array.
1696 get_func_signature(Oid funcid
, Oid
**argtypes
, int *nargs
)
1699 Form_pg_proc procstruct
;
1702 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1703 if (!HeapTupleIsValid(tp
))
1704 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1706 procstruct
= (Form_pg_proc
) GETSTRUCT(tp
);
1708 result
= procstruct
->prorettype
;
1709 *nargs
= (int) procstruct
->pronargs
;
1710 Assert(*nargs
== procstruct
->proargtypes
.dim1
);
1711 *argtypes
= (Oid
*) palloc(*nargs
* sizeof(Oid
));
1712 memcpy(*argtypes
, procstruct
->proargtypes
.values
, *nargs
* sizeof(Oid
));
1714 ReleaseSysCache(tp
);
1719 * get_func_variadictype
1720 * Given procedure id, return the function's provariadic field.
1723 get_func_variadictype(Oid funcid
)
1728 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1729 if (!HeapTupleIsValid(tp
))
1730 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1732 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->provariadic
;
1733 ReleaseSysCache(tp
);
1739 * Given procedure id, return the function's proretset flag.
1742 get_func_retset(Oid funcid
)
1747 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1748 if (!HeapTupleIsValid(tp
))
1749 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1751 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->proretset
;
1752 ReleaseSysCache(tp
);
1758 * Given procedure id, return the function's proisstrict flag.
1761 func_strict(Oid funcid
)
1766 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1767 if (!HeapTupleIsValid(tp
))
1768 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1770 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->proisstrict
;
1771 ReleaseSysCache(tp
);
1777 * Given procedure id, return the function's provolatile flag.
1780 func_volatile(Oid funcid
)
1785 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1786 if (!HeapTupleIsValid(tp
))
1787 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1789 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->provolatile
;
1790 ReleaseSysCache(tp
);
1796 * Given procedure id, return the function's proparallel flag.
1799 func_parallel(Oid funcid
)
1804 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1805 if (!HeapTupleIsValid(tp
))
1806 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1808 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->proparallel
;
1809 ReleaseSysCache(tp
);
1815 * Given procedure id, return the routine kind.
1818 get_func_prokind(Oid funcid
)
1823 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1824 if (!HeapTupleIsValid(tp
))
1825 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1827 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->prokind
;
1828 ReleaseSysCache(tp
);
1833 * get_func_leakproof
1834 * Given procedure id, return the function's leakproof field.
1837 get_func_leakproof(Oid funcid
)
1842 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1843 if (!HeapTupleIsValid(tp
))
1844 elog(ERROR
, "cache lookup failed for function %u", funcid
);
1846 result
= ((Form_pg_proc
) GETSTRUCT(tp
))->proleakproof
;
1847 ReleaseSysCache(tp
);
1854 * Returns the support function OID associated with a given function,
1855 * or InvalidOid if there is none.
1858 get_func_support(Oid funcid
)
1862 tp
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcid
));
1863 if (HeapTupleIsValid(tp
))
1865 Form_pg_proc functup
= (Form_pg_proc
) GETSTRUCT(tp
);
1866 RegProcedure result
;
1868 result
= functup
->prosupport
;
1869 ReleaseSysCache(tp
);
1873 return (RegProcedure
) InvalidOid
;
1876 /* ---------- RELATION CACHE ---------- */
1880 * Given name and namespace of a relation, look up the OID.
1882 * Returns InvalidOid if there is no such relation.
1885 get_relname_relid(const char *relname
, Oid relnamespace
)
1887 return GetSysCacheOid2(RELNAMENSP
, Anum_pg_class_oid
,
1888 PointerGetDatum(relname
),
1889 ObjectIdGetDatum(relnamespace
));
1896 * Returns the number of attributes for a given relation.
1899 get_relnatts(Oid relid
)
1903 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
1904 if (HeapTupleIsValid(tp
))
1906 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1909 result
= reltup
->relnatts
;
1910 ReleaseSysCache(tp
);
1914 return InvalidAttrNumber
;
1920 * Returns the name of a given relation.
1922 * Returns a palloc'd copy of the string, or NULL if no such relation.
1924 * NOTE: since relation name is not unique, be wary of code that uses this
1925 * for anything except preparing error messages.
1928 get_rel_name(Oid relid
)
1932 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
1933 if (HeapTupleIsValid(tp
))
1935 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1938 result
= pstrdup(NameStr(reltup
->relname
));
1939 ReleaseSysCache(tp
);
1949 * Returns the pg_namespace OID associated with a given relation.
1952 get_rel_namespace(Oid relid
)
1956 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
1957 if (HeapTupleIsValid(tp
))
1959 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1962 result
= reltup
->relnamespace
;
1963 ReleaseSysCache(tp
);
1973 * Returns the pg_type OID associated with a given relation.
1975 * Note: not all pg_class entries have associated pg_type OIDs; so be
1976 * careful to check for InvalidOid result.
1979 get_rel_type_id(Oid relid
)
1983 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
1984 if (HeapTupleIsValid(tp
))
1986 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
1989 result
= reltup
->reltype
;
1990 ReleaseSysCache(tp
);
2000 * Returns the relkind associated with a given relation.
2003 get_rel_relkind(Oid relid
)
2007 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
2008 if (HeapTupleIsValid(tp
))
2010 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
2013 result
= reltup
->relkind
;
2014 ReleaseSysCache(tp
);
2022 * get_rel_relispartition
2024 * Returns the relispartition flag associated with a given relation.
2027 get_rel_relispartition(Oid relid
)
2031 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
2032 if (HeapTupleIsValid(tp
))
2034 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
2037 result
= reltup
->relispartition
;
2038 ReleaseSysCache(tp
);
2046 * get_rel_tablespace
2048 * Returns the pg_tablespace OID associated with a given relation.
2050 * Note: InvalidOid might mean either that we couldn't find the relation,
2051 * or that it is in the database's default tablespace.
2054 get_rel_tablespace(Oid relid
)
2058 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
2059 if (HeapTupleIsValid(tp
))
2061 Form_pg_class reltup
= (Form_pg_class
) GETSTRUCT(tp
);
2064 result
= reltup
->reltablespace
;
2065 ReleaseSysCache(tp
);
2073 * get_rel_persistence
2075 * Returns the relpersistence associated with a given relation.
2078 get_rel_persistence(Oid relid
)
2081 Form_pg_class reltup
;
2084 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
2085 if (!HeapTupleIsValid(tp
))
2086 elog(ERROR
, "cache lookup failed for relation %u", relid
);
2087 reltup
= (Form_pg_class
) GETSTRUCT(tp
);
2088 result
= reltup
->relpersistence
;
2089 ReleaseSysCache(tp
);
2097 * Returns the relam associated with a given relation.
2100 get_rel_relam(Oid relid
)
2103 Form_pg_class reltup
;
2106 tp
= SearchSysCache1(RELOID
, ObjectIdGetDatum(relid
));
2107 if (!HeapTupleIsValid(tp
))
2108 elog(ERROR
, "cache lookup failed for relation %u", relid
);
2109 reltup
= (Form_pg_class
) GETSTRUCT(tp
);
2110 result
= reltup
->relam
;
2111 ReleaseSysCache(tp
);
2117 /* ---------- TRANSFORM CACHE ---------- */
2120 get_transform_fromsql(Oid typid
, Oid langid
, List
*trftypes
)
2124 if (!list_member_oid(trftypes
, typid
))
2127 tup
= SearchSysCache2(TRFTYPELANG
, ObjectIdGetDatum(typid
),
2128 ObjectIdGetDatum(langid
));
2129 if (HeapTupleIsValid(tup
))
2133 funcid
= ((Form_pg_transform
) GETSTRUCT(tup
))->trffromsql
;
2134 ReleaseSysCache(tup
);
2142 get_transform_tosql(Oid typid
, Oid langid
, List
*trftypes
)
2146 if (!list_member_oid(trftypes
, typid
))
2149 tup
= SearchSysCache2(TRFTYPELANG
, ObjectIdGetDatum(typid
),
2150 ObjectIdGetDatum(langid
));
2151 if (HeapTupleIsValid(tup
))
2155 funcid
= ((Form_pg_transform
) GETSTRUCT(tup
))->trftosql
;
2156 ReleaseSysCache(tup
);
2164 /* ---------- TYPE CACHE ---------- */
2169 * Given the type OID, determine whether the type is defined
2170 * (if not, it's only a shell).
2173 get_typisdefined(Oid typid
)
2177 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2178 if (HeapTupleIsValid(tp
))
2180 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2183 result
= typtup
->typisdefined
;
2184 ReleaseSysCache(tp
);
2194 * Given the type OID, return the length of the type.
2197 get_typlen(Oid typid
)
2201 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2202 if (HeapTupleIsValid(tp
))
2204 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2207 result
= typtup
->typlen
;
2208 ReleaseSysCache(tp
);
2218 * Given the type OID, determine whether the type is returned by value or
2219 * not. Returns true if by value, false if by reference.
2222 get_typbyval(Oid typid
)
2226 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2227 if (HeapTupleIsValid(tp
))
2229 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2232 result
= typtup
->typbyval
;
2233 ReleaseSysCache(tp
);
2243 * A two-fer: given the type OID, return both typlen and typbyval.
2245 * Since both pieces of info are needed to know how to copy a Datum,
2246 * many places need both. Might as well get them with one cache lookup
2247 * instead of two. Also, this routine raises an error instead of
2248 * returning a bogus value when given a bad type OID.
2251 get_typlenbyval(Oid typid
, int16
*typlen
, bool *typbyval
)
2254 Form_pg_type typtup
;
2256 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2257 if (!HeapTupleIsValid(tp
))
2258 elog(ERROR
, "cache lookup failed for type %u", typid
);
2259 typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2260 *typlen
= typtup
->typlen
;
2261 *typbyval
= typtup
->typbyval
;
2262 ReleaseSysCache(tp
);
2266 * get_typlenbyvalalign
2268 * A three-fer: given the type OID, return typlen, typbyval, typalign.
2271 get_typlenbyvalalign(Oid typid
, int16
*typlen
, bool *typbyval
,
2275 Form_pg_type typtup
;
2277 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2278 if (!HeapTupleIsValid(tp
))
2279 elog(ERROR
, "cache lookup failed for type %u", typid
);
2280 typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2281 *typlen
= typtup
->typlen
;
2282 *typbyval
= typtup
->typbyval
;
2283 *typalign
= typtup
->typalign
;
2284 ReleaseSysCache(tp
);
2289 * Given a pg_type row, select the type OID to pass to I/O functions
2291 * Formerly, all I/O functions were passed pg_type.typelem as their second
2292 * parameter, but we now have a more complex rule about what to pass.
2293 * This knowledge is intended to be centralized here --- direct references
2294 * to typelem elsewhere in the code are wrong, if they are associated with
2295 * I/O calls and not with actual subscripting operations! (But see
2296 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2298 * As of PostgreSQL 8.1, output functions receive only the value itself
2299 * and not any auxiliary parameters, so the name of this routine is now
2300 * a bit of a misnomer ... it should be getTypeInputParam.
2303 getTypeIOParam(HeapTuple typeTuple
)
2305 Form_pg_type typeStruct
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2308 * Array types get their typelem as parameter; everybody else gets their
2309 * own type OID as parameter.
2311 if (OidIsValid(typeStruct
->typelem
))
2312 return typeStruct
->typelem
;
2314 return typeStruct
->oid
;
2320 * A six-fer: given the type OID, return typlen, typbyval, typalign,
2321 * typdelim, typioparam, and IO function OID. The IO function
2322 * returned is controlled by IOFuncSelector
2325 get_type_io_data(Oid typid
,
2326 IOFuncSelector which_func
,
2334 HeapTuple typeTuple
;
2335 Form_pg_type typeStruct
;
2338 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2339 * use array_in and array_out during bootstrap.
2341 if (IsBootstrapProcessingMode())
2346 boot_get_type_io_data(typid
,
2363 elog(ERROR
, "binary I/O not supported during bootstrap");
2369 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2370 if (!HeapTupleIsValid(typeTuple
))
2371 elog(ERROR
, "cache lookup failed for type %u", typid
);
2372 typeStruct
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2374 *typlen
= typeStruct
->typlen
;
2375 *typbyval
= typeStruct
->typbyval
;
2376 *typalign
= typeStruct
->typalign
;
2377 *typdelim
= typeStruct
->typdelim
;
2378 *typioparam
= getTypeIOParam(typeTuple
);
2382 *func
= typeStruct
->typinput
;
2385 *func
= typeStruct
->typoutput
;
2387 case IOFunc_receive
:
2388 *func
= typeStruct
->typreceive
;
2391 *func
= typeStruct
->typsend
;
2394 ReleaseSysCache(typeTuple
);
2399 get_typalign(Oid typid
)
2403 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2404 if (HeapTupleIsValid(tp
))
2406 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2409 result
= typtup
->typalign
;
2410 ReleaseSysCache(tp
);
2414 return TYPALIGN_INT
;
2419 get_typstorage(Oid typid
)
2423 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2424 if (HeapTupleIsValid(tp
))
2426 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2429 result
= typtup
->typstorage
;
2430 ReleaseSysCache(tp
);
2434 return TYPSTORAGE_PLAIN
;
2439 * Given a type OID, return the type's default value, if any.
2441 * The result is a palloc'd expression node tree, or NULL if there
2442 * is no defined default for the datatype.
2444 * NB: caller should be prepared to coerce result to correct datatype;
2445 * the returned expression tree might produce something of the wrong type.
2448 get_typdefault(Oid typid
)
2450 HeapTuple typeTuple
;
2456 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2457 if (!HeapTupleIsValid(typeTuple
))
2458 elog(ERROR
, "cache lookup failed for type %u", typid
);
2459 type
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2462 * typdefault and typdefaultbin are potentially null, so don't try to
2463 * access 'em as struct fields. Must do it the hard way with
2466 datum
= SysCacheGetAttr(TYPEOID
,
2468 Anum_pg_type_typdefaultbin
,
2473 /* We have an expression default */
2474 expr
= stringToNode(TextDatumGetCString(datum
));
2478 /* Perhaps we have a plain literal default */
2479 datum
= SysCacheGetAttr(TYPEOID
,
2481 Anum_pg_type_typdefault
,
2486 char *strDefaultVal
;
2488 /* Convert text datum to C string */
2489 strDefaultVal
= TextDatumGetCString(datum
);
2490 /* Convert C string to a value of the given type */
2491 datum
= OidInputFunctionCall(type
->typinput
, strDefaultVal
,
2492 getTypeIOParam(typeTuple
), -1);
2493 /* Build a Const node containing the value */
2494 expr
= (Node
*) makeConst(typid
,
2501 pfree(strDefaultVal
);
2510 ReleaseSysCache(typeTuple
);
2517 * If the given type is a domain, return its base type;
2518 * otherwise return the type's own OID.
2521 getBaseType(Oid typid
)
2525 return getBaseTypeAndTypmod(typid
, &typmod
);
2529 * getBaseTypeAndTypmod
2530 * If the given type is a domain, return its base type and typmod;
2531 * otherwise return the type's own OID, and leave *typmod unchanged.
2533 * Note that the "applied typmod" should be -1 for every domain level
2534 * above the bottommost; therefore, if the passed-in typid is indeed
2535 * a domain, *typmod should be -1.
2538 getBaseTypeAndTypmod(Oid typid
, int32
*typmod
)
2541 * We loop to find the bottom base type in a stack of domains.
2546 Form_pg_type typTup
;
2548 tup
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2549 if (!HeapTupleIsValid(tup
))
2550 elog(ERROR
, "cache lookup failed for type %u", typid
);
2551 typTup
= (Form_pg_type
) GETSTRUCT(tup
);
2552 if (typTup
->typtype
!= TYPTYPE_DOMAIN
)
2554 /* Not a domain, so done */
2555 ReleaseSysCache(tup
);
2559 Assert(*typmod
== -1);
2560 typid
= typTup
->typbasetype
;
2561 *typmod
= typTup
->typtypmod
;
2563 ReleaseSysCache(tup
);
2572 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2573 * estimate the average width of values of the type. This is used by
2574 * the planner, which doesn't require absolutely correct results;
2575 * it's OK (and expected) to guess if we don't know for sure.
2578 get_typavgwidth(Oid typid
, int32 typmod
)
2580 int typlen
= get_typlen(typid
);
2584 * Easy if it's a fixed-width type
2590 * type_maximum_size knows the encoding of typmod for some datatypes;
2591 * don't duplicate that knowledge here.
2593 maxwidth
= type_maximum_size(typid
, typmod
);
2597 * For BPCHAR, the max width is also the only width. Otherwise we
2598 * need to guess about the typical data width given the max. A sliding
2599 * scale for percentage of max width seems reasonable.
2601 if (typid
== BPCHAROID
)
2604 return maxwidth
; /* assume full width */
2605 if (maxwidth
< 1000)
2606 return 32 + (maxwidth
- 32) / 2; /* assume 50% */
2609 * Beyond 1000, assume we're looking at something like
2610 * "varchar(10000)" where the limit isn't actually reached often, and
2611 * use a fixed estimate.
2613 return 32 + (1000 - 32) / 2;
2617 * Oops, we have no idea ... wild guess time.
2625 * Given the type OID, find if it is a basic type, a complex type, etc.
2626 * It returns the null char if the cache lookup fails...
2629 get_typtype(Oid typid
)
2633 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2634 if (HeapTupleIsValid(tp
))
2636 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2639 result
= typtup
->typtype
;
2640 ReleaseSysCache(tp
);
2650 * Convenience function to determine whether a type OID represents
2651 * a "rowtype" type --- either RECORD or a named composite type
2652 * (including a domain over a named composite type).
2655 type_is_rowtype(Oid typid
)
2657 if (typid
== RECORDOID
)
2658 return true; /* easy case */
2659 switch (get_typtype(typid
))
2661 case TYPTYPE_COMPOSITE
:
2663 case TYPTYPE_DOMAIN
:
2664 if (get_typtype(getBaseType(typid
)) == TYPTYPE_COMPOSITE
)
2675 * Returns true if the given type is an enum type.
2678 type_is_enum(Oid typid
)
2680 return (get_typtype(typid
) == TYPTYPE_ENUM
);
2685 * Returns true if the given type is a range type.
2688 type_is_range(Oid typid
)
2690 return (get_typtype(typid
) == TYPTYPE_RANGE
);
2694 * type_is_multirange
2695 * Returns true if the given type is a multirange type.
2698 type_is_multirange(Oid typid
)
2700 return (get_typtype(typid
) == TYPTYPE_MULTIRANGE
);
2704 * get_type_category_preferred
2706 * Given the type OID, fetch its category and preferred-type status.
2707 * Throws error on failure.
2710 get_type_category_preferred(Oid typid
, char *typcategory
, bool *typispreferred
)
2713 Form_pg_type typtup
;
2715 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2716 if (!HeapTupleIsValid(tp
))
2717 elog(ERROR
, "cache lookup failed for type %u", typid
);
2718 typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2719 *typcategory
= typtup
->typcategory
;
2720 *typispreferred
= typtup
->typispreferred
;
2721 ReleaseSysCache(tp
);
2727 * Given the type OID, get the typrelid (InvalidOid if not a complex
2731 get_typ_typrelid(Oid typid
)
2735 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2736 if (HeapTupleIsValid(tp
))
2738 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2741 result
= typtup
->typrelid
;
2742 ReleaseSysCache(tp
);
2752 * Given the type OID, get the typelem (InvalidOid if not an array type).
2754 * NB: this only succeeds for "true" arrays having array_subscript_handler
2755 * as typsubscript. For other types, InvalidOid is returned independently
2756 * of whether they have typelem or typsubscript set.
2759 get_element_type(Oid typid
)
2763 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2764 if (HeapTupleIsValid(tp
))
2766 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
2769 if (IsTrueArrayType(typtup
))
2770 result
= typtup
->typelem
;
2772 result
= InvalidOid
;
2773 ReleaseSysCache(tp
);
2783 * Given the type OID, get the corresponding "true" array type.
2784 * Returns InvalidOid if no array type can be found.
2787 get_array_type(Oid typid
)
2790 Oid result
= InvalidOid
;
2792 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2793 if (HeapTupleIsValid(tp
))
2795 result
= ((Form_pg_type
) GETSTRUCT(tp
))->typarray
;
2796 ReleaseSysCache(tp
);
2802 * get_promoted_array_type
2804 * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
2805 * construct, that is, either the corresponding "true" array type
2806 * if the input is a scalar type that has such an array type,
2807 * or the same type if the input is already a "true" array type.
2808 * Returns InvalidOid if neither rule is satisfied.
2811 get_promoted_array_type(Oid typid
)
2813 Oid array_type
= get_array_type(typid
);
2815 if (OidIsValid(array_type
))
2817 if (OidIsValid(get_element_type(typid
)))
2823 * get_base_element_type
2824 * Given the type OID, get the typelem, looking "through" any domain
2825 * to its underlying array type.
2827 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2828 * an extra cache lookup. Note that it fails to provide any information
2829 * about the typmod of the array.
2832 get_base_element_type(Oid typid
)
2835 * We loop to find the bottom base type in a stack of domains.
2840 Form_pg_type typTup
;
2842 tup
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
2843 if (!HeapTupleIsValid(tup
))
2845 typTup
= (Form_pg_type
) GETSTRUCT(tup
);
2846 if (typTup
->typtype
!= TYPTYPE_DOMAIN
)
2848 /* Not a domain, so stop descending */
2851 /* This test must match get_element_type */
2852 if (IsTrueArrayType(typTup
))
2853 result
= typTup
->typelem
;
2855 result
= InvalidOid
;
2856 ReleaseSysCache(tup
);
2860 typid
= typTup
->typbasetype
;
2861 ReleaseSysCache(tup
);
2864 /* Like get_element_type, silently return InvalidOid for bogus input */
2871 * Get info needed for converting values of a type to internal form
2874 getTypeInputInfo(Oid type
, Oid
*typInput
, Oid
*typIOParam
)
2876 HeapTuple typeTuple
;
2879 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(type
));
2880 if (!HeapTupleIsValid(typeTuple
))
2881 elog(ERROR
, "cache lookup failed for type %u", type
);
2882 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2884 if (!pt
->typisdefined
)
2886 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2887 errmsg("type %s is only a shell",
2888 format_type_be(type
))));
2889 if (!OidIsValid(pt
->typinput
))
2891 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2892 errmsg("no input function available for type %s",
2893 format_type_be(type
))));
2895 *typInput
= pt
->typinput
;
2896 *typIOParam
= getTypeIOParam(typeTuple
);
2898 ReleaseSysCache(typeTuple
);
2904 * Get info needed for printing values of a type
2907 getTypeOutputInfo(Oid type
, Oid
*typOutput
, bool *typIsVarlena
)
2909 HeapTuple typeTuple
;
2912 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(type
));
2913 if (!HeapTupleIsValid(typeTuple
))
2914 elog(ERROR
, "cache lookup failed for type %u", type
);
2915 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2917 if (!pt
->typisdefined
)
2919 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2920 errmsg("type %s is only a shell",
2921 format_type_be(type
))));
2922 if (!OidIsValid(pt
->typoutput
))
2924 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2925 errmsg("no output function available for type %s",
2926 format_type_be(type
))));
2928 *typOutput
= pt
->typoutput
;
2929 *typIsVarlena
= (!pt
->typbyval
) && (pt
->typlen
== -1);
2931 ReleaseSysCache(typeTuple
);
2935 * getTypeBinaryInputInfo
2937 * Get info needed for binary input of values of a type
2940 getTypeBinaryInputInfo(Oid type
, Oid
*typReceive
, Oid
*typIOParam
)
2942 HeapTuple typeTuple
;
2945 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(type
));
2946 if (!HeapTupleIsValid(typeTuple
))
2947 elog(ERROR
, "cache lookup failed for type %u", type
);
2948 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2950 if (!pt
->typisdefined
)
2952 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2953 errmsg("type %s is only a shell",
2954 format_type_be(type
))));
2955 if (!OidIsValid(pt
->typreceive
))
2957 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2958 errmsg("no binary input function available for type %s",
2959 format_type_be(type
))));
2961 *typReceive
= pt
->typreceive
;
2962 *typIOParam
= getTypeIOParam(typeTuple
);
2964 ReleaseSysCache(typeTuple
);
2968 * getTypeBinaryOutputInfo
2970 * Get info needed for binary output of values of a type
2973 getTypeBinaryOutputInfo(Oid type
, Oid
*typSend
, bool *typIsVarlena
)
2975 HeapTuple typeTuple
;
2978 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(type
));
2979 if (!HeapTupleIsValid(typeTuple
))
2980 elog(ERROR
, "cache lookup failed for type %u", type
);
2981 pt
= (Form_pg_type
) GETSTRUCT(typeTuple
);
2983 if (!pt
->typisdefined
)
2985 (errcode(ERRCODE_UNDEFINED_OBJECT
),
2986 errmsg("type %s is only a shell",
2987 format_type_be(type
))));
2988 if (!OidIsValid(pt
->typsend
))
2990 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
2991 errmsg("no binary output function available for type %s",
2992 format_type_be(type
))));
2994 *typSend
= pt
->typsend
;
2995 *typIsVarlena
= (!pt
->typbyval
) && (pt
->typlen
== -1);
2997 ReleaseSysCache(typeTuple
);
3003 * Given the type OID, return the type's typmodin procedure, if any.
3006 get_typmodin(Oid typid
)
3010 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
3011 if (HeapTupleIsValid(tp
))
3013 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
3016 result
= typtup
->typmodin
;
3017 ReleaseSysCache(tp
);
3028 * Given the type OID, return the type's typmodout procedure, if any.
3031 get_typmodout(Oid typid
)
3035 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
3036 if (HeapTupleIsValid(tp
))
3038 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
3041 result
= typtup
->typmodout
;
3042 ReleaseSysCache(tp
);
3048 #endif /* NOT_USED */
3053 * Given the type OID, return the type's typcollation attribute.
3056 get_typcollation(Oid typid
)
3060 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
3061 if (HeapTupleIsValid(tp
))
3063 Form_pg_type typtup
= (Form_pg_type
) GETSTRUCT(tp
);
3066 result
= typtup
->typcollation
;
3067 ReleaseSysCache(tp
);
3076 * type_is_collatable
3078 * Return whether the type cares about collations
3081 type_is_collatable(Oid typid
)
3083 return OidIsValid(get_typcollation(typid
));
3090 * Given the type OID, return the type's subscripting handler's OID,
3093 * If typelemp isn't NULL, we also store the type's typelem value there.
3094 * This saves some callers an extra catalog lookup.
3097 get_typsubscript(Oid typid
, Oid
*typelemp
)
3101 tp
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(typid
));
3102 if (HeapTupleIsValid(tp
))
3104 Form_pg_type typform
= (Form_pg_type
) GETSTRUCT(tp
);
3105 RegProcedure handler
= typform
->typsubscript
;
3108 *typelemp
= typform
->typelem
;
3109 ReleaseSysCache(tp
);
3115 *typelemp
= InvalidOid
;
3121 * getSubscriptingRoutines
3123 * Given the type OID, fetch the type's subscripting methods struct.
3124 * Return NULL if type is not subscriptable.
3126 * If typelemp isn't NULL, we also store the type's typelem value there.
3127 * This saves some callers an extra catalog lookup.
3129 const struct SubscriptRoutines
*
3130 getSubscriptingRoutines(Oid typid
, Oid
*typelemp
)
3132 RegProcedure typsubscript
= get_typsubscript(typid
, typelemp
);
3134 if (!OidIsValid(typsubscript
))
3137 return (const struct SubscriptRoutines
*)
3138 DatumGetPointer(OidFunctionCall0(typsubscript
));
3142 /* ---------- STATISTICS CACHE ---------- */
3147 * Given the table and attribute number of a column, get the average
3148 * width of entries in the column. Return zero if no data available.
3150 * Currently this is only consulted for individual tables, not for inheritance
3151 * trees, so we don't need an "inh" parameter.
3153 * Calling a hook at this point looks somewhat strange, but is required
3154 * because the optimizer calls this function without any other way for
3155 * plug-ins to control the result.
3158 get_attavgwidth(Oid relid
, AttrNumber attnum
)
3163 if (get_attavgwidth_hook
)
3165 stawidth
= (*get_attavgwidth_hook
) (relid
, attnum
);
3169 tp
= SearchSysCache3(STATRELATTINH
,
3170 ObjectIdGetDatum(relid
),
3171 Int16GetDatum(attnum
),
3172 BoolGetDatum(false));
3173 if (HeapTupleIsValid(tp
))
3175 stawidth
= ((Form_pg_statistic
) GETSTRUCT(tp
))->stawidth
;
3176 ReleaseSysCache(tp
);
3186 * Extract the contents of a "slot" of a pg_statistic tuple.
3187 * Returns true if requested slot type was found, else false.
3189 * Unlike other routines in this file, this takes a pointer to an
3190 * already-looked-up tuple in the pg_statistic cache. We do this since
3191 * most callers will want to extract more than one value from the cache
3192 * entry, and we don't want to repeat the cache lookup unnecessarily.
3193 * Also, this API allows this routine to be used with statistics tuples
3194 * that have been provided by a stats hook and didn't really come from
3197 * sslot: pointer to output area (typically, a local variable in the caller).
3198 * statstuple: pg_statistic tuple to be examined.
3199 * reqkind: STAKIND code for desired statistics slot kind.
3200 * reqop: STAOP value wanted, or InvalidOid if don't care.
3201 * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3203 * If a matching slot is found, true is returned, and *sslot is filled thus:
3204 * staop: receives the actual STAOP value.
3205 * stacoll: receives the actual STACOLL value.
3206 * valuetype: receives actual datatype of the elements of stavalues.
3207 * values: receives pointer to an array of the slot's stavalues.
3208 * nvalues: receives number of stavalues.
3209 * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3210 * nnumbers: receives number of stanumbers.
3212 * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3213 * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3214 * ATTSTATSSLOT_NUMBERS wasn't specified.
3216 * If no matching slot is found, false is returned, and *sslot is zeroed.
3218 * Note that the current API doesn't allow for searching for a slot with
3219 * a particular collation. If we ever actually support recording more than
3220 * one collation, we'll have to extend the API, but for now simple is good.
3222 * The data referred to by the fields of sslot is locally palloc'd and
3223 * is independent of the original pg_statistic tuple. When the caller
3224 * is done with it, call free_attstatsslot to release the palloc'd data.
3226 * If it's desirable to call free_attstatsslot when get_attstatsslot might
3227 * not have been called, memset'ing sslot to zeroes will allow that.
3229 * Passing flags=0 can be useful to quickly check if the requested slot type
3230 * exists. In this case no arrays are extracted, so free_attstatsslot need
3234 get_attstatsslot(AttStatsSlot
*sslot
, HeapTuple statstuple
,
3235 int reqkind
, Oid reqop
, int flags
)
3237 Form_pg_statistic stats
= (Form_pg_statistic
) GETSTRUCT(statstuple
);
3240 ArrayType
*statarray
;
3243 HeapTuple typeTuple
;
3244 Form_pg_type typeForm
;
3246 /* initialize *sslot properly */
3247 memset(sslot
, 0, sizeof(AttStatsSlot
));
3249 for (i
= 0; i
< STATISTIC_NUM_SLOTS
; i
++)
3251 if ((&stats
->stakind1
)[i
] == reqkind
&&
3252 (reqop
== InvalidOid
|| (&stats
->staop1
)[i
] == reqop
))
3255 if (i
>= STATISTIC_NUM_SLOTS
)
3256 return false; /* not there */
3258 sslot
->staop
= (&stats
->staop1
)[i
];
3259 sslot
->stacoll
= (&stats
->stacoll1
)[i
];
3261 if (flags
& ATTSTATSSLOT_VALUES
)
3263 val
= SysCacheGetAttrNotNull(STATRELATTINH
, statstuple
,
3264 Anum_pg_statistic_stavalues1
+ i
);
3267 * Detoast the array if needed, and in any case make a copy that's
3268 * under control of this AttStatsSlot.
3270 statarray
= DatumGetArrayTypePCopy(val
);
3273 * Extract the actual array element type, and pass it back in case the
3276 sslot
->valuetype
= arrayelemtype
= ARR_ELEMTYPE(statarray
);
3278 /* Need info about element type */
3279 typeTuple
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(arrayelemtype
));
3280 if (!HeapTupleIsValid(typeTuple
))
3281 elog(ERROR
, "cache lookup failed for type %u", arrayelemtype
);
3282 typeForm
= (Form_pg_type
) GETSTRUCT(typeTuple
);
3284 /* Deconstruct array into Datum elements; NULLs not expected */
3285 deconstruct_array(statarray
,
3290 &sslot
->values
, NULL
, &sslot
->nvalues
);
3293 * If the element type is pass-by-reference, we now have a bunch of
3294 * Datums that are pointers into the statarray, so we need to keep
3295 * that until free_attstatsslot. Otherwise, all the useful info is in
3296 * sslot->values[], so we can free the array object immediately.
3298 if (!typeForm
->typbyval
)
3299 sslot
->values_arr
= statarray
;
3303 ReleaseSysCache(typeTuple
);
3306 if (flags
& ATTSTATSSLOT_NUMBERS
)
3308 val
= SysCacheGetAttrNotNull(STATRELATTINH
, statstuple
,
3309 Anum_pg_statistic_stanumbers1
+ i
);
3312 * Detoast the array if needed, and in any case make a copy that's
3313 * under control of this AttStatsSlot.
3315 statarray
= DatumGetArrayTypePCopy(val
);
3318 * We expect the array to be a 1-D float4 array; verify that. We don't
3319 * need to use deconstruct_array() since the array data is just going
3320 * to look like a C array of float4 values.
3322 narrayelem
= ARR_DIMS(statarray
)[0];
3323 if (ARR_NDIM(statarray
) != 1 || narrayelem
<= 0 ||
3324 ARR_HASNULL(statarray
) ||
3325 ARR_ELEMTYPE(statarray
) != FLOAT4OID
)
3326 elog(ERROR
, "stanumbers is not a 1-D float4 array");
3328 /* Give caller a pointer directly into the statarray */
3329 sslot
->numbers
= (float4
*) ARR_DATA_PTR(statarray
);
3330 sslot
->nnumbers
= narrayelem
;
3332 /* We'll free the statarray in free_attstatsslot */
3333 sslot
->numbers_arr
= statarray
;
3341 * Free data allocated by get_attstatsslot
3344 free_attstatsslot(AttStatsSlot
*sslot
)
3346 /* The values[] array was separately palloc'd by deconstruct_array */
3348 pfree(sslot
->values
);
3349 /* The numbers[] array points into numbers_arr, do not pfree it */
3350 /* Free the detoasted array objects, if any */
3351 if (sslot
->values_arr
)
3352 pfree(sslot
->values_arr
);
3353 if (sslot
->numbers_arr
)
3354 pfree(sslot
->numbers_arr
);
3357 /* ---------- PG_NAMESPACE CACHE ---------- */
3360 * get_namespace_name
3361 * Returns the name of a given namespace
3363 * Returns a palloc'd copy of the string, or NULL if no such namespace.
3366 get_namespace_name(Oid nspid
)
3370 tp
= SearchSysCache1(NAMESPACEOID
, ObjectIdGetDatum(nspid
));
3371 if (HeapTupleIsValid(tp
))
3373 Form_pg_namespace nsptup
= (Form_pg_namespace
) GETSTRUCT(tp
);
3376 result
= pstrdup(NameStr(nsptup
->nspname
));
3377 ReleaseSysCache(tp
);
3385 * get_namespace_name_or_temp
3386 * As above, but if it is this backend's temporary namespace, return
3387 * "pg_temp" instead.
3390 get_namespace_name_or_temp(Oid nspid
)
3392 if (isTempNamespace(nspid
))
3393 return pstrdup("pg_temp");
3395 return get_namespace_name(nspid
);
3398 /* ---------- PG_RANGE CACHES ---------- */
3402 * Returns the subtype of a given range type
3404 * Returns InvalidOid if the type is not a range type.
3407 get_range_subtype(Oid rangeOid
)
3411 tp
= SearchSysCache1(RANGETYPE
, ObjectIdGetDatum(rangeOid
));
3412 if (HeapTupleIsValid(tp
))
3414 Form_pg_range rngtup
= (Form_pg_range
) GETSTRUCT(tp
);
3417 result
= rngtup
->rngsubtype
;
3418 ReleaseSysCache(tp
);
3426 * get_range_collation
3427 * Returns the collation of a given range type
3429 * Returns InvalidOid if the type is not a range type,
3430 * or if its subtype is not collatable.
3433 get_range_collation(Oid rangeOid
)
3437 tp
= SearchSysCache1(RANGETYPE
, ObjectIdGetDatum(rangeOid
));
3438 if (HeapTupleIsValid(tp
))
3440 Form_pg_range rngtup
= (Form_pg_range
) GETSTRUCT(tp
);
3443 result
= rngtup
->rngcollation
;
3444 ReleaseSysCache(tp
);
3452 * get_range_multirange
3453 * Returns the multirange type of a given range type
3455 * Returns InvalidOid if the type is not a range type.
3458 get_range_multirange(Oid rangeOid
)
3462 tp
= SearchSysCache1(RANGETYPE
, ObjectIdGetDatum(rangeOid
));
3463 if (HeapTupleIsValid(tp
))
3465 Form_pg_range rngtup
= (Form_pg_range
) GETSTRUCT(tp
);
3468 result
= rngtup
->rngmultitypid
;
3469 ReleaseSysCache(tp
);
3477 * get_multirange_range
3478 * Returns the range type of a given multirange
3480 * Returns InvalidOid if the type is not a multirange.
3483 get_multirange_range(Oid multirangeOid
)
3487 tp
= SearchSysCache1(RANGEMULTIRANGE
, ObjectIdGetDatum(multirangeOid
));
3488 if (HeapTupleIsValid(tp
))
3490 Form_pg_range rngtup
= (Form_pg_range
) GETSTRUCT(tp
);
3493 result
= rngtup
->rngtypid
;
3494 ReleaseSysCache(tp
);
3501 /* ---------- PG_INDEX CACHE ---------- */
3504 * get_index_column_opclass
3506 * Given the index OID and column number,
3507 * return opclass of the index column
3508 * or InvalidOid if the index was not found
3509 * or column is non-key one.
3512 get_index_column_opclass(Oid index_oid
, int attno
)
3515 Form_pg_index rd_index
;
3517 oidvector
*indclass
;
3520 /* First we need to know the column's opclass. */
3522 tuple
= SearchSysCache1(INDEXRELID
, ObjectIdGetDatum(index_oid
));
3523 if (!HeapTupleIsValid(tuple
))
3526 rd_index
= (Form_pg_index
) GETSTRUCT(tuple
);
3528 /* caller is supposed to guarantee this */
3529 Assert(attno
> 0 && attno
<= rd_index
->indnatts
);
3531 /* Non-key attributes don't have an opclass */
3532 if (attno
> rd_index
->indnkeyatts
)
3534 ReleaseSysCache(tuple
);
3538 datum
= SysCacheGetAttrNotNull(INDEXRELID
, tuple
, Anum_pg_index_indclass
);
3539 indclass
= ((oidvector
*) DatumGetPointer(datum
));
3541 Assert(attno
<= indclass
->dim1
);
3542 opclass
= indclass
->values
[attno
- 1];
3544 ReleaseSysCache(tuple
);
3550 * get_index_isreplident
3552 * Given the index OID, return pg_index.indisreplident.
3555 get_index_isreplident(Oid index_oid
)
3558 Form_pg_index rd_index
;
3561 tuple
= SearchSysCache1(INDEXRELID
, ObjectIdGetDatum(index_oid
));
3562 if (!HeapTupleIsValid(tuple
))
3565 rd_index
= (Form_pg_index
) GETSTRUCT(tuple
);
3566 result
= rd_index
->indisreplident
;
3567 ReleaseSysCache(tuple
);
3575 * Given the index OID, return pg_index.indisvalid.
3578 get_index_isvalid(Oid index_oid
)
3582 Form_pg_index rd_index
;
3584 tuple
= SearchSysCache1(INDEXRELID
, ObjectIdGetDatum(index_oid
));
3585 if (!HeapTupleIsValid(tuple
))
3586 elog(ERROR
, "cache lookup failed for index %u", index_oid
);
3588 rd_index
= (Form_pg_index
) GETSTRUCT(tuple
);
3589 isvalid
= rd_index
->indisvalid
;
3590 ReleaseSysCache(tuple
);
3596 * get_index_isclustered
3598 * Given the index OID, return pg_index.indisclustered.
3601 get_index_isclustered(Oid index_oid
)
3605 Form_pg_index rd_index
;
3607 tuple
= SearchSysCache1(INDEXRELID
, ObjectIdGetDatum(index_oid
));
3608 if (!HeapTupleIsValid(tuple
))
3609 elog(ERROR
, "cache lookup failed for index %u", index_oid
);
3611 rd_index
= (Form_pg_index
) GETSTRUCT(tuple
);
3612 isclustered
= rd_index
->indisclustered
;
3613 ReleaseSysCache(tuple
);
3619 * get_publication_oid - given a publication name, look up the OID
3621 * If missing_ok is false, throw an error if name not found. If true, just
3622 * return InvalidOid.
3625 get_publication_oid(const char *pubname
, bool missing_ok
)
3629 oid
= GetSysCacheOid1(PUBLICATIONNAME
, Anum_pg_publication_oid
,
3630 CStringGetDatum(pubname
));
3631 if (!OidIsValid(oid
) && !missing_ok
)
3633 (errcode(ERRCODE_UNDEFINED_OBJECT
),
3634 errmsg("publication \"%s\" does not exist", pubname
)));
3639 * get_publication_name - given a publication Oid, look up the name
3641 * If missing_ok is false, throw an error if name not found. If true, just
3645 get_publication_name(Oid pubid
, bool missing_ok
)
3649 Form_pg_publication pubform
;
3651 tup
= SearchSysCache1(PUBLICATIONOID
, ObjectIdGetDatum(pubid
));
3653 if (!HeapTupleIsValid(tup
))
3656 elog(ERROR
, "cache lookup failed for publication %u", pubid
);
3660 pubform
= (Form_pg_publication
) GETSTRUCT(tup
);
3661 pubname
= pstrdup(NameStr(pubform
->pubname
));
3663 ReleaseSysCache(tup
);
3669 * get_subscription_oid - given a subscription name, look up the OID
3671 * If missing_ok is false, throw an error if name not found. If true, just
3672 * return InvalidOid.
3675 get_subscription_oid(const char *subname
, bool missing_ok
)
3679 oid
= GetSysCacheOid2(SUBSCRIPTIONNAME
, Anum_pg_subscription_oid
,
3680 MyDatabaseId
, CStringGetDatum(subname
));
3681 if (!OidIsValid(oid
) && !missing_ok
)
3683 (errcode(ERRCODE_UNDEFINED_OBJECT
),
3684 errmsg("subscription \"%s\" does not exist", subname
)));
3689 * get_subscription_name - given a subscription OID, look up the name
3691 * If missing_ok is false, throw an error if name not found. If true, just
3695 get_subscription_name(Oid subid
, bool missing_ok
)
3699 Form_pg_subscription subform
;
3701 tup
= SearchSysCache1(SUBSCRIPTIONOID
, ObjectIdGetDatum(subid
));
3703 if (!HeapTupleIsValid(tup
))
3706 elog(ERROR
, "cache lookup failed for subscription %u", subid
);
3710 subform
= (Form_pg_subscription
) GETSTRUCT(tup
);
3711 subname
= pstrdup(NameStr(subform
->subname
));
3713 ReleaseSysCache(tup
);