Allow specifying an access method for partitioned tables
[pgsql.git] / src / backend / utils / cache / lsyscache.c
blob26368ffcc97cc7c12a28b07023757a03a91f133a
1 /*-------------------------------------------------------------------------
3 * lsyscache.c
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
9 * IDENTIFICATION
10 * src/backend/utils/cache/lsyscache.c
12 * NOTES
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
16 #include "postgres.h"
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 ---------- */
59 * op_in_opfamily
61 * Return t iff operator 'opno' is in operator family 'opfamily'.
63 * This function only considers search operators, not ordering operators.
65 bool
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.
82 int
83 get_op_opfamily_strategy(Oid opno, Oid opfamily)
85 HeapTuple tp;
86 Form_pg_amop amop_tup;
87 int result;
89 tp = SearchSysCache3(AMOPOPID,
90 ObjectIdGetDatum(opno),
91 CharGetDatum(AMOP_SEARCH),
92 ObjectIdGetDatum(opfamily));
93 if (!HeapTupleIsValid(tp))
94 return 0;
95 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
96 result = amop_tup->amopstrategy;
97 ReleaseSysCache(tp);
98 return result;
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)
110 HeapTuple tp;
111 Form_pg_amop amop_tup;
112 Oid result;
114 tp = SearchSysCache3(AMOPOPID,
115 ObjectIdGetDatum(opno),
116 CharGetDatum(AMOP_ORDER),
117 ObjectIdGetDatum(opfamily));
118 if (!HeapTupleIsValid(tp))
119 return InvalidOid;
120 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
121 result = amop_tup->amopsortfamily;
122 ReleaseSysCache(tp);
123 return result;
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.
135 void
136 get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
137 int *strategy,
138 Oid *lefttype,
139 Oid *righttype)
141 HeapTuple tp;
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",
150 opno, opfamily);
151 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
152 *strategy = amop_tup->amopstrategy;
153 *lefttype = amop_tup->amoplefttype;
154 *righttype = amop_tup->amoprighttype;
155 ReleaseSysCache(tp);
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,
167 int16 strategy)
169 HeapTuple tp;
170 Form_pg_amop amop_tup;
171 Oid result;
173 tp = SearchSysCache4(AMOPSTRATEGY,
174 ObjectIdGetDatum(opfamily),
175 ObjectIdGetDatum(lefttype),
176 ObjectIdGetDatum(righttype),
177 Int16GetDatum(strategy));
178 if (!HeapTupleIsValid(tp))
179 return InvalidOid;
180 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
181 result = amop_tup->amopopr;
182 ReleaseSysCache(tp);
183 return result;
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.
206 bool
207 get_ordering_op_properties(Oid opno,
208 Oid *opfamily, Oid *opcintype, int16 *strategy)
210 bool result = false;
211 CatCList *catlist;
212 int i;
214 /* ensure outputs are initialized on failure */
215 *opfamily = InvalidOid;
216 *opcintype = InvalidOid;
217 *strategy = 0;
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);
230 /* must be btree */
231 if (aform->amopmethod != BTREE_AM_OID)
232 continue;
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;
244 result = true;
245 break;
250 ReleaseSysCacheList(catlist);
252 return result;
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 "<",
261 * true if it's ">"
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;
270 Oid opfamily;
271 Oid opcintype;
272 int16 strategy;
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,
280 opcintype,
281 opcintype,
282 BTEqualStrategyNumber);
283 if (reverse)
284 *reverse = (strategy == BTGreaterStrategyNumber);
287 return result;
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;
308 CatCList *catlist;
309 int i;
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);
322 /* must be btree */
323 if (aform->amopmethod != BTREE_AM_OID)
324 continue;
326 if (aform->amopstrategy == BTEqualStrategyNumber)
328 /* Found a suitable opfamily, get matching ordering operator */
329 Oid typid;
331 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
332 result = get_opfamily_member(aform->amopfamily,
333 typid, typid,
334 BTLessStrategyNumber);
335 if (OidIsValid(result))
336 break;
337 /* failure probably shouldn't happen, but keep looking if so */
341 ReleaseSysCacheList(catlist);
343 return result;
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.
365 List *
366 get_mergejoin_opfamilies(Oid opno)
368 List *result = NIL;
369 CatCList *catlist;
370 int i;
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);
391 return result;
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.)
409 bool
410 get_compatible_hash_operators(Oid opno,
411 Oid *lhs_opno, Oid *rhs_opno)
413 bool result = false;
414 CatCList *catlist;
415 int i;
417 /* Ensure output args are initialized on failure */
418 if (lhs_opno)
419 *lhs_opno = InvalidOid;
420 if (rhs_opno)
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)
441 if (lhs_opno)
442 *lhs_opno = opno;
443 if (rhs_opno)
444 *rhs_opno = opno;
445 result = true;
446 break;
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.
454 if (lhs_opno)
456 *lhs_opno = get_opfamily_member(aform->amopfamily,
457 aform->amoplefttype,
458 aform->amoplefttype,
459 HTEqualStrategyNumber);
460 if (!OidIsValid(*lhs_opno))
461 continue;
462 /* Matching LHS found, done if caller doesn't want RHS */
463 if (!rhs_opno)
465 result = true;
466 break;
469 if (rhs_opno)
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 */
478 if (lhs_opno)
479 *lhs_opno = InvalidOid;
480 continue;
482 /* Matching RHS found, so done */
483 result = true;
484 break;
489 ReleaseSysCacheList(catlist);
491 return result;
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.)
509 bool
510 get_op_hash_functions(Oid opno,
511 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
513 bool result = false;
514 CatCList *catlist;
515 int i;
517 /* Ensure output args are initialized on failure */
518 if (lhs_procno)
519 *lhs_procno = InvalidOid;
520 if (rhs_procno)
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.
543 if (lhs_procno)
545 *lhs_procno = get_opfamily_proc(aform->amopfamily,
546 aform->amoplefttype,
547 aform->amoplefttype,
548 HASHSTANDARD_PROC);
549 if (!OidIsValid(*lhs_procno))
550 continue;
551 /* Matching LHS found, done if caller doesn't want RHS */
552 if (!rhs_procno)
554 result = true;
555 break;
557 /* Only one lookup needed if given operator is single-type */
558 if (aform->amoplefttype == aform->amoprighttype)
560 *rhs_procno = *lhs_procno;
561 result = true;
562 break;
565 if (rhs_procno)
567 *rhs_procno = get_opfamily_proc(aform->amopfamily,
568 aform->amoprighttype,
569 aform->amoprighttype,
570 HASHSTANDARD_PROC);
571 if (!OidIsValid(*rhs_procno))
573 /* Forget any LHS function from this opfamily */
574 if (lhs_procno)
575 *lhs_procno = InvalidOid;
576 continue;
578 /* Matching RHS found, so done */
579 result = true;
580 break;
585 ReleaseSysCacheList(catlist);
587 return result;
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.
600 List *
601 get_op_btree_interpretation(Oid opno)
603 List *result = NIL;
604 OpBtreeInterpretation *thisresult;
605 CatCList *catlist;
606 int i;
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;
619 /* must be btree */
620 if (op_form->amopmethod != BTREE_AM_OID)
621 continue;
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.
642 if (result == NIL)
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;
657 /* must be btree */
658 if (op_form->amopmethod != BTREE_AM_OID)
659 continue;
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)
667 continue;
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);
683 return result;
687 * equality_ops_are_compatible
688 * Return true if the two given equality operators have compatible
689 * semantics.
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.)
697 bool
698 equality_ops_are_compatible(Oid opno1, Oid opno2)
700 bool result;
701 CatCList *catlist;
702 int i;
704 /* Easy if they're the same operator */
705 if (opno1 == opno2)
706 return true;
709 * We search through all the pg_amop entries for opno1.
711 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
713 result = false;
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))
725 result = true;
726 break;
731 ReleaseSysCacheList(catlist);
733 return result;
737 * comparison_ops_are_compatible
738 * Return true if the two given comparison operators have compatible
739 * semantics.
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.)
748 bool
749 comparison_ops_are_compatible(Oid opno1, Oid opno2)
751 bool result;
752 CatCList *catlist;
753 int i;
755 /* Easy if they're the same operator */
756 if (opno1 == opno2)
757 return true;
760 * We search through all the pg_amop entries for opno1.
762 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
764 result = false;
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))
774 result = true;
775 break;
780 ReleaseSysCacheList(catlist);
782 return result;
786 /* ---------- AMPROC CACHES ---------- */
789 * get_opfamily_proc
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)
798 HeapTuple tp;
799 Form_pg_amproc amproc_tup;
800 RegProcedure result;
802 tp = SearchSysCache4(AMPROCNUM,
803 ObjectIdGetDatum(opfamily),
804 ObjectIdGetDatum(lefttype),
805 ObjectIdGetDatum(righttype),
806 Int16GetDatum(procnum));
807 if (!HeapTupleIsValid(tp))
808 return InvalidOid;
809 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
810 result = amproc_tup->amproc;
811 ReleaseSysCache(tp);
812 return result;
816 /* ---------- ATTRIBUTE CACHES ---------- */
819 * get_attname
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.
826 char *
827 get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
829 HeapTuple tp;
831 tp = SearchSysCache2(ATTNUM,
832 ObjectIdGetDatum(relid), Int16GetDatum(attnum));
833 if (HeapTupleIsValid(tp))
835 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
836 char *result;
838 result = pstrdup(NameStr(att_tup->attname));
839 ReleaseSysCache(tp);
840 return result;
843 if (!missing_ok)
844 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
845 attnum, relid);
846 return NULL;
850 * get_attnum
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).
857 AttrNumber
858 get_attnum(Oid relid, const char *attname)
860 HeapTuple tp;
862 tp = SearchSysCacheAttName(relid, attname);
863 if (HeapTupleIsValid(tp))
865 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
866 AttrNumber result;
868 result = att_tup->attnum;
869 ReleaseSysCache(tp);
870 return result;
872 else
873 return InvalidAttrNumber;
877 * get_attgenerated
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
885 * Boolean test.
887 char
888 get_attgenerated(Oid relid, AttrNumber attnum)
890 HeapTuple tp;
891 Form_pg_attribute att_tup;
892 char result;
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",
899 attnum, relid);
900 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
901 result = att_tup->attgenerated;
902 ReleaseSysCache(tp);
903 return result;
907 * get_atttype
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)
915 HeapTuple tp;
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);
923 Oid result;
925 result = att_tup->atttypid;
926 ReleaseSysCache(tp);
927 return result;
929 else
930 return InvalidOid;
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.
942 void
943 get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
944 Oid *typid, int32 *typmod, Oid *collid)
946 HeapTuple tp;
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",
954 attnum, relid);
955 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
957 *typid = att_tup->atttypid;
958 *typmod = att_tup->atttypmod;
959 *collid = att_tup->attcollation;
960 ReleaseSysCache(tp);
964 * get_attoptions
966 * Given the relation id and the attribute number,
967 * return the attribute options text[] datum, if any.
969 Datum
970 get_attoptions(Oid relid, int16 attnum)
972 HeapTuple tuple;
973 Datum attopts;
974 Datum result;
975 bool isnull;
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",
983 attnum, relid);
985 attopts = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
986 &isnull);
988 if (isnull)
989 result = (Datum) 0;
990 else
991 result = datumCopy(attopts, false, -1); /* text[] */
993 ReleaseSysCache(tuple);
995 return result;
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)
1009 Oid oid;
1011 oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
1012 ObjectIdGetDatum(sourcetypeid),
1013 ObjectIdGetDatum(targettypeid));
1014 if (!OidIsValid(oid) && !missing_ok)
1015 ereport(ERROR,
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))));
1020 return oid;
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.
1034 char *
1035 get_collation_name(Oid colloid)
1037 HeapTuple tp;
1039 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
1040 if (HeapTupleIsValid(tp))
1042 Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
1043 char *result;
1045 result = pstrdup(NameStr(colltup->collname));
1046 ReleaseSysCache(tp);
1047 return result;
1049 else
1050 return NULL;
1053 bool
1054 get_collation_isdeterministic(Oid colloid)
1056 HeapTuple tp;
1057 Form_pg_collation colltup;
1058 bool result;
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);
1066 return result;
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.
1080 char *
1081 get_constraint_name(Oid conoid)
1083 HeapTuple tp;
1085 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1086 if (HeapTupleIsValid(tp))
1088 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
1089 char *result;
1091 result = pstrdup(NameStr(contup->conname));
1092 ReleaseSysCache(tp);
1093 return result;
1095 else
1096 return NULL;
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
1105 * the wrong type.
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)
1115 HeapTuple tp;
1117 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1118 if (HeapTupleIsValid(tp))
1120 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
1121 Oid result;
1123 if (contup->contype == CONSTRAINT_UNIQUE ||
1124 contup->contype == CONSTRAINT_PRIMARY ||
1125 contup->contype == CONSTRAINT_EXCLUSION)
1126 result = contup->conindid;
1127 else
1128 result = InvalidOid;
1129 ReleaseSysCache(tp);
1130 return result;
1132 else
1133 return InvalidOid;
1136 /* ---------- LANGUAGE CACHE ---------- */
1138 char *
1139 get_language_name(Oid langoid, bool missing_ok)
1141 HeapTuple tp;
1143 tp = SearchSysCache1(LANGOID, ObjectIdGetDatum(langoid));
1144 if (HeapTupleIsValid(tp))
1146 Form_pg_language lantup = (Form_pg_language) GETSTRUCT(tp);
1147 char *result;
1149 result = pstrdup(NameStr(lantup->lanname));
1150 ReleaseSysCache(tp);
1151 return result;
1154 if (!missing_ok)
1155 elog(ERROR, "cache lookup failed for language %u",
1156 langoid);
1157 return NULL;
1160 /* ---------- OPCLASS CACHE ---------- */
1163 * get_opclass_family
1165 * Returns the OID of the operator family the opclass belongs to.
1168 get_opclass_family(Oid opclass)
1170 HeapTuple tp;
1171 Form_pg_opclass cla_tup;
1172 Oid result;
1174 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1175 if (!HeapTupleIsValid(tp))
1176 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1177 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1179 result = cla_tup->opcfamily;
1180 ReleaseSysCache(tp);
1181 return result;
1185 * get_opclass_input_type
1187 * Returns the OID of the datatype the opclass indexes.
1190 get_opclass_input_type(Oid opclass)
1192 HeapTuple tp;
1193 Form_pg_opclass cla_tup;
1194 Oid result;
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->opcintype;
1202 ReleaseSysCache(tp);
1203 return result;
1207 * get_opclass_opfamily_and_input_type
1209 * Returns the OID of the operator family the opclass belongs to,
1210 * the OID of the datatype the opclass indexes
1212 bool
1213 get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1215 HeapTuple tp;
1216 Form_pg_opclass cla_tup;
1218 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1219 if (!HeapTupleIsValid(tp))
1220 return false;
1222 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1224 *opfamily = cla_tup->opcfamily;
1225 *opcintype = cla_tup->opcintype;
1227 ReleaseSysCache(tp);
1229 return true;
1233 * get_opclass_method
1235 * Returns the OID of the index access method the opclass belongs to.
1238 get_opclass_method(Oid opclass)
1240 HeapTuple tp;
1241 Form_pg_opclass cla_tup;
1242 Oid result;
1244 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1245 if (!HeapTupleIsValid(tp))
1246 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1247 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1249 result = cla_tup->opcmethod;
1250 ReleaseSysCache(tp);
1251 return result;
1254 /* ---------- OPERATOR CACHE ---------- */
1257 * get_opcode
1259 * Returns the regproc id of the routine used to implement an
1260 * operator given the operator oid.
1262 RegProcedure
1263 get_opcode(Oid opno)
1265 HeapTuple tp;
1267 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1268 if (HeapTupleIsValid(tp))
1270 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1271 RegProcedure result;
1273 result = optup->oprcode;
1274 ReleaseSysCache(tp);
1275 return result;
1277 else
1278 return (RegProcedure) InvalidOid;
1282 * get_opname
1283 * returns the name of the operator with the given opno
1285 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1287 char *
1288 get_opname(Oid opno)
1290 HeapTuple tp;
1292 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1293 if (HeapTupleIsValid(tp))
1295 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1296 char *result;
1298 result = pstrdup(NameStr(optup->oprname));
1299 ReleaseSysCache(tp);
1300 return result;
1302 else
1303 return NULL;
1307 * get_op_rettype
1308 * Given operator oid, return the operator's result type.
1311 get_op_rettype(Oid opno)
1313 HeapTuple tp;
1315 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1316 if (HeapTupleIsValid(tp))
1318 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1319 Oid result;
1321 result = optup->oprresult;
1322 ReleaseSysCache(tp);
1323 return result;
1325 else
1326 return InvalidOid;
1330 * op_input_types
1332 * Returns the left and right input datatypes for an operator
1333 * (InvalidOid if not relevant).
1335 void
1336 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1338 HeapTuple tp;
1339 Form_pg_operator optup;
1341 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1342 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1343 elog(ERROR, "cache lookup failed for operator %u", opno);
1344 optup = (Form_pg_operator) GETSTRUCT(tp);
1345 *lefttype = optup->oprleft;
1346 *righttype = optup->oprright;
1347 ReleaseSysCache(tp);
1351 * op_mergejoinable
1353 * Returns true if the operator is potentially mergejoinable. (The planner
1354 * will fail to find any mergejoin plans unless there are suitable btree
1355 * opfamily entries for this operator and associated sortops. The pg_operator
1356 * flag is just a hint to tell the planner whether to bother looking.)
1358 * In some cases (currently only array_eq and record_eq), mergejoinability
1359 * depends on the specific input data type the operator is invoked for, so
1360 * that must be passed as well. We currently assume that only one input's type
1361 * is needed to check this --- by convention, pass the left input's data type.
1363 bool
1364 op_mergejoinable(Oid opno, Oid inputtype)
1366 bool result = false;
1367 HeapTuple tp;
1368 TypeCacheEntry *typentry;
1371 * For array_eq or record_eq, we can sort if the element or field types
1372 * are all sortable. We could implement all the checks for that here, but
1373 * the typcache already does that and caches the results too, so let's
1374 * rely on the typcache.
1376 if (opno == ARRAY_EQ_OP)
1378 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1379 if (typentry->cmp_proc == F_BTARRAYCMP)
1380 result = true;
1382 else if (opno == RECORD_EQ_OP)
1384 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1385 if (typentry->cmp_proc == F_BTRECORDCMP)
1386 result = true;
1388 else
1390 /* For all other operators, rely on pg_operator.oprcanmerge */
1391 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1392 if (HeapTupleIsValid(tp))
1394 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1396 result = optup->oprcanmerge;
1397 ReleaseSysCache(tp);
1400 return result;
1404 * op_hashjoinable
1406 * Returns true if the operator is hashjoinable. (There must be a suitable
1407 * hash opfamily entry for this operator if it is so marked.)
1409 * In some cases (currently only array_eq), hashjoinability depends on the
1410 * specific input data type the operator is invoked for, so that must be
1411 * passed as well. We currently assume that only one input's type is needed
1412 * to check this --- by convention, pass the left input's data type.
1414 bool
1415 op_hashjoinable(Oid opno, Oid inputtype)
1417 bool result = false;
1418 HeapTuple tp;
1419 TypeCacheEntry *typentry;
1421 /* As in op_mergejoinable, let the typcache handle the hard cases */
1422 if (opno == ARRAY_EQ_OP)
1424 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1425 if (typentry->hash_proc == F_HASH_ARRAY)
1426 result = true;
1428 else if (opno == RECORD_EQ_OP)
1430 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1431 if (typentry->hash_proc == F_HASH_RECORD)
1432 result = true;
1434 else
1436 /* For all other operators, rely on pg_operator.oprcanhash */
1437 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1438 if (HeapTupleIsValid(tp))
1440 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1442 result = optup->oprcanhash;
1443 ReleaseSysCache(tp);
1446 return result;
1450 * op_strict
1452 * Get the proisstrict flag for the operator's underlying function.
1454 bool
1455 op_strict(Oid opno)
1457 RegProcedure funcid = get_opcode(opno);
1459 if (funcid == (RegProcedure) InvalidOid)
1460 elog(ERROR, "operator %u does not exist", opno);
1462 return func_strict((Oid) funcid);
1466 * op_volatile
1468 * Get the provolatile flag for the operator's underlying function.
1470 char
1471 op_volatile(Oid opno)
1473 RegProcedure funcid = get_opcode(opno);
1475 if (funcid == (RegProcedure) InvalidOid)
1476 elog(ERROR, "operator %u does not exist", opno);
1478 return func_volatile((Oid) funcid);
1482 * get_commutator
1484 * Returns the corresponding commutator of an operator.
1487 get_commutator(Oid opno)
1489 HeapTuple tp;
1491 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1492 if (HeapTupleIsValid(tp))
1494 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1495 Oid result;
1497 result = optup->oprcom;
1498 ReleaseSysCache(tp);
1499 return result;
1501 else
1502 return InvalidOid;
1506 * get_negator
1508 * Returns the corresponding negator of an operator.
1511 get_negator(Oid opno)
1513 HeapTuple tp;
1515 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1516 if (HeapTupleIsValid(tp))
1518 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1519 Oid result;
1521 result = optup->oprnegate;
1522 ReleaseSysCache(tp);
1523 return result;
1525 else
1526 return InvalidOid;
1530 * get_oprrest
1532 * Returns procedure id for computing selectivity of an operator.
1534 RegProcedure
1535 get_oprrest(Oid opno)
1537 HeapTuple tp;
1539 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1540 if (HeapTupleIsValid(tp))
1542 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1543 RegProcedure result;
1545 result = optup->oprrest;
1546 ReleaseSysCache(tp);
1547 return result;
1549 else
1550 return (RegProcedure) InvalidOid;
1554 * get_oprjoin
1556 * Returns procedure id for computing selectivity of a join.
1558 RegProcedure
1559 get_oprjoin(Oid opno)
1561 HeapTuple tp;
1563 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1564 if (HeapTupleIsValid(tp))
1566 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1567 RegProcedure result;
1569 result = optup->oprjoin;
1570 ReleaseSysCache(tp);
1571 return result;
1573 else
1574 return (RegProcedure) InvalidOid;
1577 /* ---------- FUNCTION CACHE ---------- */
1580 * get_func_name
1581 * returns the name of the function with the given funcid
1583 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1585 char *
1586 get_func_name(Oid funcid)
1588 HeapTuple tp;
1590 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1591 if (HeapTupleIsValid(tp))
1593 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1594 char *result;
1596 result = pstrdup(NameStr(functup->proname));
1597 ReleaseSysCache(tp);
1598 return result;
1600 else
1601 return NULL;
1605 * get_func_namespace
1607 * Returns the pg_namespace OID associated with a given function.
1610 get_func_namespace(Oid funcid)
1612 HeapTuple tp;
1614 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1615 if (HeapTupleIsValid(tp))
1617 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1618 Oid result;
1620 result = functup->pronamespace;
1621 ReleaseSysCache(tp);
1622 return result;
1624 else
1625 return InvalidOid;
1629 * get_func_rettype
1630 * Given procedure id, return the function's result type.
1633 get_func_rettype(Oid funcid)
1635 HeapTuple tp;
1636 Oid result;
1638 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1639 if (!HeapTupleIsValid(tp))
1640 elog(ERROR, "cache lookup failed for function %u", funcid);
1642 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1643 ReleaseSysCache(tp);
1644 return result;
1648 * get_func_nargs
1649 * Given procedure id, return the number of arguments.
1652 get_func_nargs(Oid funcid)
1654 HeapTuple tp;
1655 int result;
1657 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1658 if (!HeapTupleIsValid(tp))
1659 elog(ERROR, "cache lookup failed for function %u", funcid);
1661 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1662 ReleaseSysCache(tp);
1663 return result;
1667 * get_func_signature
1668 * Given procedure id, return the function's argument and result types.
1669 * (The return value is the result type.)
1671 * The arguments are returned as a palloc'd array.
1674 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1676 HeapTuple tp;
1677 Form_pg_proc procstruct;
1678 Oid result;
1680 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1681 if (!HeapTupleIsValid(tp))
1682 elog(ERROR, "cache lookup failed for function %u", funcid);
1684 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1686 result = procstruct->prorettype;
1687 *nargs = (int) procstruct->pronargs;
1688 Assert(*nargs == procstruct->proargtypes.dim1);
1689 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1690 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1692 ReleaseSysCache(tp);
1693 return result;
1697 * get_func_variadictype
1698 * Given procedure id, return the function's provariadic field.
1701 get_func_variadictype(Oid funcid)
1703 HeapTuple tp;
1704 Oid result;
1706 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1707 if (!HeapTupleIsValid(tp))
1708 elog(ERROR, "cache lookup failed for function %u", funcid);
1710 result = ((Form_pg_proc) GETSTRUCT(tp))->provariadic;
1711 ReleaseSysCache(tp);
1712 return result;
1716 * get_func_retset
1717 * Given procedure id, return the function's proretset flag.
1719 bool
1720 get_func_retset(Oid funcid)
1722 HeapTuple tp;
1723 bool result;
1725 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1726 if (!HeapTupleIsValid(tp))
1727 elog(ERROR, "cache lookup failed for function %u", funcid);
1729 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1730 ReleaseSysCache(tp);
1731 return result;
1735 * func_strict
1736 * Given procedure id, return the function's proisstrict flag.
1738 bool
1739 func_strict(Oid funcid)
1741 HeapTuple tp;
1742 bool result;
1744 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1745 if (!HeapTupleIsValid(tp))
1746 elog(ERROR, "cache lookup failed for function %u", funcid);
1748 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1749 ReleaseSysCache(tp);
1750 return result;
1754 * func_volatile
1755 * Given procedure id, return the function's provolatile flag.
1757 char
1758 func_volatile(Oid funcid)
1760 HeapTuple tp;
1761 char result;
1763 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1764 if (!HeapTupleIsValid(tp))
1765 elog(ERROR, "cache lookup failed for function %u", funcid);
1767 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1768 ReleaseSysCache(tp);
1769 return result;
1773 * func_parallel
1774 * Given procedure id, return the function's proparallel flag.
1776 char
1777 func_parallel(Oid funcid)
1779 HeapTuple tp;
1780 char result;
1782 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1783 if (!HeapTupleIsValid(tp))
1784 elog(ERROR, "cache lookup failed for function %u", funcid);
1786 result = ((Form_pg_proc) GETSTRUCT(tp))->proparallel;
1787 ReleaseSysCache(tp);
1788 return result;
1792 * get_func_prokind
1793 * Given procedure id, return the routine kind.
1795 char
1796 get_func_prokind(Oid funcid)
1798 HeapTuple tp;
1799 char result;
1801 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1802 if (!HeapTupleIsValid(tp))
1803 elog(ERROR, "cache lookup failed for function %u", funcid);
1805 result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
1806 ReleaseSysCache(tp);
1807 return result;
1811 * get_func_leakproof
1812 * Given procedure id, return the function's leakproof field.
1814 bool
1815 get_func_leakproof(Oid funcid)
1817 HeapTuple tp;
1818 bool result;
1820 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1821 if (!HeapTupleIsValid(tp))
1822 elog(ERROR, "cache lookup failed for function %u", funcid);
1824 result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
1825 ReleaseSysCache(tp);
1826 return result;
1830 * get_func_support
1832 * Returns the support function OID associated with a given function,
1833 * or InvalidOid if there is none.
1835 RegProcedure
1836 get_func_support(Oid funcid)
1838 HeapTuple tp;
1840 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1841 if (HeapTupleIsValid(tp))
1843 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1844 RegProcedure result;
1846 result = functup->prosupport;
1847 ReleaseSysCache(tp);
1848 return result;
1850 else
1851 return (RegProcedure) InvalidOid;
1854 /* ---------- RELATION CACHE ---------- */
1857 * get_relname_relid
1858 * Given name and namespace of a relation, look up the OID.
1860 * Returns InvalidOid if there is no such relation.
1863 get_relname_relid(const char *relname, Oid relnamespace)
1865 return GetSysCacheOid2(RELNAMENSP, Anum_pg_class_oid,
1866 PointerGetDatum(relname),
1867 ObjectIdGetDatum(relnamespace));
1870 #ifdef NOT_USED
1872 * get_relnatts
1874 * Returns the number of attributes for a given relation.
1877 get_relnatts(Oid relid)
1879 HeapTuple tp;
1881 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1882 if (HeapTupleIsValid(tp))
1884 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1885 int result;
1887 result = reltup->relnatts;
1888 ReleaseSysCache(tp);
1889 return result;
1891 else
1892 return InvalidAttrNumber;
1894 #endif
1897 * get_rel_name
1898 * Returns the name of a given relation.
1900 * Returns a palloc'd copy of the string, or NULL if no such relation.
1902 * NOTE: since relation name is not unique, be wary of code that uses this
1903 * for anything except preparing error messages.
1905 char *
1906 get_rel_name(Oid relid)
1908 HeapTuple tp;
1910 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1911 if (HeapTupleIsValid(tp))
1913 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1914 char *result;
1916 result = pstrdup(NameStr(reltup->relname));
1917 ReleaseSysCache(tp);
1918 return result;
1920 else
1921 return NULL;
1925 * get_rel_namespace
1927 * Returns the pg_namespace OID associated with a given relation.
1930 get_rel_namespace(Oid relid)
1932 HeapTuple tp;
1934 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1935 if (HeapTupleIsValid(tp))
1937 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1938 Oid result;
1940 result = reltup->relnamespace;
1941 ReleaseSysCache(tp);
1942 return result;
1944 else
1945 return InvalidOid;
1949 * get_rel_type_id
1951 * Returns the pg_type OID associated with a given relation.
1953 * Note: not all pg_class entries have associated pg_type OIDs; so be
1954 * careful to check for InvalidOid result.
1957 get_rel_type_id(Oid relid)
1959 HeapTuple tp;
1961 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1962 if (HeapTupleIsValid(tp))
1964 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1965 Oid result;
1967 result = reltup->reltype;
1968 ReleaseSysCache(tp);
1969 return result;
1971 else
1972 return InvalidOid;
1976 * get_rel_relkind
1978 * Returns the relkind associated with a given relation.
1980 char
1981 get_rel_relkind(Oid relid)
1983 HeapTuple tp;
1985 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1986 if (HeapTupleIsValid(tp))
1988 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1989 char result;
1991 result = reltup->relkind;
1992 ReleaseSysCache(tp);
1993 return result;
1995 else
1996 return '\0';
2000 * get_rel_relispartition
2002 * Returns the relispartition flag associated with a given relation.
2004 bool
2005 get_rel_relispartition(Oid relid)
2007 HeapTuple tp;
2009 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2010 if (HeapTupleIsValid(tp))
2012 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
2013 bool result;
2015 result = reltup->relispartition;
2016 ReleaseSysCache(tp);
2017 return result;
2019 else
2020 return false;
2024 * get_rel_tablespace
2026 * Returns the pg_tablespace OID associated with a given relation.
2028 * Note: InvalidOid might mean either that we couldn't find the relation,
2029 * or that it is in the database's default tablespace.
2032 get_rel_tablespace(Oid relid)
2034 HeapTuple tp;
2036 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2037 if (HeapTupleIsValid(tp))
2039 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
2040 Oid result;
2042 result = reltup->reltablespace;
2043 ReleaseSysCache(tp);
2044 return result;
2046 else
2047 return InvalidOid;
2051 * get_rel_persistence
2053 * Returns the relpersistence associated with a given relation.
2055 char
2056 get_rel_persistence(Oid relid)
2058 HeapTuple tp;
2059 Form_pg_class reltup;
2060 char result;
2062 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2063 if (!HeapTupleIsValid(tp))
2064 elog(ERROR, "cache lookup failed for relation %u", relid);
2065 reltup = (Form_pg_class) GETSTRUCT(tp);
2066 result = reltup->relpersistence;
2067 ReleaseSysCache(tp);
2069 return result;
2073 * get_rel_relam
2075 * Returns the relam associated with a given relation.
2078 get_rel_relam(Oid relid)
2080 HeapTuple tp;
2081 Form_pg_class reltup;
2082 Oid result;
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->relam;
2089 ReleaseSysCache(tp);
2091 return result;
2095 /* ---------- TRANSFORM CACHE ---------- */
2098 get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2100 HeapTuple tup;
2102 if (!list_member_oid(trftypes, typid))
2103 return InvalidOid;
2105 tup = SearchSysCache2(TRFTYPELANG, ObjectIdGetDatum(typid),
2106 ObjectIdGetDatum(langid));
2107 if (HeapTupleIsValid(tup))
2109 Oid funcid;
2111 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2112 ReleaseSysCache(tup);
2113 return funcid;
2115 else
2116 return InvalidOid;
2120 get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2122 HeapTuple tup;
2124 if (!list_member_oid(trftypes, typid))
2125 return InvalidOid;
2127 tup = SearchSysCache2(TRFTYPELANG, ObjectIdGetDatum(typid),
2128 ObjectIdGetDatum(langid));
2129 if (HeapTupleIsValid(tup))
2131 Oid funcid;
2133 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2134 ReleaseSysCache(tup);
2135 return funcid;
2137 else
2138 return InvalidOid;
2142 /* ---------- TYPE CACHE ---------- */
2145 * get_typisdefined
2147 * Given the type OID, determine whether the type is defined
2148 * (if not, it's only a shell).
2150 bool
2151 get_typisdefined(Oid typid)
2153 HeapTuple tp;
2155 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2156 if (HeapTupleIsValid(tp))
2158 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2159 bool result;
2161 result = typtup->typisdefined;
2162 ReleaseSysCache(tp);
2163 return result;
2165 else
2166 return false;
2170 * get_typlen
2172 * Given the type OID, return the length of the type.
2174 int16
2175 get_typlen(Oid typid)
2177 HeapTuple tp;
2179 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2180 if (HeapTupleIsValid(tp))
2182 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2183 int16 result;
2185 result = typtup->typlen;
2186 ReleaseSysCache(tp);
2187 return result;
2189 else
2190 return 0;
2194 * get_typbyval
2196 * Given the type OID, determine whether the type is returned by value or
2197 * not. Returns true if by value, false if by reference.
2199 bool
2200 get_typbyval(Oid typid)
2202 HeapTuple tp;
2204 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2205 if (HeapTupleIsValid(tp))
2207 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2208 bool result;
2210 result = typtup->typbyval;
2211 ReleaseSysCache(tp);
2212 return result;
2214 else
2215 return false;
2219 * get_typlenbyval
2221 * A two-fer: given the type OID, return both typlen and typbyval.
2223 * Since both pieces of info are needed to know how to copy a Datum,
2224 * many places need both. Might as well get them with one cache lookup
2225 * instead of two. Also, this routine raises an error instead of
2226 * returning a bogus value when given a bad type OID.
2228 void
2229 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2231 HeapTuple tp;
2232 Form_pg_type typtup;
2234 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2235 if (!HeapTupleIsValid(tp))
2236 elog(ERROR, "cache lookup failed for type %u", typid);
2237 typtup = (Form_pg_type) GETSTRUCT(tp);
2238 *typlen = typtup->typlen;
2239 *typbyval = typtup->typbyval;
2240 ReleaseSysCache(tp);
2244 * get_typlenbyvalalign
2246 * A three-fer: given the type OID, return typlen, typbyval, typalign.
2248 void
2249 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2250 char *typalign)
2252 HeapTuple tp;
2253 Form_pg_type typtup;
2255 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2256 if (!HeapTupleIsValid(tp))
2257 elog(ERROR, "cache lookup failed for type %u", typid);
2258 typtup = (Form_pg_type) GETSTRUCT(tp);
2259 *typlen = typtup->typlen;
2260 *typbyval = typtup->typbyval;
2261 *typalign = typtup->typalign;
2262 ReleaseSysCache(tp);
2266 * getTypeIOParam
2267 * Given a pg_type row, select the type OID to pass to I/O functions
2269 * Formerly, all I/O functions were passed pg_type.typelem as their second
2270 * parameter, but we now have a more complex rule about what to pass.
2271 * This knowledge is intended to be centralized here --- direct references
2272 * to typelem elsewhere in the code are wrong, if they are associated with
2273 * I/O calls and not with actual subscripting operations! (But see
2274 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2276 * As of PostgreSQL 8.1, output functions receive only the value itself
2277 * and not any auxiliary parameters, so the name of this routine is now
2278 * a bit of a misnomer ... it should be getTypeInputParam.
2281 getTypeIOParam(HeapTuple typeTuple)
2283 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2286 * Array types get their typelem as parameter; everybody else gets their
2287 * own type OID as parameter.
2289 if (OidIsValid(typeStruct->typelem))
2290 return typeStruct->typelem;
2291 else
2292 return typeStruct->oid;
2296 * get_type_io_data
2298 * A six-fer: given the type OID, return typlen, typbyval, typalign,
2299 * typdelim, typioparam, and IO function OID. The IO function
2300 * returned is controlled by IOFuncSelector
2302 void
2303 get_type_io_data(Oid typid,
2304 IOFuncSelector which_func,
2305 int16 *typlen,
2306 bool *typbyval,
2307 char *typalign,
2308 char *typdelim,
2309 Oid *typioparam,
2310 Oid *func)
2312 HeapTuple typeTuple;
2313 Form_pg_type typeStruct;
2316 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2317 * use array_in and array_out during bootstrap.
2319 if (IsBootstrapProcessingMode())
2321 Oid typinput;
2322 Oid typoutput;
2324 boot_get_type_io_data(typid,
2325 typlen,
2326 typbyval,
2327 typalign,
2328 typdelim,
2329 typioparam,
2330 &typinput,
2331 &typoutput);
2332 switch (which_func)
2334 case IOFunc_input:
2335 *func = typinput;
2336 break;
2337 case IOFunc_output:
2338 *func = typoutput;
2339 break;
2340 default:
2341 elog(ERROR, "binary I/O not supported during bootstrap");
2342 break;
2344 return;
2347 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2348 if (!HeapTupleIsValid(typeTuple))
2349 elog(ERROR, "cache lookup failed for type %u", typid);
2350 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2352 *typlen = typeStruct->typlen;
2353 *typbyval = typeStruct->typbyval;
2354 *typalign = typeStruct->typalign;
2355 *typdelim = typeStruct->typdelim;
2356 *typioparam = getTypeIOParam(typeTuple);
2357 switch (which_func)
2359 case IOFunc_input:
2360 *func = typeStruct->typinput;
2361 break;
2362 case IOFunc_output:
2363 *func = typeStruct->typoutput;
2364 break;
2365 case IOFunc_receive:
2366 *func = typeStruct->typreceive;
2367 break;
2368 case IOFunc_send:
2369 *func = typeStruct->typsend;
2370 break;
2372 ReleaseSysCache(typeTuple);
2375 #ifdef NOT_USED
2376 char
2377 get_typalign(Oid typid)
2379 HeapTuple tp;
2381 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2382 if (HeapTupleIsValid(tp))
2384 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2385 char result;
2387 result = typtup->typalign;
2388 ReleaseSysCache(tp);
2389 return result;
2391 else
2392 return TYPALIGN_INT;
2394 #endif
2396 char
2397 get_typstorage(Oid typid)
2399 HeapTuple tp;
2401 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2402 if (HeapTupleIsValid(tp))
2404 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2405 char result;
2407 result = typtup->typstorage;
2408 ReleaseSysCache(tp);
2409 return result;
2411 else
2412 return TYPSTORAGE_PLAIN;
2416 * get_typdefault
2417 * Given a type OID, return the type's default value, if any.
2419 * The result is a palloc'd expression node tree, or NULL if there
2420 * is no defined default for the datatype.
2422 * NB: caller should be prepared to coerce result to correct datatype;
2423 * the returned expression tree might produce something of the wrong type.
2425 Node *
2426 get_typdefault(Oid typid)
2428 HeapTuple typeTuple;
2429 Form_pg_type type;
2430 Datum datum;
2431 bool isNull;
2432 Node *expr;
2434 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2435 if (!HeapTupleIsValid(typeTuple))
2436 elog(ERROR, "cache lookup failed for type %u", typid);
2437 type = (Form_pg_type) GETSTRUCT(typeTuple);
2440 * typdefault and typdefaultbin are potentially null, so don't try to
2441 * access 'em as struct fields. Must do it the hard way with
2442 * SysCacheGetAttr.
2444 datum = SysCacheGetAttr(TYPEOID,
2445 typeTuple,
2446 Anum_pg_type_typdefaultbin,
2447 &isNull);
2449 if (!isNull)
2451 /* We have an expression default */
2452 expr = stringToNode(TextDatumGetCString(datum));
2454 else
2456 /* Perhaps we have a plain literal default */
2457 datum = SysCacheGetAttr(TYPEOID,
2458 typeTuple,
2459 Anum_pg_type_typdefault,
2460 &isNull);
2462 if (!isNull)
2464 char *strDefaultVal;
2466 /* Convert text datum to C string */
2467 strDefaultVal = TextDatumGetCString(datum);
2468 /* Convert C string to a value of the given type */
2469 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2470 getTypeIOParam(typeTuple), -1);
2471 /* Build a Const node containing the value */
2472 expr = (Node *) makeConst(typid,
2474 type->typcollation,
2475 type->typlen,
2476 datum,
2477 false,
2478 type->typbyval);
2479 pfree(strDefaultVal);
2481 else
2483 /* No default */
2484 expr = NULL;
2488 ReleaseSysCache(typeTuple);
2490 return expr;
2494 * getBaseType
2495 * If the given type is a domain, return its base type;
2496 * otherwise return the type's own OID.
2499 getBaseType(Oid typid)
2501 int32 typmod = -1;
2503 return getBaseTypeAndTypmod(typid, &typmod);
2507 * getBaseTypeAndTypmod
2508 * If the given type is a domain, return its base type and typmod;
2509 * otherwise return the type's own OID, and leave *typmod unchanged.
2511 * Note that the "applied typmod" should be -1 for every domain level
2512 * above the bottommost; therefore, if the passed-in typid is indeed
2513 * a domain, *typmod should be -1.
2516 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2519 * We loop to find the bottom base type in a stack of domains.
2521 for (;;)
2523 HeapTuple tup;
2524 Form_pg_type typTup;
2526 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2527 if (!HeapTupleIsValid(tup))
2528 elog(ERROR, "cache lookup failed for type %u", typid);
2529 typTup = (Form_pg_type) GETSTRUCT(tup);
2530 if (typTup->typtype != TYPTYPE_DOMAIN)
2532 /* Not a domain, so done */
2533 ReleaseSysCache(tup);
2534 break;
2537 Assert(*typmod == -1);
2538 typid = typTup->typbasetype;
2539 *typmod = typTup->typtypmod;
2541 ReleaseSysCache(tup);
2544 return typid;
2548 * get_typavgwidth
2550 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2551 * estimate the average width of values of the type. This is used by
2552 * the planner, which doesn't require absolutely correct results;
2553 * it's OK (and expected) to guess if we don't know for sure.
2555 int32
2556 get_typavgwidth(Oid typid, int32 typmod)
2558 int typlen = get_typlen(typid);
2559 int32 maxwidth;
2562 * Easy if it's a fixed-width type
2564 if (typlen > 0)
2565 return typlen;
2568 * type_maximum_size knows the encoding of typmod for some datatypes;
2569 * don't duplicate that knowledge here.
2571 maxwidth = type_maximum_size(typid, typmod);
2572 if (maxwidth > 0)
2575 * For BPCHAR, the max width is also the only width. Otherwise we
2576 * need to guess about the typical data width given the max. A sliding
2577 * scale for percentage of max width seems reasonable.
2579 if (typid == BPCHAROID)
2580 return maxwidth;
2581 if (maxwidth <= 32)
2582 return maxwidth; /* assume full width */
2583 if (maxwidth < 1000)
2584 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2587 * Beyond 1000, assume we're looking at something like
2588 * "varchar(10000)" where the limit isn't actually reached often, and
2589 * use a fixed estimate.
2591 return 32 + (1000 - 32) / 2;
2595 * Oops, we have no idea ... wild guess time.
2597 return 32;
2601 * get_typtype
2603 * Given the type OID, find if it is a basic type, a complex type, etc.
2604 * It returns the null char if the cache lookup fails...
2606 char
2607 get_typtype(Oid typid)
2609 HeapTuple tp;
2611 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2612 if (HeapTupleIsValid(tp))
2614 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2615 char result;
2617 result = typtup->typtype;
2618 ReleaseSysCache(tp);
2619 return result;
2621 else
2622 return '\0';
2626 * type_is_rowtype
2628 * Convenience function to determine whether a type OID represents
2629 * a "rowtype" type --- either RECORD or a named composite type
2630 * (including a domain over a named composite type).
2632 bool
2633 type_is_rowtype(Oid typid)
2635 if (typid == RECORDOID)
2636 return true; /* easy case */
2637 switch (get_typtype(typid))
2639 case TYPTYPE_COMPOSITE:
2640 return true;
2641 case TYPTYPE_DOMAIN:
2642 if (get_typtype(getBaseType(typid)) == TYPTYPE_COMPOSITE)
2643 return true;
2644 break;
2645 default:
2646 break;
2648 return false;
2652 * type_is_enum
2653 * Returns true if the given type is an enum type.
2655 bool
2656 type_is_enum(Oid typid)
2658 return (get_typtype(typid) == TYPTYPE_ENUM);
2662 * type_is_range
2663 * Returns true if the given type is a range type.
2665 bool
2666 type_is_range(Oid typid)
2668 return (get_typtype(typid) == TYPTYPE_RANGE);
2672 * type_is_multirange
2673 * Returns true if the given type is a multirange type.
2675 bool
2676 type_is_multirange(Oid typid)
2678 return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
2682 * get_type_category_preferred
2684 * Given the type OID, fetch its category and preferred-type status.
2685 * Throws error on failure.
2687 void
2688 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2690 HeapTuple tp;
2691 Form_pg_type typtup;
2693 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2694 if (!HeapTupleIsValid(tp))
2695 elog(ERROR, "cache lookup failed for type %u", typid);
2696 typtup = (Form_pg_type) GETSTRUCT(tp);
2697 *typcategory = typtup->typcategory;
2698 *typispreferred = typtup->typispreferred;
2699 ReleaseSysCache(tp);
2703 * get_typ_typrelid
2705 * Given the type OID, get the typrelid (InvalidOid if not a complex
2706 * type).
2709 get_typ_typrelid(Oid typid)
2711 HeapTuple tp;
2713 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2714 if (HeapTupleIsValid(tp))
2716 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2717 Oid result;
2719 result = typtup->typrelid;
2720 ReleaseSysCache(tp);
2721 return result;
2723 else
2724 return InvalidOid;
2728 * get_element_type
2730 * Given the type OID, get the typelem (InvalidOid if not an array type).
2732 * NB: this only succeeds for "true" arrays having array_subscript_handler
2733 * as typsubscript. For other types, InvalidOid is returned independently
2734 * of whether they have typelem or typsubscript set.
2737 get_element_type(Oid typid)
2739 HeapTuple tp;
2741 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2742 if (HeapTupleIsValid(tp))
2744 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2745 Oid result;
2747 if (IsTrueArrayType(typtup))
2748 result = typtup->typelem;
2749 else
2750 result = InvalidOid;
2751 ReleaseSysCache(tp);
2752 return result;
2754 else
2755 return InvalidOid;
2759 * get_array_type
2761 * Given the type OID, get the corresponding "true" array type.
2762 * Returns InvalidOid if no array type can be found.
2765 get_array_type(Oid typid)
2767 HeapTuple tp;
2768 Oid result = InvalidOid;
2770 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2771 if (HeapTupleIsValid(tp))
2773 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2774 ReleaseSysCache(tp);
2776 return result;
2780 * get_promoted_array_type
2782 * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
2783 * construct, that is, either the corresponding "true" array type
2784 * if the input is a scalar type that has such an array type,
2785 * or the same type if the input is already a "true" array type.
2786 * Returns InvalidOid if neither rule is satisfied.
2789 get_promoted_array_type(Oid typid)
2791 Oid array_type = get_array_type(typid);
2793 if (OidIsValid(array_type))
2794 return array_type;
2795 if (OidIsValid(get_element_type(typid)))
2796 return typid;
2797 return InvalidOid;
2801 * get_base_element_type
2802 * Given the type OID, get the typelem, looking "through" any domain
2803 * to its underlying array type.
2805 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2806 * an extra cache lookup. Note that it fails to provide any information
2807 * about the typmod of the array.
2810 get_base_element_type(Oid typid)
2813 * We loop to find the bottom base type in a stack of domains.
2815 for (;;)
2817 HeapTuple tup;
2818 Form_pg_type typTup;
2820 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2821 if (!HeapTupleIsValid(tup))
2822 break;
2823 typTup = (Form_pg_type) GETSTRUCT(tup);
2824 if (typTup->typtype != TYPTYPE_DOMAIN)
2826 /* Not a domain, so stop descending */
2827 Oid result;
2829 /* This test must match get_element_type */
2830 if (IsTrueArrayType(typTup))
2831 result = typTup->typelem;
2832 else
2833 result = InvalidOid;
2834 ReleaseSysCache(tup);
2835 return result;
2838 typid = typTup->typbasetype;
2839 ReleaseSysCache(tup);
2842 /* Like get_element_type, silently return InvalidOid for bogus input */
2843 return InvalidOid;
2847 * getTypeInputInfo
2849 * Get info needed for converting values of a type to internal form
2851 void
2852 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2854 HeapTuple typeTuple;
2855 Form_pg_type pt;
2857 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2858 if (!HeapTupleIsValid(typeTuple))
2859 elog(ERROR, "cache lookup failed for type %u", type);
2860 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2862 if (!pt->typisdefined)
2863 ereport(ERROR,
2864 (errcode(ERRCODE_UNDEFINED_OBJECT),
2865 errmsg("type %s is only a shell",
2866 format_type_be(type))));
2867 if (!OidIsValid(pt->typinput))
2868 ereport(ERROR,
2869 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2870 errmsg("no input function available for type %s",
2871 format_type_be(type))));
2873 *typInput = pt->typinput;
2874 *typIOParam = getTypeIOParam(typeTuple);
2876 ReleaseSysCache(typeTuple);
2880 * getTypeOutputInfo
2882 * Get info needed for printing values of a type
2884 void
2885 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2887 HeapTuple typeTuple;
2888 Form_pg_type pt;
2890 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2891 if (!HeapTupleIsValid(typeTuple))
2892 elog(ERROR, "cache lookup failed for type %u", type);
2893 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2895 if (!pt->typisdefined)
2896 ereport(ERROR,
2897 (errcode(ERRCODE_UNDEFINED_OBJECT),
2898 errmsg("type %s is only a shell",
2899 format_type_be(type))));
2900 if (!OidIsValid(pt->typoutput))
2901 ereport(ERROR,
2902 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2903 errmsg("no output function available for type %s",
2904 format_type_be(type))));
2906 *typOutput = pt->typoutput;
2907 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2909 ReleaseSysCache(typeTuple);
2913 * getTypeBinaryInputInfo
2915 * Get info needed for binary input of values of a type
2917 void
2918 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2920 HeapTuple typeTuple;
2921 Form_pg_type pt;
2923 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2924 if (!HeapTupleIsValid(typeTuple))
2925 elog(ERROR, "cache lookup failed for type %u", type);
2926 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2928 if (!pt->typisdefined)
2929 ereport(ERROR,
2930 (errcode(ERRCODE_UNDEFINED_OBJECT),
2931 errmsg("type %s is only a shell",
2932 format_type_be(type))));
2933 if (!OidIsValid(pt->typreceive))
2934 ereport(ERROR,
2935 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2936 errmsg("no binary input function available for type %s",
2937 format_type_be(type))));
2939 *typReceive = pt->typreceive;
2940 *typIOParam = getTypeIOParam(typeTuple);
2942 ReleaseSysCache(typeTuple);
2946 * getTypeBinaryOutputInfo
2948 * Get info needed for binary output of values of a type
2950 void
2951 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2953 HeapTuple typeTuple;
2954 Form_pg_type pt;
2956 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2957 if (!HeapTupleIsValid(typeTuple))
2958 elog(ERROR, "cache lookup failed for type %u", type);
2959 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2961 if (!pt->typisdefined)
2962 ereport(ERROR,
2963 (errcode(ERRCODE_UNDEFINED_OBJECT),
2964 errmsg("type %s is only a shell",
2965 format_type_be(type))));
2966 if (!OidIsValid(pt->typsend))
2967 ereport(ERROR,
2968 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2969 errmsg("no binary output function available for type %s",
2970 format_type_be(type))));
2972 *typSend = pt->typsend;
2973 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2975 ReleaseSysCache(typeTuple);
2979 * get_typmodin
2981 * Given the type OID, return the type's typmodin procedure, if any.
2984 get_typmodin(Oid typid)
2986 HeapTuple tp;
2988 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2989 if (HeapTupleIsValid(tp))
2991 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2992 Oid result;
2994 result = typtup->typmodin;
2995 ReleaseSysCache(tp);
2996 return result;
2998 else
2999 return InvalidOid;
3002 #ifdef NOT_USED
3004 * get_typmodout
3006 * Given the type OID, return the type's typmodout procedure, if any.
3009 get_typmodout(Oid typid)
3011 HeapTuple tp;
3013 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3014 if (HeapTupleIsValid(tp))
3016 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
3017 Oid result;
3019 result = typtup->typmodout;
3020 ReleaseSysCache(tp);
3021 return result;
3023 else
3024 return InvalidOid;
3026 #endif /* NOT_USED */
3029 * get_typcollation
3031 * Given the type OID, return the type's typcollation attribute.
3034 get_typcollation(Oid typid)
3036 HeapTuple tp;
3038 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3039 if (HeapTupleIsValid(tp))
3041 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
3042 Oid result;
3044 result = typtup->typcollation;
3045 ReleaseSysCache(tp);
3046 return result;
3048 else
3049 return InvalidOid;
3054 * type_is_collatable
3056 * Return whether the type cares about collations
3058 bool
3059 type_is_collatable(Oid typid)
3061 return OidIsValid(get_typcollation(typid));
3066 * get_typsubscript
3068 * Given the type OID, return the type's subscripting handler's OID,
3069 * if it has one.
3071 * If typelemp isn't NULL, we also store the type's typelem value there.
3072 * This saves some callers an extra catalog lookup.
3074 RegProcedure
3075 get_typsubscript(Oid typid, Oid *typelemp)
3077 HeapTuple tp;
3079 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3080 if (HeapTupleIsValid(tp))
3082 Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
3083 RegProcedure handler = typform->typsubscript;
3085 if (typelemp)
3086 *typelemp = typform->typelem;
3087 ReleaseSysCache(tp);
3088 return handler;
3090 else
3092 if (typelemp)
3093 *typelemp = InvalidOid;
3094 return InvalidOid;
3099 * getSubscriptingRoutines
3101 * Given the type OID, fetch the type's subscripting methods struct.
3102 * Return NULL if type is not subscriptable.
3104 * If typelemp isn't NULL, we also store the type's typelem value there.
3105 * This saves some callers an extra catalog lookup.
3107 const struct SubscriptRoutines *
3108 getSubscriptingRoutines(Oid typid, Oid *typelemp)
3110 RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3112 if (!OidIsValid(typsubscript))
3113 return NULL;
3115 return (const struct SubscriptRoutines *)
3116 DatumGetPointer(OidFunctionCall0(typsubscript));
3120 /* ---------- STATISTICS CACHE ---------- */
3123 * get_attavgwidth
3125 * Given the table and attribute number of a column, get the average
3126 * width of entries in the column. Return zero if no data available.
3128 * Currently this is only consulted for individual tables, not for inheritance
3129 * trees, so we don't need an "inh" parameter.
3131 * Calling a hook at this point looks somewhat strange, but is required
3132 * because the optimizer calls this function without any other way for
3133 * plug-ins to control the result.
3135 int32
3136 get_attavgwidth(Oid relid, AttrNumber attnum)
3138 HeapTuple tp;
3139 int32 stawidth;
3141 if (get_attavgwidth_hook)
3143 stawidth = (*get_attavgwidth_hook) (relid, attnum);
3144 if (stawidth > 0)
3145 return stawidth;
3147 tp = SearchSysCache3(STATRELATTINH,
3148 ObjectIdGetDatum(relid),
3149 Int16GetDatum(attnum),
3150 BoolGetDatum(false));
3151 if (HeapTupleIsValid(tp))
3153 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3154 ReleaseSysCache(tp);
3155 if (stawidth > 0)
3156 return stawidth;
3158 return 0;
3162 * get_attstatsslot
3164 * Extract the contents of a "slot" of a pg_statistic tuple.
3165 * Returns true if requested slot type was found, else false.
3167 * Unlike other routines in this file, this takes a pointer to an
3168 * already-looked-up tuple in the pg_statistic cache. We do this since
3169 * most callers will want to extract more than one value from the cache
3170 * entry, and we don't want to repeat the cache lookup unnecessarily.
3171 * Also, this API allows this routine to be used with statistics tuples
3172 * that have been provided by a stats hook and didn't really come from
3173 * pg_statistic.
3175 * sslot: pointer to output area (typically, a local variable in the caller).
3176 * statstuple: pg_statistic tuple to be examined.
3177 * reqkind: STAKIND code for desired statistics slot kind.
3178 * reqop: STAOP value wanted, or InvalidOid if don't care.
3179 * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3181 * If a matching slot is found, true is returned, and *sslot is filled thus:
3182 * staop: receives the actual STAOP value.
3183 * stacoll: receives the actual STACOLL value.
3184 * valuetype: receives actual datatype of the elements of stavalues.
3185 * values: receives pointer to an array of the slot's stavalues.
3186 * nvalues: receives number of stavalues.
3187 * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3188 * nnumbers: receives number of stanumbers.
3190 * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3191 * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3192 * ATTSTATSSLOT_NUMBERS wasn't specified.
3194 * If no matching slot is found, false is returned, and *sslot is zeroed.
3196 * Note that the current API doesn't allow for searching for a slot with
3197 * a particular collation. If we ever actually support recording more than
3198 * one collation, we'll have to extend the API, but for now simple is good.
3200 * The data referred to by the fields of sslot is locally palloc'd and
3201 * is independent of the original pg_statistic tuple. When the caller
3202 * is done with it, call free_attstatsslot to release the palloc'd data.
3204 * If it's desirable to call free_attstatsslot when get_attstatsslot might
3205 * not have been called, memset'ing sslot to zeroes will allow that.
3207 * Passing flags=0 can be useful to quickly check if the requested slot type
3208 * exists. In this case no arrays are extracted, so free_attstatsslot need
3209 * not be called.
3211 bool
3212 get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
3213 int reqkind, Oid reqop, int flags)
3215 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
3216 int i;
3217 Datum val;
3218 ArrayType *statarray;
3219 Oid arrayelemtype;
3220 int narrayelem;
3221 HeapTuple typeTuple;
3222 Form_pg_type typeForm;
3224 /* initialize *sslot properly */
3225 memset(sslot, 0, sizeof(AttStatsSlot));
3227 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3229 if ((&stats->stakind1)[i] == reqkind &&
3230 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3231 break;
3233 if (i >= STATISTIC_NUM_SLOTS)
3234 return false; /* not there */
3236 sslot->staop = (&stats->staop1)[i];
3237 sslot->stacoll = (&stats->stacoll1)[i];
3239 if (flags & ATTSTATSSLOT_VALUES)
3241 val = SysCacheGetAttrNotNull(STATRELATTINH, statstuple,
3242 Anum_pg_statistic_stavalues1 + i);
3245 * Detoast the array if needed, and in any case make a copy that's
3246 * under control of this AttStatsSlot.
3248 statarray = DatumGetArrayTypePCopy(val);
3251 * Extract the actual array element type, and pass it back in case the
3252 * caller needs it.
3254 sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3256 /* Need info about element type */
3257 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
3258 if (!HeapTupleIsValid(typeTuple))
3259 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3260 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
3262 /* Deconstruct array into Datum elements; NULLs not expected */
3263 deconstruct_array(statarray,
3264 arrayelemtype,
3265 typeForm->typlen,
3266 typeForm->typbyval,
3267 typeForm->typalign,
3268 &sslot->values, NULL, &sslot->nvalues);
3271 * If the element type is pass-by-reference, we now have a bunch of
3272 * Datums that are pointers into the statarray, so we need to keep
3273 * that until free_attstatsslot. Otherwise, all the useful info is in
3274 * sslot->values[], so we can free the array object immediately.
3276 if (!typeForm->typbyval)
3277 sslot->values_arr = statarray;
3278 else
3279 pfree(statarray);
3281 ReleaseSysCache(typeTuple);
3284 if (flags & ATTSTATSSLOT_NUMBERS)
3286 val = SysCacheGetAttrNotNull(STATRELATTINH, statstuple,
3287 Anum_pg_statistic_stanumbers1 + i);
3290 * Detoast the array if needed, and in any case make a copy that's
3291 * under control of this AttStatsSlot.
3293 statarray = DatumGetArrayTypePCopy(val);
3296 * We expect the array to be a 1-D float4 array; verify that. We don't
3297 * need to use deconstruct_array() since the array data is just going
3298 * to look like a C array of float4 values.
3300 narrayelem = ARR_DIMS(statarray)[0];
3301 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3302 ARR_HASNULL(statarray) ||
3303 ARR_ELEMTYPE(statarray) != FLOAT4OID)
3304 elog(ERROR, "stanumbers is not a 1-D float4 array");
3306 /* Give caller a pointer directly into the statarray */
3307 sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3308 sslot->nnumbers = narrayelem;
3310 /* We'll free the statarray in free_attstatsslot */
3311 sslot->numbers_arr = statarray;
3314 return true;
3318 * free_attstatsslot
3319 * Free data allocated by get_attstatsslot
3321 void
3322 free_attstatsslot(AttStatsSlot *sslot)
3324 /* The values[] array was separately palloc'd by deconstruct_array */
3325 if (sslot->values)
3326 pfree(sslot->values);
3327 /* The numbers[] array points into numbers_arr, do not pfree it */
3328 /* Free the detoasted array objects, if any */
3329 if (sslot->values_arr)
3330 pfree(sslot->values_arr);
3331 if (sslot->numbers_arr)
3332 pfree(sslot->numbers_arr);
3335 /* ---------- PG_NAMESPACE CACHE ---------- */
3338 * get_namespace_name
3339 * Returns the name of a given namespace
3341 * Returns a palloc'd copy of the string, or NULL if no such namespace.
3343 char *
3344 get_namespace_name(Oid nspid)
3346 HeapTuple tp;
3348 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
3349 if (HeapTupleIsValid(tp))
3351 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
3352 char *result;
3354 result = pstrdup(NameStr(nsptup->nspname));
3355 ReleaseSysCache(tp);
3356 return result;
3358 else
3359 return NULL;
3363 * get_namespace_name_or_temp
3364 * As above, but if it is this backend's temporary namespace, return
3365 * "pg_temp" instead.
3367 char *
3368 get_namespace_name_or_temp(Oid nspid)
3370 if (isTempNamespace(nspid))
3371 return pstrdup("pg_temp");
3372 else
3373 return get_namespace_name(nspid);
3376 /* ---------- PG_RANGE CACHES ---------- */
3379 * get_range_subtype
3380 * Returns the subtype of a given range type
3382 * Returns InvalidOid if the type is not a range type.
3385 get_range_subtype(Oid rangeOid)
3387 HeapTuple tp;
3389 tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3390 if (HeapTupleIsValid(tp))
3392 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3393 Oid result;
3395 result = rngtup->rngsubtype;
3396 ReleaseSysCache(tp);
3397 return result;
3399 else
3400 return InvalidOid;
3404 * get_range_collation
3405 * Returns the collation of a given range type
3407 * Returns InvalidOid if the type is not a range type,
3408 * or if its subtype is not collatable.
3411 get_range_collation(Oid rangeOid)
3413 HeapTuple tp;
3415 tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3416 if (HeapTupleIsValid(tp))
3418 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3419 Oid result;
3421 result = rngtup->rngcollation;
3422 ReleaseSysCache(tp);
3423 return result;
3425 else
3426 return InvalidOid;
3430 * get_range_multirange
3431 * Returns the multirange type of a given range type
3433 * Returns InvalidOid if the type is not a range type.
3436 get_range_multirange(Oid rangeOid)
3438 HeapTuple tp;
3440 tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3441 if (HeapTupleIsValid(tp))
3443 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3444 Oid result;
3446 result = rngtup->rngmultitypid;
3447 ReleaseSysCache(tp);
3448 return result;
3450 else
3451 return InvalidOid;
3455 * get_multirange_range
3456 * Returns the range type of a given multirange
3458 * Returns InvalidOid if the type is not a multirange.
3461 get_multirange_range(Oid multirangeOid)
3463 HeapTuple tp;
3465 tp = SearchSysCache1(RANGEMULTIRANGE, ObjectIdGetDatum(multirangeOid));
3466 if (HeapTupleIsValid(tp))
3468 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3469 Oid result;
3471 result = rngtup->rngtypid;
3472 ReleaseSysCache(tp);
3473 return result;
3475 else
3476 return InvalidOid;
3479 /* ---------- PG_INDEX CACHE ---------- */
3482 * get_index_column_opclass
3484 * Given the index OID and column number,
3485 * return opclass of the index column
3486 * or InvalidOid if the index was not found
3487 * or column is non-key one.
3490 get_index_column_opclass(Oid index_oid, int attno)
3492 HeapTuple tuple;
3493 Form_pg_index rd_index;
3494 Datum datum;
3495 oidvector *indclass;
3496 Oid opclass;
3498 /* First we need to know the column's opclass. */
3500 tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3501 if (!HeapTupleIsValid(tuple))
3502 return InvalidOid;
3504 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3506 /* caller is supposed to guarantee this */
3507 Assert(attno > 0 && attno <= rd_index->indnatts);
3509 /* Non-key attributes don't have an opclass */
3510 if (attno > rd_index->indnkeyatts)
3512 ReleaseSysCache(tuple);
3513 return InvalidOid;
3516 datum = SysCacheGetAttrNotNull(INDEXRELID, tuple, Anum_pg_index_indclass);
3517 indclass = ((oidvector *) DatumGetPointer(datum));
3519 Assert(attno <= indclass->dim1);
3520 opclass = indclass->values[attno - 1];
3522 ReleaseSysCache(tuple);
3524 return opclass;
3528 * get_index_isreplident
3530 * Given the index OID, return pg_index.indisreplident.
3532 bool
3533 get_index_isreplident(Oid index_oid)
3535 HeapTuple tuple;
3536 Form_pg_index rd_index;
3537 bool result;
3539 tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3540 if (!HeapTupleIsValid(tuple))
3541 return false;
3543 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3544 result = rd_index->indisreplident;
3545 ReleaseSysCache(tuple);
3547 return result;
3551 * get_index_isvalid
3553 * Given the index OID, return pg_index.indisvalid.
3555 bool
3556 get_index_isvalid(Oid index_oid)
3558 bool isvalid;
3559 HeapTuple tuple;
3560 Form_pg_index rd_index;
3562 tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3563 if (!HeapTupleIsValid(tuple))
3564 elog(ERROR, "cache lookup failed for index %u", index_oid);
3566 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3567 isvalid = rd_index->indisvalid;
3568 ReleaseSysCache(tuple);
3570 return isvalid;
3574 * get_index_isclustered
3576 * Given the index OID, return pg_index.indisclustered.
3578 bool
3579 get_index_isclustered(Oid index_oid)
3581 bool isclustered;
3582 HeapTuple tuple;
3583 Form_pg_index rd_index;
3585 tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3586 if (!HeapTupleIsValid(tuple))
3587 elog(ERROR, "cache lookup failed for index %u", index_oid);
3589 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3590 isclustered = rd_index->indisclustered;
3591 ReleaseSysCache(tuple);
3593 return isclustered;
3597 * get_publication_oid - given a publication name, look up the OID
3599 * If missing_ok is false, throw an error if name not found. If true, just
3600 * return InvalidOid.
3603 get_publication_oid(const char *pubname, bool missing_ok)
3605 Oid oid;
3607 oid = GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
3608 CStringGetDatum(pubname));
3609 if (!OidIsValid(oid) && !missing_ok)
3610 ereport(ERROR,
3611 (errcode(ERRCODE_UNDEFINED_OBJECT),
3612 errmsg("publication \"%s\" does not exist", pubname)));
3613 return oid;
3617 * get_publication_name - given a publication Oid, look up the name
3619 * If missing_ok is false, throw an error if name not found. If true, just
3620 * return NULL.
3622 char *
3623 get_publication_name(Oid pubid, bool missing_ok)
3625 HeapTuple tup;
3626 char *pubname;
3627 Form_pg_publication pubform;
3629 tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
3631 if (!HeapTupleIsValid(tup))
3633 if (!missing_ok)
3634 elog(ERROR, "cache lookup failed for publication %u", pubid);
3635 return NULL;
3638 pubform = (Form_pg_publication) GETSTRUCT(tup);
3639 pubname = pstrdup(NameStr(pubform->pubname));
3641 ReleaseSysCache(tup);
3643 return pubname;
3647 * get_subscription_oid - given a subscription name, look up the OID
3649 * If missing_ok is false, throw an error if name not found. If true, just
3650 * return InvalidOid.
3653 get_subscription_oid(const char *subname, bool missing_ok)
3655 Oid oid;
3657 oid = GetSysCacheOid2(SUBSCRIPTIONNAME, Anum_pg_subscription_oid,
3658 MyDatabaseId, CStringGetDatum(subname));
3659 if (!OidIsValid(oid) && !missing_ok)
3660 ereport(ERROR,
3661 (errcode(ERRCODE_UNDEFINED_OBJECT),
3662 errmsg("subscription \"%s\" does not exist", subname)));
3663 return oid;
3667 * get_subscription_name - given a subscription OID, look up the name
3669 * If missing_ok is false, throw an error if name not found. If true, just
3670 * return NULL.
3672 char *
3673 get_subscription_name(Oid subid, bool missing_ok)
3675 HeapTuple tup;
3676 char *subname;
3677 Form_pg_subscription subform;
3679 tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
3681 if (!HeapTupleIsValid(tup))
3683 if (!missing_ok)
3684 elog(ERROR, "cache lookup failed for subscription %u", subid);
3685 return NULL;
3688 subform = (Form_pg_subscription) GETSTRUCT(tup);
3689 subname = pstrdup(NameStr(subform->subname));
3691 ReleaseSysCache(tup);
3693 return subname;