PostgreSQL Source Code git master
Loading...
Searching...
No Matches
lsyscache.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * lsyscache.c
4 * Convenience routines for common queries in the system catalog cache.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * IDENTIFICATION
10 * src/backend/utils/cache/lsyscache.c
11 *
12 * NOTES
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
15 */
16#include "postgres.h"
17
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"
29#include "catalog/pg_database.h"
30#include "catalog/pg_index.h"
31#include "catalog/pg_language.h"
33#include "catalog/pg_opclass.h"
34#include "catalog/pg_opfamily.h"
35#include "catalog/pg_operator.h"
36#include "catalog/pg_proc.h"
40#include "catalog/pg_range.h"
44#include "catalog/pg_type.h"
45#include "miscadmin.h"
46#include "nodes/makefuncs.h"
47#include "utils/array.h"
48#include "utils/builtins.h"
49#include "utils/catcache.h"
50#include "utils/datum.h"
51#include "utils/fmgroids.h"
52#include "utils/lsyscache.h"
53#include "utils/syscache.h"
54#include "utils/typcache.h"
55
56/* Hook for plugins to get control in get_attavgwidth() */
58
59
60/* ---------- AMOP CACHES ---------- */
61
62/*
63 * op_in_opfamily
64 *
65 * Return t iff operator 'opno' is in operator family 'opfamily'.
66 *
67 * This function only considers search operators, not ordering operators.
68 */
69bool
70op_in_opfamily(Oid opno, Oid opfamily)
71{
73 ObjectIdGetDatum(opno),
75 ObjectIdGetDatum(opfamily));
76}
77
78/*
79 * get_op_opfamily_strategy
80 *
81 * Get the operator's strategy number within the specified opfamily,
82 * or 0 if it's not a member of the opfamily.
83 *
84 * This function only considers search operators, not ordering operators.
85 */
86int
88{
89 HeapTuple tp;
91 int result;
92
94 ObjectIdGetDatum(opno),
96 ObjectIdGetDatum(opfamily));
97 if (!HeapTupleIsValid(tp))
98 return 0;
100 result = amop_tup->amopstrategy;
101 ReleaseSysCache(tp);
102 return result;
103}
104
105/*
106 * get_op_opfamily_sortfamily
107 *
108 * If the operator is an ordering operator within the specified opfamily,
109 * return its amopsortfamily OID; else return InvalidOid.
110 */
111Oid
113{
114 HeapTuple tp;
116 Oid result;
117
119 ObjectIdGetDatum(opno),
121 ObjectIdGetDatum(opfamily));
122 if (!HeapTupleIsValid(tp))
123 return InvalidOid;
125 result = amop_tup->amopsortfamily;
126 ReleaseSysCache(tp);
127 return result;
128}
129
130/*
131 * get_op_opfamily_properties
132 *
133 * Get the operator's strategy number and declared input data types
134 * within the specified opfamily.
135 *
136 * Caller should already have verified that opno is a member of opfamily,
137 * therefore we raise an error if the tuple is not found.
138 */
139void
141 int *strategy,
142 Oid *lefttype,
143 Oid *righttype)
144{
145 HeapTuple tp;
147
149 ObjectIdGetDatum(opno),
151 ObjectIdGetDatum(opfamily));
152 if (!HeapTupleIsValid(tp))
153 elog(ERROR, "operator %u is not a member of opfamily %u",
154 opno, opfamily);
156 *strategy = amop_tup->amopstrategy;
157 *lefttype = amop_tup->amoplefttype;
158 *righttype = amop_tup->amoprighttype;
159 ReleaseSysCache(tp);
160}
161
162/*
163 * get_opfamily_member
164 * Get the OID of the operator that implements the specified strategy
165 * with the specified datatypes for the specified opfamily.
166 *
167 * Returns InvalidOid if there is no pg_amop entry for the given keys.
168 */
169Oid
170get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
171 int16 strategy)
172{
173 HeapTuple tp;
175 Oid result;
176
178 ObjectIdGetDatum(opfamily),
179 ObjectIdGetDatum(lefttype),
180 ObjectIdGetDatum(righttype),
181 Int16GetDatum(strategy));
182 if (!HeapTupleIsValid(tp))
183 return InvalidOid;
185 result = amop_tup->amopopr;
186 ReleaseSysCache(tp);
187 return result;
188}
189
190/*
191 * get_opfamily_member_for_cmptype
192 * Get the OID of the operator that implements the specified comparison
193 * type with the specified datatypes for the specified opfamily.
194 *
195 * Returns InvalidOid if there is no mapping for the comparison type or no
196 * pg_amop entry for the given keys.
197 */
198Oid
199get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype,
200 CompareType cmptype)
201{
203 StrategyNumber strategy;
204
205 opmethod = get_opfamily_method(opfamily);
206 strategy = IndexAmTranslateCompareType(cmptype, opmethod, opfamily, true);
207 if (!strategy)
208 return InvalidOid;
209 return get_opfamily_member(opfamily, lefttype, righttype, strategy);
210}
211
212/*
213 * get_opmethod_canorder
214 * Return amcanorder field for given index AM.
215 *
216 * To speed things up in the common cases, we're hardcoding the results from
217 * the built-in index types. Note that we also need to hardcode the negative
218 * results from the built-in non-btree index types, since you'll usually get a
219 * few hits for those as well. It would be nice to organize and cache this a
220 * bit differently to avoid the hardcoding.
221 */
222static bool
224{
225 switch (amoid)
226 {
227 case BTREE_AM_OID:
228 return true;
229 case HASH_AM_OID:
230 case GIST_AM_OID:
231 case GIN_AM_OID:
232 case SPGIST_AM_OID:
233 case BRIN_AM_OID:
234 return false;
235 default:
237 }
238}
239
240/*
241 * get_ordering_op_properties
242 * Given the OID of an ordering operator (a "<" or ">" operator),
243 * determine its opfamily, its declared input datatype, and its
244 * comparison type.
245 *
246 * Returns true if successful, false if no matching pg_amop entry exists.
247 * (This indicates that the operator is not a valid ordering operator.)
248 *
249 * Note: the operator could be registered in multiple families, for example
250 * if someone were to build a "reverse sort" opfamily. This would result in
251 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
252 * or NULLS LAST, as well as inefficient planning due to failure to match up
253 * pathkeys that should be the same. So we want a determinate result here.
254 * Because of the way the syscache search works, we'll use the interpretation
255 * associated with the opfamily with smallest OID, which is probably
256 * determinate enough. Since there is no longer any particularly good reason
257 * to build reverse-sort opfamilies, it doesn't seem worth expending any
258 * additional effort on ensuring consistency.
259 */
260bool
262 Oid *opfamily, Oid *opcintype, CompareType *cmptype)
263{
264 bool result = false;
266 int i;
267
268 /* ensure outputs are initialized on failure */
269 *opfamily = InvalidOid;
270 *opcintype = InvalidOid;
271 *cmptype = COMPARE_INVALID;
272
273 /*
274 * Search pg_amop to see if the target operator is registered as the "<"
275 * or ">" operator of any btree opfamily.
276 */
278
279 for (i = 0; i < catlist->n_members; i++)
280 {
281 HeapTuple tuple = &catlist->members[i]->tuple;
284
285 /* must be ordering index */
286 if (!get_opmethod_canorder(aform->amopmethod))
287 continue;
288
290 aform->amopmethod,
291 aform->amopfamily,
292 true);
293
295 {
296 /* Found it ... should have consistent input types */
297 if (aform->amoplefttype == aform->amoprighttype)
298 {
299 /* Found a suitable opfamily, return info */
300 *opfamily = aform->amopfamily;
301 *opcintype = aform->amoplefttype;
302 *cmptype = am_cmptype;
303 result = true;
304 break;
305 }
306 }
307 }
308
310
311 return result;
312}
313
314/*
315 * get_equality_op_for_ordering_op
316 * Get the OID of the datatype-specific equality operator
317 * associated with an ordering operator (a "<" or ">" operator).
318 *
319 * If "reverse" isn't NULL, also set *reverse to false if the operator is "<",
320 * true if it's ">"
321 *
322 * Returns InvalidOid if no matching equality operator can be found.
323 * (This indicates that the operator is not a valid ordering operator.)
324 */
325Oid
327{
329 Oid opfamily;
330 Oid opcintype;
331 CompareType cmptype;
332
333 /* Find the operator in pg_amop */
335 &opfamily, &opcintype, &cmptype))
336 {
337 /* Found a suitable opfamily, get matching equality operator */
339 opcintype,
340 opcintype,
341 COMPARE_EQ);
342 if (reverse)
343 *reverse = (cmptype == COMPARE_GT);
344 }
345
346 return result;
347}
348
349/*
350 * get_ordering_op_for_equality_op
351 * Get the OID of a datatype-specific "less than" ordering operator
352 * associated with an equality operator. (If there are multiple
353 * possibilities, assume any one will do.)
354 *
355 * This function is used when we have to sort data before unique-ifying,
356 * and don't much care which sorting op is used as long as it's compatible
357 * with the intended equality operator. Since we need a sorting operator,
358 * it should be single-data-type even if the given operator is cross-type.
359 * The caller specifies whether to find an op for the LHS or RHS data type.
360 *
361 * Returns InvalidOid if no matching ordering operator can be found.
362 */
363Oid
365{
368 int i;
369
370 /*
371 * Search pg_amop to see if the target operator is registered as the "="
372 * operator of any btree opfamily.
373 */
375
376 for (i = 0; i < catlist->n_members; i++)
377 {
378 HeapTuple tuple = &catlist->members[i]->tuple;
380 CompareType cmptype;
381
382 /* must be ordering index */
383 if (!get_opmethod_canorder(aform->amopmethod))
384 continue;
385
386 cmptype = IndexAmTranslateStrategy(aform->amopstrategy,
387 aform->amopmethod,
388 aform->amopfamily,
389 true);
390 if (cmptype == COMPARE_EQ)
391 {
392 /* Found a suitable opfamily, get matching ordering operator */
393 Oid typid;
394
395 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
397 typid, typid,
398 COMPARE_LT);
399 if (OidIsValid(result))
400 break;
401 /* failure probably shouldn't happen, but keep looking if so */
402 }
403 }
404
406
407 return result;
408}
409
410/*
411 * get_mergejoin_opfamilies
412 * Given a putatively mergejoinable operator, return a list of the OIDs
413 * of the amcanorder opfamilies in which it represents equality.
414 *
415 * It is possible (though at present unusual) for an operator to be equality
416 * in more than one opfamily, hence the result is a list. This also lets us
417 * return NIL if the operator is not found in any opfamilies.
418 *
419 * The planner currently uses simple equal() tests to compare the lists
420 * returned by this function, which makes the list order relevant, though
421 * strictly speaking it should not be. Because of the way syscache list
422 * searches are handled, in normal operation the result will be sorted by OID
423 * so everything works fine. If running with system index usage disabled,
424 * the result ordering is unspecified and hence the planner might fail to
425 * recognize optimization opportunities ... but that's hardly a scenario in
426 * which performance is good anyway, so there's no point in expending code
427 * or cycles here to guarantee the ordering in that case.
428 */
429List *
431{
432 List *result = NIL;
434 int i;
435
436 /*
437 * Search pg_amop to see if the target operator is registered as the "="
438 * operator of any opfamily of an ordering index type.
439 */
441
442 for (i = 0; i < catlist->n_members; i++)
443 {
444 HeapTuple tuple = &catlist->members[i]->tuple;
446
447 /* must be ordering index equality */
448 if (get_opmethod_canorder(aform->amopmethod) &&
449 IndexAmTranslateStrategy(aform->amopstrategy,
450 aform->amopmethod,
451 aform->amopfamily,
452 true) == COMPARE_EQ)
453 result = lappend_oid(result, aform->amopfamily);
454 }
455
457
458 return result;
459}
460
461/*
462 * get_compatible_hash_operators
463 * Get the OID(s) of hash equality operator(s) compatible with the given
464 * operator, but operating on its LHS and/or RHS datatype.
465 *
466 * An operator for the LHS type is sought and returned into *lhs_opno if
467 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
468 * and returned into *rhs_opno if rhs_opno isn't NULL.
469 *
470 * If the given operator is not cross-type, the results should be the same
471 * operator, but in cross-type situations they will be different.
472 *
473 * Returns true if able to find the requested operator(s), false if not.
474 * (This indicates that the operator should not have been marked oprcanhash.)
475 *
476 * Callers must beware that for container types (arrays, records, ranges)
477 * this function will succeed for array_eq etc, but the hash function could
478 * fail at runtime if the contained type(s) are not hashable. If it is
479 * possible that the operator is one of these, precheck with op_hashjoinable
480 * or get_op_hash_functions_ext.
481 */
482bool
485{
486 bool result = false;
488 int i;
489
490 /* Ensure output args are initialized on failure */
491 if (lhs_opno)
493 if (rhs_opno)
495
496 /*
497 * Search pg_amop to see if the target operator is registered as the "="
498 * operator of any hash opfamily. If the operator is registered in
499 * multiple opfamilies, assume we can use any one.
500 */
502
503 for (i = 0; i < catlist->n_members; i++)
504 {
505 HeapTuple tuple = &catlist->members[i]->tuple;
507
508 if (aform->amopmethod == HASH_AM_OID &&
509 aform->amopstrategy == HTEqualStrategyNumber)
510 {
511 /* No extra lookup needed if given operator is single-type */
512 if (aform->amoplefttype == aform->amoprighttype)
513 {
514 if (lhs_opno)
515 *lhs_opno = opno;
516 if (rhs_opno)
517 *rhs_opno = opno;
518 result = true;
519 break;
520 }
521
522 /*
523 * Get the matching single-type operator(s). Failure probably
524 * shouldn't happen --- it implies a bogus opfamily --- but
525 * continue looking if so.
526 */
527 if (lhs_opno)
528 {
529 *lhs_opno = get_opfamily_member(aform->amopfamily,
530 aform->amoplefttype,
531 aform->amoplefttype,
533 if (!OidIsValid(*lhs_opno))
534 continue;
535 /* Matching LHS found, done if caller doesn't want RHS */
536 if (!rhs_opno)
537 {
538 result = true;
539 break;
540 }
541 }
542 if (rhs_opno)
543 {
544 *rhs_opno = get_opfamily_member(aform->amopfamily,
545 aform->amoprighttype,
546 aform->amoprighttype,
548 if (!OidIsValid(*rhs_opno))
549 {
550 /* Forget any LHS operator from this opfamily */
551 if (lhs_opno)
553 continue;
554 }
555 /* Matching RHS found, so done */
556 result = true;
557 break;
558 }
559 }
560 }
561
563
564 return result;
565}
566
567/*
568 * get_op_hash_functions
569 * Get the OID(s) of the standard hash support function(s) compatible with
570 * the given operator, operating on its LHS and/or RHS datatype as required.
571 *
572 * A function for the LHS type is sought and returned into *lhs_procno if
573 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
574 * and returned into *rhs_procno if rhs_procno isn't NULL.
575 *
576 * If the given operator is not cross-type, the results should be the same
577 * function, but in cross-type situations they will be different.
578 *
579 * Returns true if able to find the requested function(s), false if not.
580 * (This indicates that the operator should not have been marked oprcanhash.)
581 *
582 * Callers must beware that for container types (arrays, records, ranges)
583 * this function will succeed for array_eq etc, but the hash function could
584 * fail at runtime if the contained type(s) are not hashable. If it is
585 * possible that the operator is one of these, use get_op_hash_functions_ext
586 * or precheck with op_hashjoinable.
587 */
588bool
591{
592 bool result = false;
594 int i;
595
596 /* Ensure output args are initialized on failure */
597 if (lhs_procno)
599 if (rhs_procno)
601
602 /*
603 * Search pg_amop to see if the target operator is registered as the "="
604 * operator of any hash opfamily. If the operator is registered in
605 * multiple opfamilies, assume we can use any one.
606 */
608
609 for (i = 0; i < catlist->n_members; i++)
610 {
611 HeapTuple tuple = &catlist->members[i]->tuple;
613
614 if (aform->amopmethod == HASH_AM_OID &&
615 aform->amopstrategy == HTEqualStrategyNumber)
616 {
617 /*
618 * Get the matching support function(s). Failure probably
619 * shouldn't happen --- it implies a bogus opfamily --- but
620 * continue looking if so.
621 */
622 if (lhs_procno)
623 {
624 *lhs_procno = get_opfamily_proc(aform->amopfamily,
625 aform->amoplefttype,
626 aform->amoplefttype,
628 if (!OidIsValid(*lhs_procno))
629 continue;
630 /* Matching LHS found, done if caller doesn't want RHS */
631 if (!rhs_procno)
632 {
633 result = true;
634 break;
635 }
636 /* Only one lookup needed if given operator is single-type */
637 if (aform->amoplefttype == aform->amoprighttype)
638 {
640 result = true;
641 break;
642 }
643 }
644 if (rhs_procno)
645 {
646 *rhs_procno = get_opfamily_proc(aform->amopfamily,
647 aform->amoprighttype,
648 aform->amoprighttype,
650 if (!OidIsValid(*rhs_procno))
651 {
652 /* Forget any LHS function from this opfamily */
653 if (lhs_procno)
655 continue;
656 }
657 /* Matching RHS found, so done */
658 result = true;
659 break;
660 }
661 }
662 }
663
665
666 return result;
667}
668
669/*
670 * get_op_hash_functions_ext
671 * As above, but verify hashability in container-type cases.
672 *
673 * As with op_hashjoinable, assume the left input type is sufficient
674 * to disambiguate container-type cases.
675 */
676bool
679{
680 TypeCacheEntry *typentry;
681
682 /* Ensure output args are initialized on failure */
683 if (lhs_procno)
685 if (rhs_procno)
687
688 /* As in op_hashjoinable, let the typcache handle the hard cases */
689 if (opno == ARRAY_EQ_OP)
690 {
691 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
692 if (typentry->hash_proc != F_HASH_ARRAY)
693 return false;
694 }
695 else if (opno == RECORD_EQ_OP)
696 {
697 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
698 if (typentry->hash_proc != F_HASH_RECORD)
699 return false;
700 }
701 else if (opno == RANGE_EQ_OP)
702 {
703 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
704 if (typentry->hash_proc != F_HASH_RANGE)
705 return false;
706 }
707 else if (opno == MULTIRANGE_EQ_OP)
708 {
709 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
710 if (typentry->hash_proc != F_HASH_MULTIRANGE)
711 return false;
712 }
713
714 /* OK, do the normal lookup */
716}
717
718/*
719 * get_op_index_interpretation
720 * Given an operator's OID, find out which amcanorder opfamilies it belongs to,
721 * and what properties it has within each one. The results are returned
722 * as a palloc'd list of OpIndexInterpretation structs.
723 *
724 * In addition to the normal btree operators, we consider a <> operator to be
725 * a "member" of an opfamily if its negator is an equality operator of the
726 * opfamily. COMPARE_NE is returned as the strategy number for this case.
727 */
728List *
730{
731 List *result = NIL;
734 int i;
735
736 /*
737 * Find all the pg_amop entries containing the operator.
738 */
740
741 for (i = 0; i < catlist->n_members; i++)
742 {
743 HeapTuple op_tuple = &catlist->members[i]->tuple;
745 CompareType cmptype;
746
747 /* must be ordering index */
748 if (!get_opmethod_canorder(op_form->amopmethod))
749 continue;
750
751 /* Get the operator's comparison type */
752 cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
753 op_form->amopmethod,
754 op_form->amopfamily,
755 true);
756
757 /* should not happen */
758 if (cmptype == COMPARE_INVALID)
759 continue;
760
762 thisresult->opfamily_id = op_form->amopfamily;
763 thisresult->cmptype = cmptype;
764 thisresult->oplefttype = op_form->amoplefttype;
765 thisresult->oprighttype = op_form->amoprighttype;
767 }
768
770
771 /*
772 * If we didn't find any btree opfamily containing the operator, perhaps
773 * it is a <> operator. See if it has a negator that is in an opfamily.
774 */
775 if (result == NIL)
776 {
777 Oid op_negator = get_negator(opno);
778
780 {
783
784 for (i = 0; i < catlist->n_members; i++)
785 {
786 HeapTuple op_tuple = &catlist->members[i]->tuple;
788 const IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
789 CompareType cmptype;
790
791 /* must be ordering index */
792 if (!amroutine->amcanorder)
793 continue;
794
795 /* Get the operator's comparison type */
796 cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
797 op_form->amopmethod,
798 op_form->amopfamily,
799 true);
800
801 /* Only consider negators that are = */
802 if (cmptype != COMPARE_EQ)
803 continue;
804
805 /* OK, report it as COMPARE_NE */
807 thisresult->opfamily_id = op_form->amopfamily;
808 thisresult->cmptype = COMPARE_NE;
809 thisresult->oplefttype = op_form->amoplefttype;
810 thisresult->oprighttype = op_form->amoprighttype;
812 }
813
815 }
816 }
817
818 return result;
819}
820
821/*
822 * equality_ops_are_compatible
823 * Return true if the two given operators have compatible equality
824 * semantics.
825 *
826 * This is trivially true if they are the same operator. Otherwise,
827 * we look to see if they both belong to an opfamily that guarantees
828 * compatible semantics for equality. Either finding allows us to assume
829 * that they have compatible notions of equality.
830 *
831 * The typical use is to compare two equality operators (for instance the
832 * cross-type operators int24eq vs int4eq), but the test is meaningful for
833 * any pair of operators in a btree/hash opfamily. Btree marks its
834 * opfamilies as amconsistentequality, which guarantees that every member
835 * of the family (=, <, <=, >, >=) agrees on the equivalence relation
836 * defined by the family's "=". So a non-equality operator and an
837 * equality operator from the same opfamily are also "compatible" in this
838 * sense.
839 */
840bool
842{
843 bool result;
845 int i;
846
847 /* Easy if they're the same operator */
848 if (opno1 == opno2)
849 return true;
850
851 /*
852 * We search through all the pg_amop entries for opno1.
853 */
855
856 result = false;
857 for (i = 0; i < catlist->n_members; i++)
858 {
859 HeapTuple op_tuple = &catlist->members[i]->tuple;
861
862 /*
863 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
864 * check it first
865 */
866 if (op_in_opfamily(opno2, op_form->amopfamily) &&
868 {
869 result = true;
870 break;
871 }
872 }
873
875
876 return result;
877}
878
879/*
880 * comparison_ops_are_compatible
881 * Return true if the two given comparison operators have compatible
882 * semantics.
883 *
884 * This is trivially true if they are the same operator. Otherwise, we look
885 * to see if they both belong to an opfamily that guarantees compatible
886 * semantics for ordering. (For example, for btree, '<' and '>=' ops match if
887 * they belong to the same family.)
888 *
889 * (This is identical to equality_ops_are_compatible(), except that we check
890 * amconsistentordering instead of amconsistentequality.)
891 */
892bool
894{
895 bool result;
897 int i;
898
899 /* Easy if they're the same operator */
900 if (opno1 == opno2)
901 return true;
902
903 /*
904 * We search through all the pg_amop entries for opno1.
905 */
907
908 result = false;
909 for (i = 0; i < catlist->n_members; i++)
910 {
911 HeapTuple op_tuple = &catlist->members[i]->tuple;
913
914 /*
915 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
916 * check it first
917 */
918 if (op_in_opfamily(opno2, op_form->amopfamily) &&
920 {
921 result = true;
922 break;
923 }
924 }
925
927
928 return result;
929}
930
931/*
932 * collations_agree_on_equality
933 * Return true if the two collations have equivalent notions of equality,
934 * so that a uniqueness or equality proof established under one side
935 * carries over to a comparison performed under the other side.
936 *
937 * Note: this is equality compatibility only. Do NOT use this to reason
938 * about ordering.
939 *
940 * An InvalidOid on either side denotes the absence of a collation -- that
941 * side's operation is not collation-sensitive (e.g. a non-collatable column
942 * type). Absence of a collation cannot conflict with the other side's
943 * collation, so we treat such pairs as agreeing on equality. This generalizes
944 * the asymmetric treatment in IndexCollMatchesExprColl().
945 *
946 * Otherwise the collations have equivalent equality if they match, or if both
947 * are deterministic: by definition a deterministic collation treats two
948 * strings as equal iff they are byte-wise equal (see CREATE COLLATION), so any
949 * two deterministic collations share the same equality relation. A mismatch
950 * involving a nondeterministic collation, however, may mean the two equality
951 * relations disagree, and the proof is unsound.
952 */
953bool
955{
956 if (!OidIsValid(coll1) || !OidIsValid(coll2))
957 return true;
958
959 if (coll1 == coll2)
960 return true;
961
964 return false;
965
966 return true;
967}
968
969/*
970 * op_is_safe_index_member
971 * Check if the operator is a member of a B-tree or Hash operator family.
972 *
973 * Membership in such an opfamily has several useful implications: the operator
974 * returns non-null for non-null inputs (i.e. "null-safety", required so that
975 * the operator doesn't break index integrity), and it agrees with other
976 * members of the same opfamily on equality semantics. Callers use this check
977 * as a proxy for any of those properties.
978 */
979bool
981{
982 bool result = false;
984 int i;
985
986 /*
987 * Search pg_amop to see if the target operator is registered for any
988 * btree or hash opfamily.
989 */
991
992 for (i = 0; i < catlist->n_members; i++)
993 {
994 HeapTuple tuple = &catlist->members[i]->tuple;
996
997 /* Check if the AM is B-tree or Hash */
998 if (aform->amopmethod == BTREE_AM_OID ||
999 aform->amopmethod == HASH_AM_OID)
1000 {
1001 result = true;
1002 break;
1003 }
1004 }
1005
1007
1008 return result;
1009}
1010
1011
1012/* ---------- AMPROC CACHES ---------- */
1013
1014/*
1015 * get_opfamily_proc
1016 * Get the OID of the specified support function
1017 * for the specified opfamily and datatypes.
1018 *
1019 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
1020 */
1021Oid
1022get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
1023{
1024 HeapTuple tp;
1027
1029 ObjectIdGetDatum(opfamily),
1030 ObjectIdGetDatum(lefttype),
1031 ObjectIdGetDatum(righttype),
1033 if (!HeapTupleIsValid(tp))
1034 return InvalidOid;
1036 result = amproc_tup->amproc;
1037 ReleaseSysCache(tp);
1038 return result;
1039}
1040
1041
1042/* ---------- ATTRIBUTE CACHES ---------- */
1043
1044/*
1045 * get_attname
1046 * Given the relation id and the attribute number, return the "attname"
1047 * field from the attribute relation as a palloc'ed string.
1048 *
1049 * If no such attribute exists and missing_ok is true, NULL is returned;
1050 * otherwise a not-intended-for-user-consumption error is thrown.
1051 */
1052char *
1053get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
1054{
1055 HeapTuple tp;
1056
1059 if (HeapTupleIsValid(tp))
1060 {
1062 char *result;
1063
1064 result = pstrdup(NameStr(att_tup->attname));
1065 ReleaseSysCache(tp);
1066 return result;
1067 }
1068
1069 if (!missing_ok)
1070 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1071 attnum, relid);
1072 return NULL;
1073}
1074
1075/*
1076 * get_attnum
1077 *
1078 * Given the relation id and the attribute name,
1079 * return the "attnum" field from the attribute relation.
1080 *
1081 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
1082 */
1084get_attnum(Oid relid, const char *attname)
1085{
1086 HeapTuple tp;
1087
1088 tp = SearchSysCacheAttName(relid, attname);
1089 if (HeapTupleIsValid(tp))
1090 {
1093
1094 result = att_tup->attnum;
1095 ReleaseSysCache(tp);
1096 return result;
1097 }
1098 else
1099 return InvalidAttrNumber;
1100}
1101
1102/*
1103 * get_attgenerated
1104 *
1105 * Given the relation id and the attribute number,
1106 * return the "attgenerated" field from the attribute relation.
1107 *
1108 * Errors if not found.
1109 *
1110 * Since not generated is represented by '\0', this can also be used as a
1111 * Boolean test.
1112 */
1113char
1115{
1116 HeapTuple tp;
1118 char result;
1119
1121 ObjectIdGetDatum(relid),
1123 if (!HeapTupleIsValid(tp))
1124 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1125 attnum, relid);
1127 result = att_tup->attgenerated;
1128 ReleaseSysCache(tp);
1129 return result;
1130}
1131
1132/*
1133 * get_atttype
1134 *
1135 * Given the relation OID and the attribute number with the relation,
1136 * return the attribute type OID.
1137 */
1138Oid
1140{
1141 HeapTuple tp;
1142
1144 ObjectIdGetDatum(relid),
1146 if (HeapTupleIsValid(tp))
1147 {
1149 Oid result;
1150
1151 result = att_tup->atttypid;
1152 ReleaseSysCache(tp);
1153 return result;
1154 }
1155 else
1156 return InvalidOid;
1157}
1158
1159/*
1160 * get_atttypetypmodcoll
1161 *
1162 * A three-fer: given the relation id and the attribute number,
1163 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
1164 *
1165 * Unlike the otherwise-similar get_atttype, this routine
1166 * raises an error if it can't obtain the information.
1167 */
1168void
1170 Oid *typid, int32 *typmod, Oid *collid)
1171{
1172 HeapTuple tp;
1174
1176 ObjectIdGetDatum(relid),
1178 if (!HeapTupleIsValid(tp))
1179 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1180 attnum, relid);
1182
1183 *typid = att_tup->atttypid;
1184 *typmod = att_tup->atttypmod;
1185 *collid = att_tup->attcollation;
1186 ReleaseSysCache(tp);
1187}
1188
1189/*
1190 * get_attoptions
1191 *
1192 * Given the relation id and the attribute number,
1193 * return the attribute options text[] datum, if any.
1194 */
1195Datum
1197{
1198 HeapTuple tuple;
1199 Datum attopts;
1200 Datum result;
1201 bool isnull;
1202
1203 tuple = SearchSysCache2(ATTNUM,
1204 ObjectIdGetDatum(relid),
1206
1207 if (!HeapTupleIsValid(tuple))
1208 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1209 attnum, relid);
1210
1212 &isnull);
1213
1214 if (isnull)
1215 result = (Datum) 0;
1216 else
1217 result = datumCopy(attopts, false, -1); /* text[] */
1218
1219 ReleaseSysCache(tuple);
1220
1221 return result;
1222}
1223
1224/* ---------- PG_CAST CACHE ---------- */
1225
1226/*
1227 * get_cast_oid - given two type OIDs, look up a cast OID
1228 *
1229 * If missing_ok is false, throw an error if the cast is not found. If
1230 * true, just return InvalidOid.
1231 */
1232Oid
1234{
1235 Oid oid;
1236
1240 if (!OidIsValid(oid) && !missing_ok)
1241 ereport(ERROR,
1243 errmsg("cast from type %s to type %s does not exist",
1246 return oid;
1247}
1248
1249/* ---------- COLLATION CACHE ---------- */
1250
1251/*
1252 * get_collation_name
1253 * Returns the name of a given pg_collation entry.
1254 *
1255 * Returns a palloc'd copy of the string, or NULL if no such collation.
1256 *
1257 * NOTE: since collation name is not unique, be wary of code that uses this
1258 * for anything except preparing error messages.
1259 */
1260char *
1262{
1263 HeapTuple tp;
1264
1266 if (HeapTupleIsValid(tp))
1267 {
1269 char *result;
1270
1271 result = pstrdup(NameStr(colltup->collname));
1272 ReleaseSysCache(tp);
1273 return result;
1274 }
1275 else
1276 return NULL;
1277}
1278
1279bool
1281{
1282 HeapTuple tp;
1284 bool result;
1285
1287 if (!HeapTupleIsValid(tp))
1288 elog(ERROR, "cache lookup failed for collation %u", colloid);
1290 result = colltup->collisdeterministic;
1291 ReleaseSysCache(tp);
1292 return result;
1293}
1294
1295/* ---------- CONSTRAINT CACHE ---------- */
1296
1297/*
1298 * get_constraint_name
1299 * Returns the name of a given pg_constraint entry.
1300 *
1301 * Returns a palloc'd copy of the string, or NULL if no such constraint.
1302 *
1303 * NOTE: since constraint name is not unique, be wary of code that uses this
1304 * for anything except preparing error messages.
1305 */
1306char *
1308{
1309 HeapTuple tp;
1310
1312 if (HeapTupleIsValid(tp))
1313 {
1315 char *result;
1316
1317 result = pstrdup(NameStr(contup->conname));
1318 ReleaseSysCache(tp);
1319 return result;
1320 }
1321 else
1322 return NULL;
1323}
1324
1325/*
1326 * get_constraint_index
1327 * Given the OID of a unique, primary-key, or exclusion constraint,
1328 * return the OID of the underlying index.
1329 *
1330 * Returns InvalidOid if the constraint could not be found or is of
1331 * the wrong type.
1332 *
1333 * The intent of this function is to return the index "owned" by the
1334 * specified constraint. Therefore we must check contype, since some
1335 * pg_constraint entries (e.g. for foreign-key constraints) store the
1336 * OID of an index that is referenced but not owned by the constraint.
1337 */
1338Oid
1340{
1341 HeapTuple tp;
1342
1344 if (HeapTupleIsValid(tp))
1345 {
1347 Oid result;
1348
1349 if (contup->contype == CONSTRAINT_UNIQUE ||
1350 contup->contype == CONSTRAINT_PRIMARY ||
1351 contup->contype == CONSTRAINT_EXCLUSION)
1352 result = contup->conindid;
1353 else
1355 ReleaseSysCache(tp);
1356 return result;
1357 }
1358 else
1359 return InvalidOid;
1360}
1361
1362/*
1363 * get_constraint_type
1364 * Return the pg_constraint.contype value for the given constraint.
1365 *
1366 * No frills.
1367 */
1368char
1370{
1371 HeapTuple tp;
1372 char contype;
1373
1375 if (!HeapTupleIsValid(tp))
1376 elog(ERROR, "cache lookup failed for constraint %u", conoid);
1377
1378 contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
1379 ReleaseSysCache(tp);
1380
1381 return contype;
1382}
1383
1384/* ---------- DATABASE CACHE ---------- */
1385
1386/*
1387 * get_database_name - given a database OID, look up the name
1388 *
1389 * Returns a palloc'd string, or NULL if no such database.
1390 */
1391char *
1393{
1395 char *result;
1396
1399 {
1402 }
1403 else
1404 result = NULL;
1405
1406 return result;
1407}
1408
1409
1410/* ---------- LANGUAGE CACHE ---------- */
1411
1412char *
1414{
1415 HeapTuple tp;
1416
1418 if (HeapTupleIsValid(tp))
1419 {
1421 char *result;
1422
1423 result = pstrdup(NameStr(lantup->lanname));
1424 ReleaseSysCache(tp);
1425 return result;
1426 }
1427
1428 if (!missing_ok)
1429 elog(ERROR, "cache lookup failed for language %u",
1430 langoid);
1431 return NULL;
1432}
1433
1434/* ---------- OPCLASS CACHE ---------- */
1435
1436/*
1437 * get_opclass_family
1438 *
1439 * Returns the OID of the operator family the opclass belongs to.
1440 */
1441Oid
1443{
1444 HeapTuple tp;
1446 Oid result;
1447
1448 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1449 if (!HeapTupleIsValid(tp))
1450 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1452
1453 result = cla_tup->opcfamily;
1454 ReleaseSysCache(tp);
1455 return result;
1456}
1457
1458/*
1459 * get_opclass_input_type
1460 *
1461 * Returns the OID of the datatype the opclass indexes.
1462 */
1463Oid
1465{
1466 HeapTuple tp;
1468 Oid result;
1469
1470 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1471 if (!HeapTupleIsValid(tp))
1472 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1474
1475 result = cla_tup->opcintype;
1476 ReleaseSysCache(tp);
1477 return result;
1478}
1479
1480/*
1481 * get_opclass_opfamily_and_input_type
1482 *
1483 * Returns the OID of the operator family the opclass belongs to,
1484 * the OID of the datatype the opclass indexes
1485 */
1486bool
1487get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1488{
1489 HeapTuple tp;
1491
1492 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1493 if (!HeapTupleIsValid(tp))
1494 return false;
1495
1497
1498 *opfamily = cla_tup->opcfamily;
1499 *opcintype = cla_tup->opcintype;
1500
1501 ReleaseSysCache(tp);
1502
1503 return true;
1504}
1505
1506/*
1507 * get_opclass_method
1508 *
1509 * Returns the OID of the index access method the opclass belongs to.
1510 */
1511Oid
1513{
1514 HeapTuple tp;
1516 Oid result;
1517
1518 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1519 if (!HeapTupleIsValid(tp))
1520 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1522
1523 result = cla_tup->opcmethod;
1524 ReleaseSysCache(tp);
1525 return result;
1526}
1527
1528/* ---------- OPFAMILY CACHE ---------- */
1529
1530/*
1531 * get_opfamily_method
1532 *
1533 * Returns the OID of the index access method the opfamily is for.
1534 */
1535Oid
1537{
1538 HeapTuple tp;
1540 Oid result;
1541
1543 if (!HeapTupleIsValid(tp))
1544 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1546
1547 result = opfform->opfmethod;
1548 ReleaseSysCache(tp);
1549 return result;
1550}
1551
1552char *
1553get_opfamily_name(Oid opfid, bool missing_ok)
1554{
1555 HeapTuple tup;
1556 char *opfname;
1558
1560
1561 if (!HeapTupleIsValid(tup))
1562 {
1563 if (!missing_ok)
1564 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1565 return NULL;
1566 }
1567
1569 opfname = pstrdup(NameStr(opfform->opfname));
1570
1572
1573 return opfname;
1574}
1575
1576/* ---------- OPERATOR CACHE ---------- */
1577
1578/*
1579 * get_opcode
1580 *
1581 * Returns the regproc id of the routine used to implement an
1582 * operator given the operator oid.
1583 */
1586{
1587 HeapTuple tp;
1588
1590 if (HeapTupleIsValid(tp))
1591 {
1594
1595 result = optup->oprcode;
1596 ReleaseSysCache(tp);
1597 return result;
1598 }
1599 else
1600 return (RegProcedure) InvalidOid;
1601}
1602
1603/*
1604 * get_opname
1605 * returns the name of the operator with the given opno
1606 *
1607 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1608 */
1609char *
1611{
1612 HeapTuple tp;
1613
1615 if (HeapTupleIsValid(tp))
1616 {
1618 char *result;
1619
1620 result = pstrdup(NameStr(optup->oprname));
1621 ReleaseSysCache(tp);
1622 return result;
1623 }
1624 else
1625 return NULL;
1626}
1627
1628/*
1629 * get_op_rettype
1630 * Given operator oid, return the operator's result type.
1631 */
1632Oid
1634{
1635 HeapTuple tp;
1636
1638 if (HeapTupleIsValid(tp))
1639 {
1641 Oid result;
1642
1643 result = optup->oprresult;
1644 ReleaseSysCache(tp);
1645 return result;
1646 }
1647 else
1648 return InvalidOid;
1649}
1650
1651/*
1652 * op_input_types
1653 *
1654 * Returns the left and right input datatypes for an operator
1655 * (InvalidOid if not relevant).
1656 */
1657void
1658op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1659{
1660 HeapTuple tp;
1662
1664 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1665 elog(ERROR, "cache lookup failed for operator %u", opno);
1667 *lefttype = optup->oprleft;
1668 *righttype = optup->oprright;
1669 ReleaseSysCache(tp);
1670}
1671
1672/*
1673 * op_mergejoinable
1674 *
1675 * Returns true if the operator is potentially mergejoinable. (The planner
1676 * will fail to find any mergejoin plans unless there are suitable btree
1677 * opfamily entries for this operator and associated sortops. The pg_operator
1678 * flag is just a hint to tell the planner whether to bother looking.)
1679 *
1680 * In some cases (currently only array_eq and record_eq), mergejoinability
1681 * depends on the specific input data type the operator is invoked for, so
1682 * that must be passed as well. We currently assume that only one input's type
1683 * is needed to check this --- by convention, pass the left input's data type.
1684 */
1685bool
1686op_mergejoinable(Oid opno, Oid inputtype)
1687{
1688 bool result = false;
1689 HeapTuple tp;
1690 TypeCacheEntry *typentry;
1691
1692 /*
1693 * For array_eq or record_eq, we can sort if the element or field types
1694 * are all sortable. We could implement all the checks for that here, but
1695 * the typcache already does that and caches the results too, so let's
1696 * rely on the typcache. We do not need similar special cases for ranges
1697 * or multiranges, because their subtypes are required to be sortable.
1698 */
1699 if (opno == ARRAY_EQ_OP)
1700 {
1701 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1702 if (typentry->cmp_proc == F_BTARRAYCMP)
1703 result = true;
1704 }
1705 else if (opno == RECORD_EQ_OP)
1706 {
1707 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1708 if (typentry->cmp_proc == F_BTRECORDCMP)
1709 result = true;
1710 }
1711 else
1712 {
1713 /* For all other operators, rely on pg_operator.oprcanmerge */
1715 if (HeapTupleIsValid(tp))
1716 {
1718
1719 result = optup->oprcanmerge;
1720 ReleaseSysCache(tp);
1721 }
1722 }
1723 return result;
1724}
1725
1726/*
1727 * op_hashjoinable
1728 *
1729 * Returns true if the operator is hashjoinable. (There must be a suitable
1730 * hash opfamily entry for this operator if it is so marked.)
1731 *
1732 * In some cases (currently array_eq, record_eq, range_eq, multirange_eq),
1733 * hashjoinability depends on the specific input data type the operator is
1734 * invoked for, so that must be passed as well. We currently assume that only
1735 * one input's type is needed to check this --- by convention, pass the left
1736 * input's data type.
1737 */
1738bool
1739op_hashjoinable(Oid opno, Oid inputtype)
1740{
1741 bool result = false;
1742 HeapTuple tp;
1743 TypeCacheEntry *typentry;
1744
1745 /* As in op_mergejoinable, let the typcache handle the hard cases */
1746 if (opno == ARRAY_EQ_OP)
1747 {
1748 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1749 if (typentry->hash_proc == F_HASH_ARRAY)
1750 result = true;
1751 }
1752 else if (opno == RECORD_EQ_OP)
1753 {
1754 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1755 if (typentry->hash_proc == F_HASH_RECORD)
1756 result = true;
1757 }
1758 else if (opno == RANGE_EQ_OP)
1759 {
1760 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1761 if (typentry->hash_proc == F_HASH_RANGE)
1762 result = true;
1763 }
1764 else if (opno == MULTIRANGE_EQ_OP)
1765 {
1766 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1767 if (typentry->hash_proc == F_HASH_MULTIRANGE)
1768 result = true;
1769 }
1770 else
1771 {
1772 /* For all other operators, rely on pg_operator.oprcanhash */
1774 if (HeapTupleIsValid(tp))
1775 {
1777
1778 result = optup->oprcanhash;
1779 ReleaseSysCache(tp);
1780 }
1781 }
1782 return result;
1783}
1784
1785/*
1786 * op_strict
1787 *
1788 * Get the proisstrict flag for the operator's underlying function.
1789 */
1790bool
1792{
1793 RegProcedure funcid = get_opcode(opno);
1794
1795 if (funcid == (RegProcedure) InvalidOid)
1796 elog(ERROR, "operator %u does not exist", opno);
1797
1798 return func_strict((Oid) funcid);
1799}
1800
1801/*
1802 * op_volatile
1803 *
1804 * Get the provolatile flag for the operator's underlying function.
1805 */
1806char
1808{
1809 RegProcedure funcid = get_opcode(opno);
1810
1811 if (funcid == (RegProcedure) InvalidOid)
1812 elog(ERROR, "operator %u does not exist", opno);
1813
1814 return func_volatile((Oid) funcid);
1815}
1816
1817/*
1818 * get_commutator
1819 *
1820 * Returns the corresponding commutator of an operator.
1821 */
1822Oid
1824{
1825 HeapTuple tp;
1826
1828 if (HeapTupleIsValid(tp))
1829 {
1831 Oid result;
1832
1833 result = optup->oprcom;
1834 ReleaseSysCache(tp);
1835 return result;
1836 }
1837 else
1838 return InvalidOid;
1839}
1840
1841/*
1842 * get_negator
1843 *
1844 * Returns the corresponding negator of an operator.
1845 */
1846Oid
1848{
1849 HeapTuple tp;
1850
1852 if (HeapTupleIsValid(tp))
1853 {
1855 Oid result;
1856
1857 result = optup->oprnegate;
1858 ReleaseSysCache(tp);
1859 return result;
1860 }
1861 else
1862 return InvalidOid;
1863}
1864
1865/*
1866 * get_oprrest
1867 *
1868 * Returns procedure id for computing selectivity of an operator.
1869 */
1872{
1873 HeapTuple tp;
1874
1876 if (HeapTupleIsValid(tp))
1877 {
1880
1881 result = optup->oprrest;
1882 ReleaseSysCache(tp);
1883 return result;
1884 }
1885 else
1886 return (RegProcedure) InvalidOid;
1887}
1888
1889/*
1890 * get_oprjoin
1891 *
1892 * Returns procedure id for computing selectivity of a join.
1893 */
1896{
1897 HeapTuple tp;
1898
1900 if (HeapTupleIsValid(tp))
1901 {
1904
1905 result = optup->oprjoin;
1906 ReleaseSysCache(tp);
1907 return result;
1908 }
1909 else
1910 return (RegProcedure) InvalidOid;
1911}
1912
1913/* ---------- FUNCTION CACHE ---------- */
1914
1915/*
1916 * get_func_name
1917 * returns the name of the function with the given funcid
1918 *
1919 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1920 */
1921char *
1923{
1924 HeapTuple tp;
1925
1927 if (HeapTupleIsValid(tp))
1928 {
1930 char *result;
1931
1932 result = pstrdup(NameStr(functup->proname));
1933 ReleaseSysCache(tp);
1934 return result;
1935 }
1936 else
1937 return NULL;
1938}
1939
1940/*
1941 * get_func_namespace
1942 *
1943 * Returns the pg_namespace OID associated with a given function.
1944 */
1945Oid
1947{
1948 HeapTuple tp;
1949
1951 if (HeapTupleIsValid(tp))
1952 {
1954 Oid result;
1955
1956 result = functup->pronamespace;
1957 ReleaseSysCache(tp);
1958 return result;
1959 }
1960 else
1961 return InvalidOid;
1962}
1963
1964/*
1965 * get_func_rettype
1966 * Given procedure id, return the function's result type.
1967 */
1968Oid
1970{
1971 HeapTuple tp;
1972 Oid result;
1973
1975 if (!HeapTupleIsValid(tp))
1976 elog(ERROR, "cache lookup failed for function %u", funcid);
1977
1978 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1979 ReleaseSysCache(tp);
1980 return result;
1981}
1982
1983/*
1984 * get_func_nargs
1985 * Given procedure id, return the number of arguments.
1986 */
1987int
1989{
1990 HeapTuple tp;
1991 int result;
1992
1994 if (!HeapTupleIsValid(tp))
1995 elog(ERROR, "cache lookup failed for function %u", funcid);
1996
1998 ReleaseSysCache(tp);
1999 return result;
2000}
2001
2002/*
2003 * get_func_signature
2004 * Given procedure id, return the function's argument and result types.
2005 * (The return value is the result type.)
2006 *
2007 * The arguments are returned as a palloc'd array.
2008 */
2009Oid
2010get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
2011{
2012 HeapTuple tp;
2014 Oid result;
2015
2017 if (!HeapTupleIsValid(tp))
2018 elog(ERROR, "cache lookup failed for function %u", funcid);
2019
2021
2022 result = procstruct->prorettype;
2023 *nargs = (int) procstruct->pronargs;
2024 Assert(*nargs == procstruct->proargtypes.dim1);
2025 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
2026 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
2027
2028 ReleaseSysCache(tp);
2029 return result;
2030}
2031
2032/*
2033 * get_func_variadictype
2034 * Given procedure id, return the function's provariadic field.
2035 */
2036Oid
2038{
2039 HeapTuple tp;
2040 Oid result;
2041
2043 if (!HeapTupleIsValid(tp))
2044 elog(ERROR, "cache lookup failed for function %u", funcid);
2045
2047 ReleaseSysCache(tp);
2048 return result;
2049}
2050
2051/*
2052 * get_func_retset
2053 * Given procedure id, return the function's proretset flag.
2054 */
2055bool
2057{
2058 HeapTuple tp;
2059 bool result;
2060
2062 if (!HeapTupleIsValid(tp))
2063 elog(ERROR, "cache lookup failed for function %u", funcid);
2064
2066 ReleaseSysCache(tp);
2067 return result;
2068}
2069
2070/*
2071 * func_strict
2072 * Given procedure id, return the function's proisstrict flag.
2073 */
2074bool
2076{
2077 HeapTuple tp;
2078 bool result;
2079
2081 if (!HeapTupleIsValid(tp))
2082 elog(ERROR, "cache lookup failed for function %u", funcid);
2083
2085 ReleaseSysCache(tp);
2086 return result;
2087}
2088
2089/*
2090 * func_volatile
2091 * Given procedure id, return the function's provolatile flag.
2092 */
2093char
2095{
2096 HeapTuple tp;
2097 char result;
2098
2100 if (!HeapTupleIsValid(tp))
2101 elog(ERROR, "cache lookup failed for function %u", funcid);
2102
2104 ReleaseSysCache(tp);
2105 return result;
2106}
2107
2108/*
2109 * func_parallel
2110 * Given procedure id, return the function's proparallel flag.
2111 */
2112char
2114{
2115 HeapTuple tp;
2116 char result;
2117
2119 if (!HeapTupleIsValid(tp))
2120 elog(ERROR, "cache lookup failed for function %u", funcid);
2121
2123 ReleaseSysCache(tp);
2124 return result;
2125}
2126
2127/*
2128 * get_func_prokind
2129 * Given procedure id, return the routine kind.
2130 */
2131char
2133{
2134 HeapTuple tp;
2135 char result;
2136
2138 if (!HeapTupleIsValid(tp))
2139 elog(ERROR, "cache lookup failed for function %u", funcid);
2140
2141 result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
2142 ReleaseSysCache(tp);
2143 return result;
2144}
2145
2146/*
2147 * get_func_leakproof
2148 * Given procedure id, return the function's leakproof field.
2149 */
2150bool
2152{
2153 HeapTuple tp;
2154 bool result;
2155
2157 if (!HeapTupleIsValid(tp))
2158 elog(ERROR, "cache lookup failed for function %u", funcid);
2159
2161 ReleaseSysCache(tp);
2162 return result;
2163}
2164
2165/*
2166 * get_func_support
2167 *
2168 * Returns the support function OID associated with a given function,
2169 * or InvalidOid if there is none.
2170 */
2173{
2174 HeapTuple tp;
2175
2177 if (HeapTupleIsValid(tp))
2178 {
2181
2182 result = functup->prosupport;
2183 ReleaseSysCache(tp);
2184 return result;
2185 }
2186 else
2187 return (RegProcedure) InvalidOid;
2188}
2189
2190/* ---------- RELATION CACHE ---------- */
2191
2192/*
2193 * get_relname_relid
2194 * Given name and namespace of a relation, look up the OID.
2195 *
2196 * Returns InvalidOid if there is no such relation.
2197 */
2198Oid
2199get_relname_relid(const char *relname, Oid relnamespace)
2200{
2203 ObjectIdGetDatum(relnamespace));
2204}
2205
2206#ifdef NOT_USED
2207/*
2208 * get_relnatts
2209 *
2210 * Returns the number of attributes for a given relation.
2211 */
2212int
2213get_relnatts(Oid relid)
2214{
2215 HeapTuple tp;
2216
2218 if (HeapTupleIsValid(tp))
2219 {
2221 int result;
2222
2223 result = reltup->relnatts;
2224 ReleaseSysCache(tp);
2225 return result;
2226 }
2227 else
2228 return InvalidAttrNumber;
2229}
2230#endif
2231
2232/*
2233 * get_rel_name
2234 * Returns the name of a given relation.
2235 *
2236 * Returns a palloc'd copy of the string, or NULL if no such relation.
2237 *
2238 * NOTE: since relation name is not unique, be wary of code that uses this
2239 * for anything except preparing error messages.
2240 */
2241char *
2243{
2244 HeapTuple tp;
2245
2247 if (HeapTupleIsValid(tp))
2248 {
2250 char *result;
2251
2252 result = pstrdup(NameStr(reltup->relname));
2253 ReleaseSysCache(tp);
2254 return result;
2255 }
2256 else
2257 return NULL;
2258}
2259
2260/*
2261 * get_rel_namespace
2262 *
2263 * Returns the pg_namespace OID associated with a given relation.
2264 */
2265Oid
2267{
2268 HeapTuple tp;
2269
2271 if (HeapTupleIsValid(tp))
2272 {
2274 Oid result;
2275
2276 result = reltup->relnamespace;
2277 ReleaseSysCache(tp);
2278 return result;
2279 }
2280 else
2281 return InvalidOid;
2282}
2283
2284/*
2285 * get_rel_type_id
2286 *
2287 * Returns the pg_type OID associated with a given relation.
2288 *
2289 * Note: not all pg_class entries have associated pg_type OIDs; so be
2290 * careful to check for InvalidOid result.
2291 */
2292Oid
2294{
2295 HeapTuple tp;
2296
2298 if (HeapTupleIsValid(tp))
2299 {
2301 Oid result;
2302
2303 result = reltup->reltype;
2304 ReleaseSysCache(tp);
2305 return result;
2306 }
2307 else
2308 return InvalidOid;
2309}
2310
2311/*
2312 * get_rel_relkind
2313 *
2314 * Returns the relkind associated with a given relation.
2315 */
2316char
2318{
2319 HeapTuple tp;
2320
2322 if (HeapTupleIsValid(tp))
2323 {
2325 char result;
2326
2327 result = reltup->relkind;
2328 ReleaseSysCache(tp);
2329 return result;
2330 }
2331 else
2332 return '\0';
2333}
2334
2335/*
2336 * get_rel_relispartition
2337 *
2338 * Returns the relispartition flag associated with a given relation.
2339 */
2340bool
2342{
2343 HeapTuple tp;
2344
2346 if (HeapTupleIsValid(tp))
2347 {
2349 bool result;
2350
2351 result = reltup->relispartition;
2352 ReleaseSysCache(tp);
2353 return result;
2354 }
2355 else
2356 return false;
2357}
2358
2359/*
2360 * get_rel_tablespace
2361 *
2362 * Returns the pg_tablespace OID associated with a given relation.
2363 *
2364 * Note: InvalidOid might mean either that we couldn't find the relation,
2365 * or that it is in the database's default tablespace.
2366 */
2367Oid
2369{
2370 HeapTuple tp;
2371
2373 if (HeapTupleIsValid(tp))
2374 {
2376 Oid result;
2377
2378 result = reltup->reltablespace;
2379 ReleaseSysCache(tp);
2380 return result;
2381 }
2382 else
2383 return InvalidOid;
2384}
2385
2386/*
2387 * get_rel_persistence
2388 *
2389 * Returns the relpersistence associated with a given relation.
2390 */
2391char
2393{
2394 HeapTuple tp;
2396 char result;
2397
2399 if (!HeapTupleIsValid(tp))
2400 elog(ERROR, "cache lookup failed for relation %u", relid);
2402 result = reltup->relpersistence;
2403 ReleaseSysCache(tp);
2404
2405 return result;
2406}
2407
2408/*
2409 * get_rel_relam
2410 *
2411 * Returns the relam associated with a given relation.
2412 */
2413Oid
2415{
2416 HeapTuple tp;
2418 Oid result;
2419
2421 if (!HeapTupleIsValid(tp))
2422 elog(ERROR, "cache lookup failed for relation %u", relid);
2424 result = reltup->relam;
2425 ReleaseSysCache(tp);
2426
2427 return result;
2428}
2429
2430
2431/* ---------- TRANSFORM CACHE ---------- */
2432
2433Oid
2434get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2435{
2436 HeapTuple tup;
2437
2438 if (!list_member_oid(trftypes, typid))
2439 return InvalidOid;
2440
2442 ObjectIdGetDatum(langid));
2443 if (HeapTupleIsValid(tup))
2444 {
2445 Oid funcid;
2446
2447 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2449 return funcid;
2450 }
2451 else
2452 return InvalidOid;
2453}
2454
2455Oid
2456get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2457{
2458 HeapTuple tup;
2459
2460 if (!list_member_oid(trftypes, typid))
2461 return InvalidOid;
2462
2464 ObjectIdGetDatum(langid));
2465 if (HeapTupleIsValid(tup))
2466 {
2467 Oid funcid;
2468
2469 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2471 return funcid;
2472 }
2473 else
2474 return InvalidOid;
2475}
2476
2477
2478/* ---------- TYPE CACHE ---------- */
2479
2480/*
2481 * get_typisdefined
2482 *
2483 * Given the type OID, determine whether the type is defined
2484 * (if not, it's only a shell).
2485 */
2486bool
2488{
2489 HeapTuple tp;
2490
2492 if (HeapTupleIsValid(tp))
2493 {
2495 bool result;
2496
2497 result = typtup->typisdefined;
2498 ReleaseSysCache(tp);
2499 return result;
2500 }
2501 else
2502 return false;
2503}
2504
2505/*
2506 * get_typlen
2507 *
2508 * Given the type OID, return the length of the type.
2509 */
2510int16
2512{
2513 HeapTuple tp;
2514
2516 if (HeapTupleIsValid(tp))
2517 {
2519 int16 result;
2520
2521 result = typtup->typlen;
2522 ReleaseSysCache(tp);
2523 return result;
2524 }
2525 else
2526 return 0;
2527}
2528
2529/*
2530 * get_typbyval
2531 *
2532 * Given the type OID, determine whether the type is returned by value or
2533 * not. Returns true if by value, false if by reference.
2534 */
2535bool
2537{
2538 HeapTuple tp;
2539
2541 if (HeapTupleIsValid(tp))
2542 {
2544 bool result;
2545
2546 result = typtup->typbyval;
2547 ReleaseSysCache(tp);
2548 return result;
2549 }
2550 else
2551 return false;
2552}
2553
2554/*
2555 * get_typlenbyval
2556 *
2557 * A two-fer: given the type OID, return both typlen and typbyval.
2558 *
2559 * Since both pieces of info are needed to know how to copy a Datum,
2560 * many places need both. Might as well get them with one cache lookup
2561 * instead of two. Also, this routine raises an error instead of
2562 * returning a bogus value when given a bad type OID.
2563 */
2564void
2565get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2566{
2567 HeapTuple tp;
2569
2571 if (!HeapTupleIsValid(tp))
2572 elog(ERROR, "cache lookup failed for type %u", typid);
2574 *typlen = typtup->typlen;
2575 *typbyval = typtup->typbyval;
2576 ReleaseSysCache(tp);
2577}
2578
2579/*
2580 * get_typlenbyvalalign
2581 *
2582 * A three-fer: given the type OID, return typlen, typbyval, typalign.
2583 */
2584void
2585get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2586 char *typalign)
2587{
2588 HeapTuple tp;
2590
2592 if (!HeapTupleIsValid(tp))
2593 elog(ERROR, "cache lookup failed for type %u", typid);
2595 *typlen = typtup->typlen;
2596 *typbyval = typtup->typbyval;
2597 *typalign = typtup->typalign;
2598 ReleaseSysCache(tp);
2599}
2600
2601/*
2602 * getTypeIOParam
2603 * Given a pg_type row, select the type OID to pass to I/O functions
2604 *
2605 * Formerly, all I/O functions were passed pg_type.typelem as their second
2606 * parameter, but we now have a more complex rule about what to pass.
2607 * This knowledge is intended to be centralized here --- direct references
2608 * to typelem elsewhere in the code are wrong, if they are associated with
2609 * I/O calls and not with actual subscripting operations! (But see
2610 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2611 *
2612 * As of PostgreSQL 8.1, output functions receive only the value itself
2613 * and not any auxiliary parameters, so the name of this routine is now
2614 * a bit of a misnomer ... it should be getTypeInputParam.
2615 */
2616Oid
2618{
2620
2621 /*
2622 * Array types get their typelem as parameter; everybody else gets their
2623 * own type OID as parameter.
2624 */
2625 if (OidIsValid(typeStruct->typelem))
2626 return typeStruct->typelem;
2627 else
2628 return typeStruct->oid;
2629}
2630
2631/*
2632 * get_type_io_data
2633 *
2634 * A six-fer: given the type OID, return typlen, typbyval, typalign,
2635 * typdelim, typioparam, and IO function OID. The IO function
2636 * returned is controlled by IOFuncSelector
2637 */
2638void
2641 int16 *typlen,
2642 bool *typbyval,
2643 char *typalign,
2644 char *typdelim,
2645 Oid *typioparam,
2646 Oid *func)
2647{
2650
2651 /*
2652 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2653 * use array_in and array_out during bootstrap.
2654 */
2656 {
2657 Oid typinput;
2658 Oid typoutput;
2659 Oid typcollation;
2660
2662 typlen,
2663 typbyval,
2664 typalign,
2665 typdelim,
2666 typioparam,
2667 &typinput,
2668 &typoutput,
2669 &typcollation);
2670 switch (which_func)
2671 {
2672 case IOFunc_input:
2673 *func = typinput;
2674 break;
2675 case IOFunc_output:
2676 *func = typoutput;
2677 break;
2678 default:
2679 elog(ERROR, "binary I/O not supported during bootstrap");
2680 break;
2681 }
2682 return;
2683 }
2684
2687 elog(ERROR, "cache lookup failed for type %u", typid);
2689
2690 *typlen = typeStruct->typlen;
2691 *typbyval = typeStruct->typbyval;
2692 *typalign = typeStruct->typalign;
2693 *typdelim = typeStruct->typdelim;
2694 *typioparam = getTypeIOParam(typeTuple);
2695 switch (which_func)
2696 {
2697 case IOFunc_input:
2698 *func = typeStruct->typinput;
2699 break;
2700 case IOFunc_output:
2701 *func = typeStruct->typoutput;
2702 break;
2703 case IOFunc_receive:
2704 *func = typeStruct->typreceive;
2705 break;
2706 case IOFunc_send:
2707 *func = typeStruct->typsend;
2708 break;
2709 }
2711}
2712
2713#ifdef NOT_USED
2714char
2715get_typalign(Oid typid)
2716{
2717 HeapTuple tp;
2718
2720 if (HeapTupleIsValid(tp))
2721 {
2723 char result;
2724
2725 result = typtup->typalign;
2726 ReleaseSysCache(tp);
2727 return result;
2728 }
2729 else
2730 return TYPALIGN_INT;
2731}
2732#endif
2733
2734char
2736{
2737 HeapTuple tp;
2738
2740 if (HeapTupleIsValid(tp))
2741 {
2743 char result;
2744
2745 result = typtup->typstorage;
2746 ReleaseSysCache(tp);
2747 return result;
2748 }
2749 else
2750 return TYPSTORAGE_PLAIN;
2751}
2752
2753/*
2754 * get_typdefault
2755 * Given a type OID, return the type's default value, if any.
2756 *
2757 * The result is a palloc'd expression node tree, or NULL if there
2758 * is no defined default for the datatype.
2759 *
2760 * NB: caller should be prepared to coerce result to correct datatype;
2761 * the returned expression tree might produce something of the wrong type.
2762 */
2763Node *
2765{
2768 Datum datum;
2769 bool isNull;
2770 Node *expr;
2771
2774 elog(ERROR, "cache lookup failed for type %u", typid);
2776
2777 /*
2778 * typdefault and typdefaultbin are potentially null, so don't try to
2779 * access 'em as struct fields. Must do it the hard way with
2780 * SysCacheGetAttr.
2781 */
2782 datum = SysCacheGetAttr(TYPEOID,
2783 typeTuple,
2785 &isNull);
2786
2787 if (!isNull)
2788 {
2789 /* We have an expression default */
2790 expr = stringToNode(TextDatumGetCString(datum));
2791 }
2792 else
2793 {
2794 /* Perhaps we have a plain literal default */
2795 datum = SysCacheGetAttr(TYPEOID,
2796 typeTuple,
2798 &isNull);
2799
2800 if (!isNull)
2801 {
2802 char *strDefaultVal;
2803
2804 /* Convert text datum to C string */
2806 /* Convert C string to a value of the given type */
2807 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2809 /* Build a Const node containing the value */
2810 expr = (Node *) makeConst(typid,
2811 -1,
2812 type->typcollation,
2813 type->typlen,
2814 datum,
2815 false,
2816 type->typbyval);
2818 }
2819 else
2820 {
2821 /* No default */
2822 expr = NULL;
2823 }
2824 }
2825
2827
2828 return expr;
2829}
2830
2831/*
2832 * getBaseType
2833 * If the given type is a domain, return its base type;
2834 * otherwise return the type's own OID.
2835 */
2836Oid
2838{
2839 int32 typmod = -1;
2840
2841 return getBaseTypeAndTypmod(typid, &typmod);
2842}
2843
2844/*
2845 * getBaseTypeAndTypmod
2846 * If the given type is a domain, return its base type and typmod;
2847 * otherwise return the type's own OID, and leave *typmod unchanged.
2848 *
2849 * Note that the "applied typmod" should be -1 for every domain level
2850 * above the bottommost; therefore, if the passed-in typid is indeed
2851 * a domain, *typmod should be -1.
2852 */
2853Oid
2855{
2856 /*
2857 * We loop to find the bottom base type in a stack of domains.
2858 */
2859 for (;;)
2860 {
2861 HeapTuple tup;
2863
2865 if (!HeapTupleIsValid(tup))
2866 elog(ERROR, "cache lookup failed for type %u", typid);
2868 if (typTup->typtype != TYPTYPE_DOMAIN)
2869 {
2870 /* Not a domain, so done */
2872 break;
2873 }
2874
2875 Assert(*typmod == -1);
2876 typid = typTup->typbasetype;
2877 *typmod = typTup->typtypmod;
2878
2880 }
2881
2882 return typid;
2883}
2884
2885/*
2886 * get_typavgwidth
2887 *
2888 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2889 * estimate the average width of values of the type. This is used by
2890 * the planner, which doesn't require absolutely correct results;
2891 * it's OK (and expected) to guess if we don't know for sure.
2892 */
2893int32
2895{
2896 int typlen = get_typlen(typid);
2898
2899 /*
2900 * Easy if it's a fixed-width type
2901 */
2902 if (typlen > 0)
2903 return typlen;
2904
2905 /*
2906 * type_maximum_size knows the encoding of typmod for some datatypes;
2907 * don't duplicate that knowledge here.
2908 */
2909 maxwidth = type_maximum_size(typid, typmod);
2910 if (maxwidth > 0)
2911 {
2912 /*
2913 * For BPCHAR, the max width is also the only width. Otherwise we
2914 * need to guess about the typical data width given the max. A sliding
2915 * scale for percentage of max width seems reasonable.
2916 */
2917 if (typid == BPCHAROID)
2918 return maxwidth;
2919 if (maxwidth <= 32)
2920 return maxwidth; /* assume full width */
2921 if (maxwidth < 1000)
2922 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2923
2924 /*
2925 * Beyond 1000, assume we're looking at something like
2926 * "varchar(10000)" where the limit isn't actually reached often, and
2927 * use a fixed estimate.
2928 */
2929 return 32 + (1000 - 32) / 2;
2930 }
2931
2932 /*
2933 * Oops, we have no idea ... wild guess time.
2934 */
2935 return 32;
2936}
2937
2938/*
2939 * get_typtype
2940 *
2941 * Given the type OID, find if it is a basic type, a complex type, etc.
2942 * It returns the null char if the cache lookup fails...
2943 */
2944char
2946{
2947 HeapTuple tp;
2948
2950 if (HeapTupleIsValid(tp))
2951 {
2953 char result;
2954
2955 result = typtup->typtype;
2956 ReleaseSysCache(tp);
2957 return result;
2958 }
2959 else
2960 return '\0';
2961}
2962
2963/*
2964 * type_is_rowtype
2965 *
2966 * Convenience function to determine whether a type OID represents
2967 * a "rowtype" type --- either RECORD or a named composite type
2968 * (including a domain over a named composite type).
2969 */
2970bool
2972{
2973 if (typid == RECORDOID)
2974 return true; /* easy case */
2975 switch (get_typtype(typid))
2976 {
2977 case TYPTYPE_COMPOSITE:
2978 return true;
2979 case TYPTYPE_DOMAIN:
2981 return true;
2982 break;
2983 default:
2984 break;
2985 }
2986 return false;
2987}
2988
2989/*
2990 * type_is_enum
2991 * Returns true if the given type is an enum type.
2992 */
2993bool
2995{
2996 return (get_typtype(typid) == TYPTYPE_ENUM);
2997}
2998
2999/*
3000 * type_is_range
3001 * Returns true if the given type is a range type.
3002 */
3003bool
3005{
3006 return (get_typtype(typid) == TYPTYPE_RANGE);
3007}
3008
3009/*
3010 * type_is_multirange
3011 * Returns true if the given type is a multirange type.
3012 */
3013bool
3015{
3016 return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
3017}
3018
3019/*
3020 * get_type_category_preferred
3021 *
3022 * Given the type OID, fetch its category and preferred-type status.
3023 * Throws error on failure.
3024 */
3025void
3027{
3028 HeapTuple tp;
3030
3032 if (!HeapTupleIsValid(tp))
3033 elog(ERROR, "cache lookup failed for type %u", typid);
3035 *typcategory = typtup->typcategory;
3036 *typispreferred = typtup->typispreferred;
3037 ReleaseSysCache(tp);
3038}
3039
3040/*
3041 * get_typ_typrelid
3042 *
3043 * Given the type OID, get the typrelid (InvalidOid if not a complex
3044 * type).
3045 */
3046Oid
3048{
3049 HeapTuple tp;
3050
3052 if (HeapTupleIsValid(tp))
3053 {
3055 Oid result;
3056
3057 result = typtup->typrelid;
3058 ReleaseSysCache(tp);
3059 return result;
3060 }
3061 else
3062 return InvalidOid;
3063}
3064
3065/*
3066 * get_element_type
3067 *
3068 * Given the type OID, get the typelem (InvalidOid if not an array type).
3069 *
3070 * NB: this only succeeds for "true" arrays having array_subscript_handler
3071 * as typsubscript. For other types, InvalidOid is returned independently
3072 * of whether they have typelem or typsubscript set.
3073 */
3074Oid
3076{
3077 HeapTuple tp;
3078
3080 if (HeapTupleIsValid(tp))
3081 {
3083 Oid result;
3084
3086 result = typtup->typelem;
3087 else
3089 ReleaseSysCache(tp);
3090 return result;
3091 }
3092 else
3093 return InvalidOid;
3094}
3095
3096/*
3097 * get_array_type
3098 *
3099 * Given the type OID, get the corresponding "true" array type.
3100 * Returns InvalidOid if no array type can be found.
3101 */
3102Oid
3104{
3105 HeapTuple tp;
3107
3109 if (HeapTupleIsValid(tp))
3110 {
3111 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
3112 ReleaseSysCache(tp);
3113 }
3114 return result;
3115}
3116
3117/*
3118 * get_promoted_array_type
3119 *
3120 * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
3121 * construct, that is, either the corresponding "true" array type
3122 * if the input is a scalar type that has such an array type,
3123 * or the same type if the input is already a "true" array type.
3124 * Returns InvalidOid if neither rule is satisfied.
3125 */
3126Oid
3128{
3129 Oid array_type = get_array_type(typid);
3130
3131 if (OidIsValid(array_type))
3132 return array_type;
3133 if (OidIsValid(get_element_type(typid)))
3134 return typid;
3135 return InvalidOid;
3136}
3137
3138/*
3139 * get_base_element_type
3140 * Given the type OID, get the typelem, looking "through" any domain
3141 * to its underlying array type.
3142 *
3143 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
3144 * an extra cache lookup. Note that it fails to provide any information
3145 * about the typmod of the array.
3146 */
3147Oid
3149{
3150 /*
3151 * We loop to find the bottom base type in a stack of domains.
3152 */
3153 for (;;)
3154 {
3155 HeapTuple tup;
3157
3159 if (!HeapTupleIsValid(tup))
3160 break;
3162 if (typTup->typtype != TYPTYPE_DOMAIN)
3163 {
3164 /* Not a domain, so stop descending */
3165 Oid result;
3166
3167 /* This test must match get_element_type */
3169 result = typTup->typelem;
3170 else
3173 return result;
3174 }
3175
3176 typid = typTup->typbasetype;
3178 }
3179
3180 /* Like get_element_type, silently return InvalidOid for bogus input */
3181 return InvalidOid;
3182}
3183
3184/*
3185 * getTypeInputInfo
3186 *
3187 * Get info needed for converting values of a type to internal form
3188 */
3189void
3191{
3194
3197 elog(ERROR, "cache lookup failed for type %u", type);
3199
3200 if (!pt->typisdefined)
3201 ereport(ERROR,
3203 errmsg("type %s is only a shell",
3204 format_type_be(type))));
3205 if (!OidIsValid(pt->typinput))
3206 ereport(ERROR,
3208 errmsg("no input function available for type %s",
3209 format_type_be(type))));
3210
3211 *typInput = pt->typinput;
3213
3215}
3216
3217/*
3218 * getTypeOutputInfo
3219 *
3220 * Get info needed for printing values of a type
3221 */
3222void
3224{
3227
3230 elog(ERROR, "cache lookup failed for type %u", type);
3232
3233 if (!pt->typisdefined)
3234 ereport(ERROR,
3236 errmsg("type %s is only a shell",
3237 format_type_be(type))));
3238 if (!OidIsValid(pt->typoutput))
3239 ereport(ERROR,
3241 errmsg("no output function available for type %s",
3242 format_type_be(type))));
3243
3244 *typOutput = pt->typoutput;
3245 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3246
3248}
3249
3250/*
3251 * getTypeBinaryInputInfo
3252 *
3253 * Get info needed for binary input of values of a type
3254 */
3255void
3257{
3260
3263 elog(ERROR, "cache lookup failed for type %u", type);
3265
3266 if (!pt->typisdefined)
3267 ereport(ERROR,
3269 errmsg("type %s is only a shell",
3270 format_type_be(type))));
3271 if (!OidIsValid(pt->typreceive))
3272 ereport(ERROR,
3274 errmsg("no binary input function available for type %s",
3275 format_type_be(type))));
3276
3277 *typReceive = pt->typreceive;
3279
3281}
3282
3283/*
3284 * getTypeBinaryOutputInfo
3285 *
3286 * Get info needed for binary output of values of a type
3287 */
3288void
3290{
3293
3296 elog(ERROR, "cache lookup failed for type %u", type);
3298
3299 if (!pt->typisdefined)
3300 ereport(ERROR,
3302 errmsg("type %s is only a shell",
3303 format_type_be(type))));
3304 if (!OidIsValid(pt->typsend))
3305 ereport(ERROR,
3307 errmsg("no binary output function available for type %s",
3308 format_type_be(type))));
3309
3310 *typSend = pt->typsend;
3311 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3312
3314}
3315
3316/*
3317 * get_typmodin
3318 *
3319 * Given the type OID, return the type's typmodin procedure, if any.
3320 */
3321Oid
3323{
3324 HeapTuple tp;
3325
3327 if (HeapTupleIsValid(tp))
3328 {
3330 Oid result;
3331
3332 result = typtup->typmodin;
3333 ReleaseSysCache(tp);
3334 return result;
3335 }
3336 else
3337 return InvalidOid;
3338}
3339
3340#ifdef NOT_USED
3341/*
3342 * get_typmodout
3343 *
3344 * Given the type OID, return the type's typmodout procedure, if any.
3345 */
3346Oid
3347get_typmodout(Oid typid)
3348{
3349 HeapTuple tp;
3350
3352 if (HeapTupleIsValid(tp))
3353 {
3355 Oid result;
3356
3357 result = typtup->typmodout;
3358 ReleaseSysCache(tp);
3359 return result;
3360 }
3361 else
3362 return InvalidOid;
3363}
3364#endif /* NOT_USED */
3365
3366/*
3367 * get_typcollation
3368 *
3369 * Given the type OID, return the type's typcollation attribute.
3370 */
3371Oid
3373{
3374 HeapTuple tp;
3375
3377 if (HeapTupleIsValid(tp))
3378 {
3380 Oid result;
3381
3382 result = typtup->typcollation;
3383 ReleaseSysCache(tp);
3384 return result;
3385 }
3386 else
3387 return InvalidOid;
3388}
3389
3390
3391/*
3392 * type_is_collatable
3393 *
3394 * Return whether the type cares about collations
3395 */
3396bool
3398{
3399 return OidIsValid(get_typcollation(typid));
3400}
3401
3402
3403/*
3404 * get_typsubscript
3405 *
3406 * Given the type OID, return the type's subscripting handler's OID,
3407 * if it has one.
3408 *
3409 * If typelemp isn't NULL, we also store the type's typelem value there.
3410 * This saves some callers an extra catalog lookup.
3411 */
3414{
3415 HeapTuple tp;
3416
3418 if (HeapTupleIsValid(tp))
3419 {
3421 RegProcedure handler = typform->typsubscript;
3422
3423 if (typelemp)
3424 *typelemp = typform->typelem;
3425 ReleaseSysCache(tp);
3426 return handler;
3427 }
3428 else
3429 {
3430 if (typelemp)
3432 return InvalidOid;
3433 }
3434}
3435
3436/*
3437 * getSubscriptingRoutines
3438 *
3439 * Given the type OID, fetch the type's subscripting methods struct.
3440 * Return NULL if type is not subscriptable.
3441 *
3442 * If typelemp isn't NULL, we also store the type's typelem value there.
3443 * This saves some callers an extra catalog lookup.
3444 */
3445const struct SubscriptRoutines *
3447{
3448 RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3449
3450 if (!OidIsValid(typsubscript))
3451 return NULL;
3452
3453 return (const struct SubscriptRoutines *)
3454 DatumGetPointer(OidFunctionCall0(typsubscript));
3455}
3456
3457
3458/* ---------- STATISTICS CACHE ---------- */
3459
3460/*
3461 * get_attavgwidth
3462 *
3463 * Given the table and attribute number of a column, get the average
3464 * width of entries in the column. Return zero if no data available.
3465 *
3466 * Currently this is only consulted for individual tables, not for inheritance
3467 * trees, so we don't need an "inh" parameter.
3468 *
3469 * Calling a hook at this point looks somewhat strange, but is required
3470 * because the optimizer calls this function without any other way for
3471 * plug-ins to control the result.
3472 */
3473int32
3475{
3476 HeapTuple tp;
3477 int32 stawidth;
3478
3480 {
3481 stawidth = (*get_attavgwidth_hook) (relid, attnum);
3482 if (stawidth > 0)
3483 return stawidth;
3484 }
3486 ObjectIdGetDatum(relid),
3488 BoolGetDatum(false));
3489 if (HeapTupleIsValid(tp))
3490 {
3491 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3492 ReleaseSysCache(tp);
3493 if (stawidth > 0)
3494 return stawidth;
3495 }
3496 return 0;
3497}
3498
3499/*
3500 * get_attstatsslot
3501 *
3502 * Extract the contents of a "slot" of a pg_statistic tuple.
3503 * Returns true if requested slot type was found, else false.
3504 *
3505 * Unlike other routines in this file, this takes a pointer to an
3506 * already-looked-up tuple in the pg_statistic cache. We do this since
3507 * most callers will want to extract more than one value from the cache
3508 * entry, and we don't want to repeat the cache lookup unnecessarily.
3509 * Also, this API allows this routine to be used with statistics tuples
3510 * that have been provided by a stats hook and didn't really come from
3511 * pg_statistic.
3512 *
3513 * sslot: pointer to output area (typically, a local variable in the caller).
3514 * statstuple: pg_statistic tuple to be examined.
3515 * reqkind: STAKIND code for desired statistics slot kind.
3516 * reqop: STAOP value wanted, or InvalidOid if don't care.
3517 * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3518 *
3519 * If a matching slot is found, true is returned, and *sslot is filled thus:
3520 * staop: receives the actual STAOP value.
3521 * stacoll: receives the actual STACOLL value.
3522 * valuetype: receives actual datatype of the elements of stavalues.
3523 * values: receives pointer to an array of the slot's stavalues.
3524 * nvalues: receives number of stavalues.
3525 * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3526 * nnumbers: receives number of stanumbers.
3527 *
3528 * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3529 * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3530 * ATTSTATSSLOT_NUMBERS wasn't specified.
3531 *
3532 * If no matching slot is found, false is returned, and *sslot is zeroed.
3533 *
3534 * Note that the current API doesn't allow for searching for a slot with
3535 * a particular collation. If we ever actually support recording more than
3536 * one collation, we'll have to extend the API, but for now simple is good.
3537 *
3538 * The data referred to by the fields of sslot is locally palloc'd and
3539 * is independent of the original pg_statistic tuple. When the caller
3540 * is done with it, call free_attstatsslot to release the palloc'd data.
3541 *
3542 * If it's desirable to call free_attstatsslot when get_attstatsslot might
3543 * not have been called, memset'ing sslot to zeroes will allow that.
3544 *
3545 * Passing flags=0 can be useful to quickly check if the requested slot type
3546 * exists. In this case no arrays are extracted, so free_attstatsslot need
3547 * not be called.
3548 */
3549bool
3551 int reqkind, Oid reqop, int flags)
3552{
3554 int i;
3555 Datum val;
3558 int narrayelem;
3561
3562 /* initialize *sslot properly */
3563 memset(sslot, 0, sizeof(AttStatsSlot));
3564
3565 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3566 {
3567 if ((&stats->stakind1)[i] == reqkind &&
3568 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3569 break;
3570 }
3571 if (i >= STATISTIC_NUM_SLOTS)
3572 return false; /* not there */
3573
3574 sslot->staop = (&stats->staop1)[i];
3575 sslot->stacoll = (&stats->stacoll1)[i];
3576
3577 if (flags & ATTSTATSSLOT_VALUES)
3578 {
3581
3582 /*
3583 * Detoast the array if needed, and in any case make a copy that's
3584 * under control of this AttStatsSlot.
3585 */
3587
3588 /*
3589 * Extract the actual array element type, and pass it back in case the
3590 * caller needs it.
3591 */
3592 sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3593
3594 /* Need info about element type */
3597 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3599
3600 /* Deconstruct array into Datum elements; NULLs not expected */
3603 typeForm->typlen,
3604 typeForm->typbyval,
3605 typeForm->typalign,
3606 &sslot->values, NULL, &sslot->nvalues);
3607
3608 /*
3609 * If the element type is pass-by-reference, we now have a bunch of
3610 * Datums that are pointers into the statarray, so we need to keep
3611 * that until free_attstatsslot. Otherwise, all the useful info is in
3612 * sslot->values[], so we can free the array object immediately.
3613 */
3614 if (!typeForm->typbyval)
3615 sslot->values_arr = statarray;
3616 else
3618
3620 }
3621
3622 if (flags & ATTSTATSSLOT_NUMBERS)
3623 {
3626
3627 /*
3628 * Detoast the array if needed, and in any case make a copy that's
3629 * under control of this AttStatsSlot.
3630 */
3632
3633 /*
3634 * We expect the array to be a 1-D float4 array; verify that. We don't
3635 * need to use deconstruct_array() since the array data is just going
3636 * to look like a C array of float4 values.
3637 */
3639 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3642 elog(ERROR, "stanumbers is not a 1-D float4 array");
3643
3644 /* Give caller a pointer directly into the statarray */
3645 sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3646 sslot->nnumbers = narrayelem;
3647
3648 /* We'll free the statarray in free_attstatsslot */
3649 sslot->numbers_arr = statarray;
3650 }
3651
3652 return true;
3653}
3654
3655/*
3656 * free_attstatsslot
3657 * Free data allocated by get_attstatsslot
3658 */
3659void
3661{
3662 /* The values[] array was separately palloc'd by deconstruct_array */
3663 if (sslot->values)
3664 pfree(sslot->values);
3665 /* The numbers[] array points into numbers_arr, do not pfree it */
3666 /* Free the detoasted array objects, if any */
3667 if (sslot->values_arr)
3668 pfree(sslot->values_arr);
3669 if (sslot->numbers_arr)
3670 pfree(sslot->numbers_arr);
3671}
3672
3673/* ---------- PG_NAMESPACE CACHE ---------- */
3674
3675/*
3676 * get_namespace_name
3677 * Returns the name of a given namespace
3678 *
3679 * Returns a palloc'd copy of the string, or NULL if no such namespace.
3680 */
3681char *
3683{
3684 HeapTuple tp;
3685
3687 if (HeapTupleIsValid(tp))
3688 {
3690 char *result;
3691
3692 result = pstrdup(NameStr(nsptup->nspname));
3693 ReleaseSysCache(tp);
3694 return result;
3695 }
3696 else
3697 return NULL;
3698}
3699
3700/*
3701 * get_namespace_name_or_temp
3702 * As above, but if it is this backend's temporary namespace, return
3703 * "pg_temp" instead.
3704 */
3705char *
3707{
3709 return pstrdup("pg_temp");
3710 else
3711 return get_namespace_name(nspid);
3712}
3713
3714/*
3715 * get_qualified_objname
3716 * Returns a palloc'd string containing the schema-qualified name of the
3717 * object for the given namespace ID and object name.
3718 */
3719char *
3721{
3722 char *nspname;
3723 char *result;
3724
3726 if (!nspname)
3727 elog(ERROR, "cache lookup failed for namespace %u", nspid);
3728
3729 result = quote_qualified_identifier(nspname, objname);
3730
3731 return result;
3732}
3733
3734/* ---------- PG_RANGE CACHES ---------- */
3735
3736/*
3737 * get_range_subtype
3738 * Returns the subtype of a given range type
3739 *
3740 * Returns InvalidOid if the type is not a range type.
3741 */
3742Oid
3744{
3745 HeapTuple tp;
3746
3748 if (HeapTupleIsValid(tp))
3749 {
3751 Oid result;
3752
3753 result = rngtup->rngsubtype;
3754 ReleaseSysCache(tp);
3755 return result;
3756 }
3757 else
3758 return InvalidOid;
3759}
3760
3761/*
3762 * get_range_collation
3763 * Returns the collation of a given range type
3764 *
3765 * Returns InvalidOid if the type is not a range type,
3766 * or if its subtype is not collatable.
3767 */
3768Oid
3770{
3771 HeapTuple tp;
3772
3774 if (HeapTupleIsValid(tp))
3775 {
3777 Oid result;
3778
3779 result = rngtup->rngcollation;
3780 ReleaseSysCache(tp);
3781 return result;
3782 }
3783 else
3784 return InvalidOid;
3785}
3786
3787/*
3788 * get_range_constructor2
3789 * Gets the 2-arg constructor for the given rangetype.
3790 *
3791 * Raises an error if not found.
3792 */
3795{
3796 HeapTuple tp;
3797
3799 if (HeapTupleIsValid(tp))
3800 {
3803
3804 result = rngtup->rngconstruct2;
3805 ReleaseSysCache(tp);
3806 return result;
3807 }
3808 else
3809 elog(ERROR, "cache lookup failed for range type %u", rangeOid);
3810}
3811
3812/*
3813 * get_range_multirange
3814 * Returns the multirange type of a given range type
3815 *
3816 * Returns InvalidOid if the type is not a range type.
3817 */
3818Oid
3820{
3821 HeapTuple tp;
3822
3824 if (HeapTupleIsValid(tp))
3825 {
3827 Oid result;
3828
3829 result = rngtup->rngmultitypid;
3830 ReleaseSysCache(tp);
3831 return result;
3832 }
3833 else
3834 return InvalidOid;
3835}
3836
3837/*
3838 * get_multirange_range
3839 * Returns the range type of a given multirange
3840 *
3841 * Returns InvalidOid if the type is not a multirange.
3842 */
3843Oid
3845{
3846 HeapTuple tp;
3847
3849 if (HeapTupleIsValid(tp))
3850 {
3852 Oid result;
3853
3854 result = rngtup->rngtypid;
3855 ReleaseSysCache(tp);
3856 return result;
3857 }
3858 else
3859 return InvalidOid;
3860}
3861
3862/* ---------- PG_INDEX CACHE ---------- */
3863
3864/*
3865 * get_index_column_opclass
3866 *
3867 * Given the index OID and column number,
3868 * return opclass of the index column
3869 * or InvalidOid if the index was not found
3870 * or column is non-key one.
3871 */
3872Oid
3874{
3875 HeapTuple tuple;
3876 Form_pg_index rd_index;
3877 Datum datum;
3879 Oid opclass;
3880
3881 /* First we need to know the column's opclass. */
3882
3884 if (!HeapTupleIsValid(tuple))
3885 return InvalidOid;
3886
3887 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3888
3889 /* caller is supposed to guarantee this */
3890 Assert(attno > 0 && attno <= rd_index->indnatts);
3891
3892 /* Non-key attributes don't have an opclass */
3893 if (attno > rd_index->indnkeyatts)
3894 {
3895 ReleaseSysCache(tuple);
3896 return InvalidOid;
3897 }
3898
3900 indclass = ((oidvector *) DatumGetPointer(datum));
3901
3903 opclass = indclass->values[attno - 1];
3904
3905 ReleaseSysCache(tuple);
3906
3907 return opclass;
3908}
3909
3910/*
3911 * get_index_isreplident
3912 *
3913 * Given the index OID, return pg_index.indisreplident.
3914 */
3915bool
3917{
3918 HeapTuple tuple;
3919 Form_pg_index rd_index;
3920 bool result;
3921
3923 if (!HeapTupleIsValid(tuple))
3924 return false;
3925
3926 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3927 result = rd_index->indisreplident;
3928 ReleaseSysCache(tuple);
3929
3930 return result;
3931}
3932
3933/*
3934 * get_index_isvalid
3935 *
3936 * Given the index OID, return pg_index.indisvalid.
3937 */
3938bool
3940{
3941 bool isvalid;
3942 HeapTuple tuple;
3943 Form_pg_index rd_index;
3944
3946 if (!HeapTupleIsValid(tuple))
3947 elog(ERROR, "cache lookup failed for index %u", index_oid);
3948
3949 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3950 isvalid = rd_index->indisvalid;
3951 ReleaseSysCache(tuple);
3952
3953 return isvalid;
3954}
3955
3956/*
3957 * get_index_isclustered
3958 *
3959 * Given the index OID, return pg_index.indisclustered.
3960 */
3961bool
3963{
3964 bool isclustered;
3965 HeapTuple tuple;
3966 Form_pg_index rd_index;
3967
3969 if (!HeapTupleIsValid(tuple))
3970 elog(ERROR, "cache lookup failed for index %u", index_oid);
3971
3972 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3973 isclustered = rd_index->indisclustered;
3974 ReleaseSysCache(tuple);
3975
3976 return isclustered;
3977}
3978
3979/*
3980 * get_publication_oid - given a publication name, look up the OID
3981 *
3982 * If missing_ok is false, throw an error if name not found. If true, just
3983 * return InvalidOid.
3984 */
3985Oid
3986get_publication_oid(const char *pubname, bool missing_ok)
3987{
3988 Oid oid;
3989
3991 CStringGetDatum(pubname));
3992 if (!OidIsValid(oid) && !missing_ok)
3993 ereport(ERROR,
3995 errmsg("publication \"%s\" does not exist", pubname)));
3996 return oid;
3997}
3998
3999/*
4000 * get_publication_name - given a publication Oid, look up the name
4001 *
4002 * If missing_ok is false, throw an error if name not found. If true, just
4003 * return NULL.
4004 */
4005char *
4006get_publication_name(Oid pubid, bool missing_ok)
4007{
4008 HeapTuple tup;
4009 char *pubname;
4011
4013
4014 if (!HeapTupleIsValid(tup))
4015 {
4016 if (!missing_ok)
4017 elog(ERROR, "cache lookup failed for publication %u", pubid);
4018 return NULL;
4019 }
4020
4022 pubname = pstrdup(NameStr(pubform->pubname));
4023
4025
4026 return pubname;
4027}
4028
4029/*
4030 * get_subscription_oid - given a subscription name, look up the OID
4031 *
4032 * If missing_ok is false, throw an error if name not found. If true, just
4033 * return InvalidOid.
4034 */
4035Oid
4036get_subscription_oid(const char *subname, bool missing_ok)
4037{
4038 Oid oid;
4039
4042 if (!OidIsValid(oid) && !missing_ok)
4043 ereport(ERROR,
4045 errmsg("subscription \"%s\" does not exist", subname)));
4046 return oid;
4047}
4048
4049/*
4050 * get_subscription_name - given a subscription OID, look up the name
4051 *
4052 * If missing_ok is false, throw an error if name not found. If true, just
4053 * return NULL.
4054 */
4055char *
4056get_subscription_name(Oid subid, bool missing_ok)
4057{
4058 HeapTuple tup;
4059 char *subname;
4061
4063
4064 if (!HeapTupleIsValid(tup))
4065 {
4066 if (!missing_ok)
4067 elog(ERROR, "cache lookup failed for subscription %u", subid);
4068 return NULL;
4069 }
4070
4072 subname = pstrdup(NameStr(subform->subname));
4073
4075
4076 return subname;
4077}
4078
4079char *
4081{
4082 HeapTuple tuple;
4083 char *labelname;
4084
4086 if (!tuple)
4087 {
4088 elog(ERROR, "cache lookup failed for label %u", labeloid);
4089 return NULL;
4090 }
4092 ReleaseSysCache(tuple);
4093
4094 return labelname;
4095}
4096
4097char *
4099{
4100 HeapTuple tuple;
4101 char *propname;
4102
4104 if (!tuple)
4105 {
4106 elog(ERROR, "cache lookup failed for property %u", propoid);
4107 return NULL;
4108 }
4110 ReleaseSysCache(tuple);
4111
4112 return propname;
4113}
const IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition amapi.c:69
StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
Definition amapi.c:161
CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok)
Definition amapi.c:131
#define DatumGetArrayTypePCopy(X)
Definition array.h:262
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
void boot_get_type_io_data(Oid typid, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *typinput, Oid *typoutput, Oid *typcollation)
Definition bootstrap.c:1011
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:894
#define Assert(condition)
Definition c.h:1002
int16_t int16
Definition c.h:678
regproc RegProcedure
Definition c.h:793
int32_t int32
Definition c.h:679
float float4
Definition c.h:772
#define OidIsValid(objectId)
Definition c.h:917
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
CompareType
Definition cmptype.h:32
@ COMPARE_INVALID
Definition cmptype.h:33
@ COMPARE_GT
Definition cmptype.h:38
@ COMPARE_EQ
Definition cmptype.h:36
@ COMPARE_NE
Definition cmptype.h:39
@ COMPARE_LT
Definition cmptype.h:34
int nspid
Oid collid
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_object(type)
Definition fe_memutils.h:89
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
Definition fmgr.c:1755
#define OidFunctionCall0(functionId)
Definition fmgr.h:724
int32 type_maximum_size(Oid type_oid, int32 typemod)
char * format_type_be(Oid type_oid)
Oid MyDatabaseId
Definition globals.c:96
#define HASHSTANDARD_PROC
Definition hash.h:355
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
long val
Definition informix.c:689
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
Oid get_range_subtype(Oid rangeOid)
Definition lsyscache.c:3743
char * get_rel_name(Oid relid)
Definition lsyscache.c:2242
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:140
Oid get_func_variadictype(Oid funcid)
Definition lsyscache.c:2037
Oid get_opclass_method(Oid opclass)
Definition lsyscache.c:1512
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition lsyscache.c:483
bool get_rel_relispartition(Oid relid)
Definition lsyscache.c:2341
char * get_propgraph_property_name(Oid propoid)
Definition lsyscache.c:4098
Oid get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
Definition lsyscache.c:112
bool collations_agree_on_equality(Oid coll1, Oid coll2)
Definition lsyscache.c:954
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2392
char get_func_prokind(Oid funcid)
Definition lsyscache.c:2132
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3939
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition lsyscache.c:1233
RegProcedure get_range_constructor2(Oid rangeOid)
Definition lsyscache.c:3794
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition lsyscache.c:3289
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:1084
RegProcedure get_oprrest(Oid opno)
Definition lsyscache.c:1871
void free_attstatsslot(AttStatsSlot *sslot)
Definition lsyscache.c:3660
bool comparison_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:893
Oid get_constraint_index(Oid conoid)
Definition lsyscache.c:1339
bool get_func_retset(Oid funcid)
Definition lsyscache.c:2056
bool get_ordering_op_properties(Oid opno, Oid *opfamily, Oid *opcintype, CompareType *cmptype)
Definition lsyscache.c:261
Oid get_element_type(Oid typid)
Definition lsyscache.c:3075
Oid get_opclass_input_type(Oid opclass)
Definition lsyscache.c:1464
bool type_is_rowtype(Oid typid)
Definition lsyscache.c:2971
bool type_is_range(Oid typid)
Definition lsyscache.c:3004
char func_parallel(Oid funcid)
Definition lsyscache.c:2113
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1442
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1114
bool type_is_enum(Oid typid)
Definition lsyscache.c:2994
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3844
Oid get_typmodin(Oid typid)
Definition lsyscache.c:3322
Oid get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, CompareType cmptype)
Definition lsyscache.c:199
char get_typstorage(Oid typid)
Definition lsyscache.c:2735
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition lsyscache.c:1487
RegProcedure get_func_support(Oid funcid)
Definition lsyscache.c:2172
char * get_database_name(Oid dbid)
Definition lsyscache.c:1392
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3223
bool get_typisdefined(Oid typid)
Definition lsyscache.c:2487
char * get_opname(Oid opno)
Definition lsyscache.c:1610
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1196
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2585
int32 get_attavgwidth(Oid relid, AttrNumber attnum)
Definition lsyscache.c:3474
bool get_index_isreplident(Oid index_oid)
Definition lsyscache.c:3916
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:1022
RegProcedure get_oprjoin(Oid opno)
Definition lsyscache.c:1895
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition lsyscache.c:326
bool op_strict(Oid opno)
Definition lsyscache.c:1791
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1739
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2317
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2565
Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
Definition lsyscache.c:2010
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition lsyscache.c:3986
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2266
static bool get_opmethod_canorder(Oid amoid)
Definition lsyscache.c:223
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1585
Oid get_typcollation(Oid typid)
Definition lsyscache.c:3372
Oid get_op_rettype(Oid opno)
Definition lsyscache.c:1633
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:87
char * get_collation_name(Oid colloid)
Definition lsyscache.c:1261
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2293
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1413
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3706
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3190
char func_volatile(Oid funcid)
Definition lsyscache.c:2094
bool equality_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:841
get_attavgwidth_hook_type get_attavgwidth_hook
Definition lsyscache.c:57
bool op_is_safe_index_member(Oid opno)
Definition lsyscache.c:980
bool get_index_isclustered(Oid index_oid)
Definition lsyscache.c:3962
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:170
char * get_propgraph_label_name(Oid labeloid)
Definition lsyscache.c:4080
Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
Definition lsyscache.c:364
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition lsyscache.c:2456
bool func_strict(Oid funcid)
Definition lsyscache.c:2075
Oid get_index_column_opclass(Oid index_oid, int attno)
Definition lsyscache.c:3873
bool get_op_hash_functions_ext(Oid opno, Oid inputtype, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:677
char * get_constraint_name(Oid conoid)
Definition lsyscache.c:1307
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1053
bool get_func_leakproof(Oid funcid)
Definition lsyscache.c:2151
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition lsyscache.c:3446
Node * get_typdefault(Oid typid)
Definition lsyscache.c:2764
bool get_collation_isdeterministic(Oid colloid)
Definition lsyscache.c:1280
List * get_op_index_interpretation(Oid opno)
Definition lsyscache.c:729
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition lsyscache.c:4036
char * get_subscription_name(Oid subid, bool missing_ok)
Definition lsyscache.c:4056
Oid get_range_collation(Oid rangeOid)
Definition lsyscache.c:3769
char * get_opfamily_name(Oid opfid, bool missing_ok)
Definition lsyscache.c:1553
char * get_func_name(Oid funcid)
Definition lsyscache.c:1922
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3819
Oid get_rel_relam(Oid relid)
Definition lsyscache.c:2414
char op_volatile(Oid opno)
Definition lsyscache.c:1807
Oid get_func_namespace(Oid funcid)
Definition lsyscache.c:1946
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3397
Oid get_rel_tablespace(Oid relid)
Definition lsyscache.c:2368
int get_func_nargs(Oid funcid)
Definition lsyscache.c:1988
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition lsyscache.c:2639
int16 get_typlen(Oid typid)
Definition lsyscache.c:2511
Oid get_typ_typrelid(Oid typid)
Definition lsyscache.c:3047
char get_typtype(Oid typid)
Definition lsyscache.c:2945
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:3148
Oid getTypeIOParam(HeapTuple typeTuple)
Definition lsyscache.c:2617
Oid get_opfamily_method(Oid opfid)
Definition lsyscache.c:1536
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition lsyscache.c:2854
char * get_qualified_objname(Oid nspid, char *objname)
Definition lsyscache.c:3720
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition lsyscache.c:2434
char * get_publication_name(Oid pubid, bool missing_ok)
Definition lsyscache.c:4006
Oid getBaseType(Oid typid)
Definition lsyscache.c:2837
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:589
bool get_typbyval(Oid typid)
Definition lsyscache.c:2536
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1686
List * get_mergejoin_opfamilies(Oid opno)
Definition lsyscache.c:430
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3682
Oid get_array_type(Oid typid)
Definition lsyscache.c:3103
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1969
Oid get_promoted_array_type(Oid typid)
Definition lsyscache.c:3127
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1139
char get_constraint_type(Oid conoid)
Definition lsyscache.c:1369
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition lsyscache.c:2894
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition lsyscache.c:70
RegProcedure get_typsubscript(Oid typid, Oid *typelemp)
Definition lsyscache.c:3413
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
Definition lsyscache.c:3026
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition lsyscache.c:3550
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2199
Oid get_negator(Oid opno)
Definition lsyscache.c:1847
Oid get_commutator(Oid opno)
Definition lsyscache.c:1823
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:1658
bool type_is_multirange(Oid typid)
Definition lsyscache.c:3014
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition lsyscache.c:3256
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition lsyscache.c:1169
#define ATTSTATSSLOT_NUMBERS
Definition lsyscache.h:44
#define ATTSTATSSLOT_VALUES
Definition lsyscache.h:43
IOFuncSelector
Definition lsyscache.h:35
@ IOFunc_output
Definition lsyscache.h:37
@ IOFunc_input
Definition lsyscache.h:36
@ IOFunc_send
Definition lsyscache.h:39
@ IOFunc_receive
Definition lsyscache.h:38
int32(* get_attavgwidth_hook_type)(Oid relid, AttrNumber attnum)
Definition lsyscache.h:66
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc(Size size)
Definition mcxt.c:1390
#define IsBootstrapProcessingMode()
Definition miscadmin.h:486
bool isTempNamespace(Oid namespaceId)
Definition namespace.c:3721
static char * errmsg
END_CATALOG_STRUCT typedef FormData_pg_amop * Form_pg_amop
Definition pg_amop.h:92
END_CATALOG_STRUCT typedef FormData_pg_amproc * Form_pg_amproc
Definition pg_amproc.h:72
NameData attname
int16 attnum
FormData_pg_attribute * Form_pg_attribute
NameData relname
Definition pg_class.h:40
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
END_CATALOG_STRUCT typedef FormData_pg_collation * Form_pg_collation
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
NameData datname
Definition pg_database.h:37
END_CATALOG_STRUCT typedef FormData_pg_database * Form_pg_database
END_CATALOG_STRUCT typedef FormData_pg_index * Form_pg_index
Definition pg_index.h:74
END_CATALOG_STRUCT typedef FormData_pg_language * Form_pg_language
Definition pg_language.h:69
#define NIL
Definition pg_list.h:68
END_CATALOG_STRUCT typedef FormData_pg_namespace * Form_pg_namespace
END_CATALOG_STRUCT typedef FormData_pg_opclass * Form_pg_opclass
Definition pg_opclass.h:87
END_CATALOG_STRUCT typedef FormData_pg_operator * Form_pg_operator
Definition pg_operator.h:87
END_CATALOG_STRUCT typedef FormData_pg_opfamily * Form_pg_opfamily
Definition pg_opfamily.h:55
int16 pronargs
Definition pg_proc.h:83
END_CATALOG_STRUCT typedef FormData_pg_proc * Form_pg_proc
Definition pg_proc.h:140
END_CATALOG_STRUCT typedef FormData_pg_propgraph_label * Form_pg_propgraph_label
END_CATALOG_STRUCT typedef FormData_pg_propgraph_property * Form_pg_propgraph_property
END_CATALOG_STRUCT typedef FormData_pg_publication * Form_pg_publication
END_CATALOG_STRUCT typedef FormData_pg_range * Form_pg_range
Definition pg_range.h:71
#define STATISTIC_NUM_SLOTS
FormData_pg_statistic * Form_pg_statistic
NameData subname
END_CATALOG_STRUCT typedef FormData_pg_subscription * Form_pg_subscription
END_CATALOG_STRUCT typedef FormData_pg_transform * Form_pg_transform
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
char typalign
Definition pg_type.h:178
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#define PointerGetDatum(X)
Definition postgres.h:354
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
unsigned int Oid
static int fb(int x)
void * stringToNode(const char *str)
Definition read.c:90
char * quote_qualified_identifier(const char *qualifier, const char *ident)
uint16 StrategyNumber
Definition stratnum.h:22
#define HTEqualStrategyNumber
Definition stratnum.h:41
bool amconsistentordering
Definition amapi.h:255
bool amcanorder
Definition amapi.h:247
bool amconsistentequality
Definition amapi.h:253
Definition pg_list.h:54
Definition nodes.h:133
Definition c.h:874
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
HeapTuple SearchSysCache3(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3)
Definition syscache.c:241
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition syscache.c:476
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
HeapTuple SearchSysCache4(SysCacheIdentifier cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition syscache.c:251
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
#define ReleaseSysCacheList(x)
Definition syscache.h:134
#define SearchSysCacheList1(cacheId, key1)
Definition syscache.h:127
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition syscache.h:104
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition syscache.h:109
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_CMP_PROC
Definition typcache.h:141
#define TYPECACHE_HASH_PROC
Definition typcache.h:142
const char * type