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 equality operators have compatible
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. (The reason we need
830 * to do these pushups is that one might be a cross-type operator; for
831 * instance int24eq vs int4eq.)
832 */
833bool
835{
836 bool result;
838 int i;
839
840 /* Easy if they're the same operator */
841 if (opno1 == opno2)
842 return true;
843
844 /*
845 * We search through all the pg_amop entries for opno1.
846 */
848
849 result = false;
850 for (i = 0; i < catlist->n_members; i++)
851 {
852 HeapTuple op_tuple = &catlist->members[i]->tuple;
854
855 /*
856 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
857 * check it first
858 */
859 if (op_in_opfamily(opno2, op_form->amopfamily) &&
861 {
862 result = true;
863 break;
864 }
865 }
866
868
869 return result;
870}
871
872/*
873 * comparison_ops_are_compatible
874 * Return true if the two given comparison operators have compatible
875 * semantics.
876 *
877 * This is trivially true if they are the same operator. Otherwise, we look
878 * to see if they both belong to an opfamily that guarantees compatible
879 * semantics for ordering. (For example, for btree, '<' and '>=' ops match if
880 * they belong to the same family.)
881 *
882 * (This is identical to equality_ops_are_compatible(), except that we check
883 * amconsistentordering instead of amconsistentequality.)
884 */
885bool
887{
888 bool result;
890 int i;
891
892 /* Easy if they're the same operator */
893 if (opno1 == opno2)
894 return true;
895
896 /*
897 * We search through all the pg_amop entries for opno1.
898 */
900
901 result = false;
902 for (i = 0; i < catlist->n_members; i++)
903 {
904 HeapTuple op_tuple = &catlist->members[i]->tuple;
906
907 /*
908 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
909 * check it first
910 */
911 if (op_in_opfamily(opno2, op_form->amopfamily) &&
913 {
914 result = true;
915 break;
916 }
917 }
918
920
921 return result;
922}
923
924/*
925 * collations_agree_on_equality
926 * Return true if the two collations have equivalent notions of equality,
927 * so that a uniqueness or equality proof established under one side
928 * carries over to a comparison performed under the other side.
929 *
930 * Note: this is equality compatibility only. Do NOT use this to reason
931 * about ordering.
932 *
933 * An InvalidOid on either side denotes the absence of a collation -- that
934 * side's operation is not collation-sensitive (e.g. a non-collatable column
935 * type). Absence of a collation cannot conflict with the other side's
936 * collation, so we treat such pairs as agreeing on equality. This generalizes
937 * the asymmetric treatment in IndexCollMatchesExprColl().
938 *
939 * Otherwise the collations have equivalent equality if they match, or if both
940 * are deterministic: by definition a deterministic collation treats two
941 * strings as equal iff they are byte-wise equal (see CREATE COLLATION), so any
942 * two deterministic collations share the same equality relation. A mismatch
943 * involving a nondeterministic collation, however, may mean the two equality
944 * relations disagree, and the proof is unsound.
945 */
946bool
948{
949 if (!OidIsValid(coll1) || !OidIsValid(coll2))
950 return true;
951
952 if (coll1 == coll2)
953 return true;
954
957 return false;
958
959 return true;
960}
961
962/*
963 * op_is_safe_index_member
964 * Check if the operator is a member of a B-tree or Hash operator family.
965 *
966 * We use this check as a proxy for "null-safety": if an operator is trusted by
967 * the btree or hash opfamily, it implies that the operator adheres to standard
968 * boolean behavior, and would not return NULL when given valid non-null
969 * inputs, as doing so would break index integrity.
970 */
971bool
973{
974 bool result = false;
976 int i;
977
978 /*
979 * Search pg_amop to see if the target operator is registered for any
980 * btree or hash opfamily.
981 */
983
984 for (i = 0; i < catlist->n_members; i++)
985 {
986 HeapTuple tuple = &catlist->members[i]->tuple;
988
989 /* Check if the AM is B-tree or Hash */
990 if (aform->amopmethod == BTREE_AM_OID ||
991 aform->amopmethod == HASH_AM_OID)
992 {
993 result = true;
994 break;
995 }
996 }
997
999
1000 return result;
1001}
1002
1003
1004/* ---------- AMPROC CACHES ---------- */
1005
1006/*
1007 * get_opfamily_proc
1008 * Get the OID of the specified support function
1009 * for the specified opfamily and datatypes.
1010 *
1011 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
1012 */
1013Oid
1014get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
1015{
1016 HeapTuple tp;
1019
1021 ObjectIdGetDatum(opfamily),
1022 ObjectIdGetDatum(lefttype),
1023 ObjectIdGetDatum(righttype),
1025 if (!HeapTupleIsValid(tp))
1026 return InvalidOid;
1028 result = amproc_tup->amproc;
1029 ReleaseSysCache(tp);
1030 return result;
1031}
1032
1033
1034/* ---------- ATTRIBUTE CACHES ---------- */
1035
1036/*
1037 * get_attname
1038 * Given the relation id and the attribute number, return the "attname"
1039 * field from the attribute relation as a palloc'ed string.
1040 *
1041 * If no such attribute exists and missing_ok is true, NULL is returned;
1042 * otherwise a not-intended-for-user-consumption error is thrown.
1043 */
1044char *
1045get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
1046{
1047 HeapTuple tp;
1048
1051 if (HeapTupleIsValid(tp))
1052 {
1054 char *result;
1055
1056 result = pstrdup(NameStr(att_tup->attname));
1057 ReleaseSysCache(tp);
1058 return result;
1059 }
1060
1061 if (!missing_ok)
1062 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1063 attnum, relid);
1064 return NULL;
1065}
1066
1067/*
1068 * get_attnum
1069 *
1070 * Given the relation id and the attribute name,
1071 * return the "attnum" field from the attribute relation.
1072 *
1073 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
1074 */
1076get_attnum(Oid relid, const char *attname)
1077{
1078 HeapTuple tp;
1079
1080 tp = SearchSysCacheAttName(relid, attname);
1081 if (HeapTupleIsValid(tp))
1082 {
1085
1086 result = att_tup->attnum;
1087 ReleaseSysCache(tp);
1088 return result;
1089 }
1090 else
1091 return InvalidAttrNumber;
1092}
1093
1094/*
1095 * get_attgenerated
1096 *
1097 * Given the relation id and the attribute number,
1098 * return the "attgenerated" field from the attribute relation.
1099 *
1100 * Errors if not found.
1101 *
1102 * Since not generated is represented by '\0', this can also be used as a
1103 * Boolean test.
1104 */
1105char
1107{
1108 HeapTuple tp;
1110 char result;
1111
1113 ObjectIdGetDatum(relid),
1115 if (!HeapTupleIsValid(tp))
1116 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1117 attnum, relid);
1119 result = att_tup->attgenerated;
1120 ReleaseSysCache(tp);
1121 return result;
1122}
1123
1124/*
1125 * get_atttype
1126 *
1127 * Given the relation OID and the attribute number with the relation,
1128 * return the attribute type OID.
1129 */
1130Oid
1132{
1133 HeapTuple tp;
1134
1136 ObjectIdGetDatum(relid),
1138 if (HeapTupleIsValid(tp))
1139 {
1141 Oid result;
1142
1143 result = att_tup->atttypid;
1144 ReleaseSysCache(tp);
1145 return result;
1146 }
1147 else
1148 return InvalidOid;
1149}
1150
1151/*
1152 * get_atttypetypmodcoll
1153 *
1154 * A three-fer: given the relation id and the attribute number,
1155 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
1156 *
1157 * Unlike the otherwise-similar get_atttype, this routine
1158 * raises an error if it can't obtain the information.
1159 */
1160void
1162 Oid *typid, int32 *typmod, Oid *collid)
1163{
1164 HeapTuple tp;
1166
1168 ObjectIdGetDatum(relid),
1170 if (!HeapTupleIsValid(tp))
1171 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1172 attnum, relid);
1174
1175 *typid = att_tup->atttypid;
1176 *typmod = att_tup->atttypmod;
1177 *collid = att_tup->attcollation;
1178 ReleaseSysCache(tp);
1179}
1180
1181/*
1182 * get_attoptions
1183 *
1184 * Given the relation id and the attribute number,
1185 * return the attribute options text[] datum, if any.
1186 */
1187Datum
1189{
1190 HeapTuple tuple;
1191 Datum attopts;
1192 Datum result;
1193 bool isnull;
1194
1195 tuple = SearchSysCache2(ATTNUM,
1196 ObjectIdGetDatum(relid),
1198
1199 if (!HeapTupleIsValid(tuple))
1200 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1201 attnum, relid);
1202
1204 &isnull);
1205
1206 if (isnull)
1207 result = (Datum) 0;
1208 else
1209 result = datumCopy(attopts, false, -1); /* text[] */
1210
1211 ReleaseSysCache(tuple);
1212
1213 return result;
1214}
1215
1216/* ---------- PG_CAST CACHE ---------- */
1217
1218/*
1219 * get_cast_oid - given two type OIDs, look up a cast OID
1220 *
1221 * If missing_ok is false, throw an error if the cast is not found. If
1222 * true, just return InvalidOid.
1223 */
1224Oid
1226{
1227 Oid oid;
1228
1232 if (!OidIsValid(oid) && !missing_ok)
1233 ereport(ERROR,
1235 errmsg("cast from type %s to type %s does not exist",
1238 return oid;
1239}
1240
1241/* ---------- COLLATION CACHE ---------- */
1242
1243/*
1244 * get_collation_name
1245 * Returns the name of a given pg_collation entry.
1246 *
1247 * Returns a palloc'd copy of the string, or NULL if no such collation.
1248 *
1249 * NOTE: since collation name is not unique, be wary of code that uses this
1250 * for anything except preparing error messages.
1251 */
1252char *
1254{
1255 HeapTuple tp;
1256
1258 if (HeapTupleIsValid(tp))
1259 {
1261 char *result;
1262
1263 result = pstrdup(NameStr(colltup->collname));
1264 ReleaseSysCache(tp);
1265 return result;
1266 }
1267 else
1268 return NULL;
1269}
1270
1271bool
1273{
1274 HeapTuple tp;
1276 bool result;
1277
1279 if (!HeapTupleIsValid(tp))
1280 elog(ERROR, "cache lookup failed for collation %u", colloid);
1282 result = colltup->collisdeterministic;
1283 ReleaseSysCache(tp);
1284 return result;
1285}
1286
1287/* ---------- CONSTRAINT CACHE ---------- */
1288
1289/*
1290 * get_constraint_name
1291 * Returns the name of a given pg_constraint entry.
1292 *
1293 * Returns a palloc'd copy of the string, or NULL if no such constraint.
1294 *
1295 * NOTE: since constraint name is not unique, be wary of code that uses this
1296 * for anything except preparing error messages.
1297 */
1298char *
1300{
1301 HeapTuple tp;
1302
1304 if (HeapTupleIsValid(tp))
1305 {
1307 char *result;
1308
1309 result = pstrdup(NameStr(contup->conname));
1310 ReleaseSysCache(tp);
1311 return result;
1312 }
1313 else
1314 return NULL;
1315}
1316
1317/*
1318 * get_constraint_index
1319 * Given the OID of a unique, primary-key, or exclusion constraint,
1320 * return the OID of the underlying index.
1321 *
1322 * Returns InvalidOid if the constraint could not be found or is of
1323 * the wrong type.
1324 *
1325 * The intent of this function is to return the index "owned" by the
1326 * specified constraint. Therefore we must check contype, since some
1327 * pg_constraint entries (e.g. for foreign-key constraints) store the
1328 * OID of an index that is referenced but not owned by the constraint.
1329 */
1330Oid
1332{
1333 HeapTuple tp;
1334
1336 if (HeapTupleIsValid(tp))
1337 {
1339 Oid result;
1340
1341 if (contup->contype == CONSTRAINT_UNIQUE ||
1342 contup->contype == CONSTRAINT_PRIMARY ||
1343 contup->contype == CONSTRAINT_EXCLUSION)
1344 result = contup->conindid;
1345 else
1347 ReleaseSysCache(tp);
1348 return result;
1349 }
1350 else
1351 return InvalidOid;
1352}
1353
1354/*
1355 * get_constraint_type
1356 * Return the pg_constraint.contype value for the given constraint.
1357 *
1358 * No frills.
1359 */
1360char
1362{
1363 HeapTuple tp;
1364 char contype;
1365
1367 if (!HeapTupleIsValid(tp))
1368 elog(ERROR, "cache lookup failed for constraint %u", conoid);
1369
1370 contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
1371 ReleaseSysCache(tp);
1372
1373 return contype;
1374}
1375
1376/* ---------- DATABASE CACHE ---------- */
1377
1378/*
1379 * get_database_name - given a database OID, look up the name
1380 *
1381 * Returns a palloc'd string, or NULL if no such database.
1382 */
1383char *
1385{
1387 char *result;
1388
1391 {
1394 }
1395 else
1396 result = NULL;
1397
1398 return result;
1399}
1400
1401
1402/* ---------- LANGUAGE CACHE ---------- */
1403
1404char *
1406{
1407 HeapTuple tp;
1408
1410 if (HeapTupleIsValid(tp))
1411 {
1413 char *result;
1414
1415 result = pstrdup(NameStr(lantup->lanname));
1416 ReleaseSysCache(tp);
1417 return result;
1418 }
1419
1420 if (!missing_ok)
1421 elog(ERROR, "cache lookup failed for language %u",
1422 langoid);
1423 return NULL;
1424}
1425
1426/* ---------- OPCLASS CACHE ---------- */
1427
1428/*
1429 * get_opclass_family
1430 *
1431 * Returns the OID of the operator family the opclass belongs to.
1432 */
1433Oid
1435{
1436 HeapTuple tp;
1438 Oid result;
1439
1440 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1441 if (!HeapTupleIsValid(tp))
1442 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1444
1445 result = cla_tup->opcfamily;
1446 ReleaseSysCache(tp);
1447 return result;
1448}
1449
1450/*
1451 * get_opclass_input_type
1452 *
1453 * Returns the OID of the datatype the opclass indexes.
1454 */
1455Oid
1457{
1458 HeapTuple tp;
1460 Oid result;
1461
1462 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1463 if (!HeapTupleIsValid(tp))
1464 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1466
1467 result = cla_tup->opcintype;
1468 ReleaseSysCache(tp);
1469 return result;
1470}
1471
1472/*
1473 * get_opclass_opfamily_and_input_type
1474 *
1475 * Returns the OID of the operator family the opclass belongs to,
1476 * the OID of the datatype the opclass indexes
1477 */
1478bool
1479get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1480{
1481 HeapTuple tp;
1483
1484 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1485 if (!HeapTupleIsValid(tp))
1486 return false;
1487
1489
1490 *opfamily = cla_tup->opcfamily;
1491 *opcintype = cla_tup->opcintype;
1492
1493 ReleaseSysCache(tp);
1494
1495 return true;
1496}
1497
1498/*
1499 * get_opclass_method
1500 *
1501 * Returns the OID of the index access method the opclass belongs to.
1502 */
1503Oid
1505{
1506 HeapTuple tp;
1508 Oid result;
1509
1510 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1511 if (!HeapTupleIsValid(tp))
1512 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1514
1515 result = cla_tup->opcmethod;
1516 ReleaseSysCache(tp);
1517 return result;
1518}
1519
1520/* ---------- OPFAMILY CACHE ---------- */
1521
1522/*
1523 * get_opfamily_method
1524 *
1525 * Returns the OID of the index access method the opfamily is for.
1526 */
1527Oid
1529{
1530 HeapTuple tp;
1532 Oid result;
1533
1535 if (!HeapTupleIsValid(tp))
1536 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1538
1539 result = opfform->opfmethod;
1540 ReleaseSysCache(tp);
1541 return result;
1542}
1543
1544char *
1545get_opfamily_name(Oid opfid, bool missing_ok)
1546{
1547 HeapTuple tup;
1548 char *opfname;
1550
1552
1553 if (!HeapTupleIsValid(tup))
1554 {
1555 if (!missing_ok)
1556 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1557 return NULL;
1558 }
1559
1561 opfname = pstrdup(NameStr(opfform->opfname));
1562
1564
1565 return opfname;
1566}
1567
1568/* ---------- OPERATOR CACHE ---------- */
1569
1570/*
1571 * get_opcode
1572 *
1573 * Returns the regproc id of the routine used to implement an
1574 * operator given the operator oid.
1575 */
1578{
1579 HeapTuple tp;
1580
1582 if (HeapTupleIsValid(tp))
1583 {
1586
1587 result = optup->oprcode;
1588 ReleaseSysCache(tp);
1589 return result;
1590 }
1591 else
1592 return (RegProcedure) InvalidOid;
1593}
1594
1595/*
1596 * get_opname
1597 * returns the name of the operator with the given opno
1598 *
1599 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1600 */
1601char *
1603{
1604 HeapTuple tp;
1605
1607 if (HeapTupleIsValid(tp))
1608 {
1610 char *result;
1611
1612 result = pstrdup(NameStr(optup->oprname));
1613 ReleaseSysCache(tp);
1614 return result;
1615 }
1616 else
1617 return NULL;
1618}
1619
1620/*
1621 * get_op_rettype
1622 * Given operator oid, return the operator's result type.
1623 */
1624Oid
1626{
1627 HeapTuple tp;
1628
1630 if (HeapTupleIsValid(tp))
1631 {
1633 Oid result;
1634
1635 result = optup->oprresult;
1636 ReleaseSysCache(tp);
1637 return result;
1638 }
1639 else
1640 return InvalidOid;
1641}
1642
1643/*
1644 * op_input_types
1645 *
1646 * Returns the left and right input datatypes for an operator
1647 * (InvalidOid if not relevant).
1648 */
1649void
1650op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1651{
1652 HeapTuple tp;
1654
1656 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1657 elog(ERROR, "cache lookup failed for operator %u", opno);
1659 *lefttype = optup->oprleft;
1660 *righttype = optup->oprright;
1661 ReleaseSysCache(tp);
1662}
1663
1664/*
1665 * op_mergejoinable
1666 *
1667 * Returns true if the operator is potentially mergejoinable. (The planner
1668 * will fail to find any mergejoin plans unless there are suitable btree
1669 * opfamily entries for this operator and associated sortops. The pg_operator
1670 * flag is just a hint to tell the planner whether to bother looking.)
1671 *
1672 * In some cases (currently only array_eq and record_eq), mergejoinability
1673 * depends on the specific input data type the operator is invoked for, so
1674 * that must be passed as well. We currently assume that only one input's type
1675 * is needed to check this --- by convention, pass the left input's data type.
1676 */
1677bool
1678op_mergejoinable(Oid opno, Oid inputtype)
1679{
1680 bool result = false;
1681 HeapTuple tp;
1682 TypeCacheEntry *typentry;
1683
1684 /*
1685 * For array_eq or record_eq, we can sort if the element or field types
1686 * are all sortable. We could implement all the checks for that here, but
1687 * the typcache already does that and caches the results too, so let's
1688 * rely on the typcache. We do not need similar special cases for ranges
1689 * or multiranges, because their subtypes are required to be sortable.
1690 */
1691 if (opno == ARRAY_EQ_OP)
1692 {
1693 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1694 if (typentry->cmp_proc == F_BTARRAYCMP)
1695 result = true;
1696 }
1697 else if (opno == RECORD_EQ_OP)
1698 {
1699 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1700 if (typentry->cmp_proc == F_BTRECORDCMP)
1701 result = true;
1702 }
1703 else
1704 {
1705 /* For all other operators, rely on pg_operator.oprcanmerge */
1707 if (HeapTupleIsValid(tp))
1708 {
1710
1711 result = optup->oprcanmerge;
1712 ReleaseSysCache(tp);
1713 }
1714 }
1715 return result;
1716}
1717
1718/*
1719 * op_hashjoinable
1720 *
1721 * Returns true if the operator is hashjoinable. (There must be a suitable
1722 * hash opfamily entry for this operator if it is so marked.)
1723 *
1724 * In some cases (currently array_eq, record_eq, range_eq, multirange_eq),
1725 * hashjoinability depends on the specific input data type the operator is
1726 * invoked for, so that must be passed as well. We currently assume that only
1727 * one input's type is needed to check this --- by convention, pass the left
1728 * input's data type.
1729 */
1730bool
1731op_hashjoinable(Oid opno, Oid inputtype)
1732{
1733 bool result = false;
1734 HeapTuple tp;
1735 TypeCacheEntry *typentry;
1736
1737 /* As in op_mergejoinable, let the typcache handle the hard cases */
1738 if (opno == ARRAY_EQ_OP)
1739 {
1740 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1741 if (typentry->hash_proc == F_HASH_ARRAY)
1742 result = true;
1743 }
1744 else if (opno == RECORD_EQ_OP)
1745 {
1746 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1747 if (typentry->hash_proc == F_HASH_RECORD)
1748 result = true;
1749 }
1750 else if (opno == RANGE_EQ_OP)
1751 {
1752 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1753 if (typentry->hash_proc == F_HASH_RANGE)
1754 result = true;
1755 }
1756 else if (opno == MULTIRANGE_EQ_OP)
1757 {
1758 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1759 if (typentry->hash_proc == F_HASH_MULTIRANGE)
1760 result = true;
1761 }
1762 else
1763 {
1764 /* For all other operators, rely on pg_operator.oprcanhash */
1766 if (HeapTupleIsValid(tp))
1767 {
1769
1770 result = optup->oprcanhash;
1771 ReleaseSysCache(tp);
1772 }
1773 }
1774 return result;
1775}
1776
1777/*
1778 * op_strict
1779 *
1780 * Get the proisstrict flag for the operator's underlying function.
1781 */
1782bool
1784{
1785 RegProcedure funcid = get_opcode(opno);
1786
1787 if (funcid == (RegProcedure) InvalidOid)
1788 elog(ERROR, "operator %u does not exist", opno);
1789
1790 return func_strict((Oid) funcid);
1791}
1792
1793/*
1794 * op_volatile
1795 *
1796 * Get the provolatile flag for the operator's underlying function.
1797 */
1798char
1800{
1801 RegProcedure funcid = get_opcode(opno);
1802
1803 if (funcid == (RegProcedure) InvalidOid)
1804 elog(ERROR, "operator %u does not exist", opno);
1805
1806 return func_volatile((Oid) funcid);
1807}
1808
1809/*
1810 * get_commutator
1811 *
1812 * Returns the corresponding commutator of an operator.
1813 */
1814Oid
1816{
1817 HeapTuple tp;
1818
1820 if (HeapTupleIsValid(tp))
1821 {
1823 Oid result;
1824
1825 result = optup->oprcom;
1826 ReleaseSysCache(tp);
1827 return result;
1828 }
1829 else
1830 return InvalidOid;
1831}
1832
1833/*
1834 * get_negator
1835 *
1836 * Returns the corresponding negator of an operator.
1837 */
1838Oid
1840{
1841 HeapTuple tp;
1842
1844 if (HeapTupleIsValid(tp))
1845 {
1847 Oid result;
1848
1849 result = optup->oprnegate;
1850 ReleaseSysCache(tp);
1851 return result;
1852 }
1853 else
1854 return InvalidOid;
1855}
1856
1857/*
1858 * get_oprrest
1859 *
1860 * Returns procedure id for computing selectivity of an operator.
1861 */
1864{
1865 HeapTuple tp;
1866
1868 if (HeapTupleIsValid(tp))
1869 {
1872
1873 result = optup->oprrest;
1874 ReleaseSysCache(tp);
1875 return result;
1876 }
1877 else
1878 return (RegProcedure) InvalidOid;
1879}
1880
1881/*
1882 * get_oprjoin
1883 *
1884 * Returns procedure id for computing selectivity of a join.
1885 */
1888{
1889 HeapTuple tp;
1890
1892 if (HeapTupleIsValid(tp))
1893 {
1896
1897 result = optup->oprjoin;
1898 ReleaseSysCache(tp);
1899 return result;
1900 }
1901 else
1902 return (RegProcedure) InvalidOid;
1903}
1904
1905/* ---------- FUNCTION CACHE ---------- */
1906
1907/*
1908 * get_func_name
1909 * returns the name of the function with the given funcid
1910 *
1911 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1912 */
1913char *
1915{
1916 HeapTuple tp;
1917
1919 if (HeapTupleIsValid(tp))
1920 {
1922 char *result;
1923
1924 result = pstrdup(NameStr(functup->proname));
1925 ReleaseSysCache(tp);
1926 return result;
1927 }
1928 else
1929 return NULL;
1930}
1931
1932/*
1933 * get_func_namespace
1934 *
1935 * Returns the pg_namespace OID associated with a given function.
1936 */
1937Oid
1939{
1940 HeapTuple tp;
1941
1943 if (HeapTupleIsValid(tp))
1944 {
1946 Oid result;
1947
1948 result = functup->pronamespace;
1949 ReleaseSysCache(tp);
1950 return result;
1951 }
1952 else
1953 return InvalidOid;
1954}
1955
1956/*
1957 * get_func_rettype
1958 * Given procedure id, return the function's result type.
1959 */
1960Oid
1962{
1963 HeapTuple tp;
1964 Oid result;
1965
1967 if (!HeapTupleIsValid(tp))
1968 elog(ERROR, "cache lookup failed for function %u", funcid);
1969
1970 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1971 ReleaseSysCache(tp);
1972 return result;
1973}
1974
1975/*
1976 * get_func_nargs
1977 * Given procedure id, return the number of arguments.
1978 */
1979int
1981{
1982 HeapTuple tp;
1983 int result;
1984
1986 if (!HeapTupleIsValid(tp))
1987 elog(ERROR, "cache lookup failed for function %u", funcid);
1988
1990 ReleaseSysCache(tp);
1991 return result;
1992}
1993
1994/*
1995 * get_func_signature
1996 * Given procedure id, return the function's argument and result types.
1997 * (The return value is the result type.)
1998 *
1999 * The arguments are returned as a palloc'd array.
2000 */
2001Oid
2002get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
2003{
2004 HeapTuple tp;
2006 Oid result;
2007
2009 if (!HeapTupleIsValid(tp))
2010 elog(ERROR, "cache lookup failed for function %u", funcid);
2011
2013
2014 result = procstruct->prorettype;
2015 *nargs = (int) procstruct->pronargs;
2016 Assert(*nargs == procstruct->proargtypes.dim1);
2017 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
2018 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
2019
2020 ReleaseSysCache(tp);
2021 return result;
2022}
2023
2024/*
2025 * get_func_variadictype
2026 * Given procedure id, return the function's provariadic field.
2027 */
2028Oid
2030{
2031 HeapTuple tp;
2032 Oid result;
2033
2035 if (!HeapTupleIsValid(tp))
2036 elog(ERROR, "cache lookup failed for function %u", funcid);
2037
2039 ReleaseSysCache(tp);
2040 return result;
2041}
2042
2043/*
2044 * get_func_retset
2045 * Given procedure id, return the function's proretset flag.
2046 */
2047bool
2049{
2050 HeapTuple tp;
2051 bool result;
2052
2054 if (!HeapTupleIsValid(tp))
2055 elog(ERROR, "cache lookup failed for function %u", funcid);
2056
2058 ReleaseSysCache(tp);
2059 return result;
2060}
2061
2062/*
2063 * func_strict
2064 * Given procedure id, return the function's proisstrict flag.
2065 */
2066bool
2068{
2069 HeapTuple tp;
2070 bool result;
2071
2073 if (!HeapTupleIsValid(tp))
2074 elog(ERROR, "cache lookup failed for function %u", funcid);
2075
2077 ReleaseSysCache(tp);
2078 return result;
2079}
2080
2081/*
2082 * func_volatile
2083 * Given procedure id, return the function's provolatile flag.
2084 */
2085char
2087{
2088 HeapTuple tp;
2089 char result;
2090
2092 if (!HeapTupleIsValid(tp))
2093 elog(ERROR, "cache lookup failed for function %u", funcid);
2094
2096 ReleaseSysCache(tp);
2097 return result;
2098}
2099
2100/*
2101 * func_parallel
2102 * Given procedure id, return the function's proparallel flag.
2103 */
2104char
2106{
2107 HeapTuple tp;
2108 char result;
2109
2111 if (!HeapTupleIsValid(tp))
2112 elog(ERROR, "cache lookup failed for function %u", funcid);
2113
2115 ReleaseSysCache(tp);
2116 return result;
2117}
2118
2119/*
2120 * get_func_prokind
2121 * Given procedure id, return the routine kind.
2122 */
2123char
2125{
2126 HeapTuple tp;
2127 char result;
2128
2130 if (!HeapTupleIsValid(tp))
2131 elog(ERROR, "cache lookup failed for function %u", funcid);
2132
2133 result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
2134 ReleaseSysCache(tp);
2135 return result;
2136}
2137
2138/*
2139 * get_func_leakproof
2140 * Given procedure id, return the function's leakproof field.
2141 */
2142bool
2144{
2145 HeapTuple tp;
2146 bool result;
2147
2149 if (!HeapTupleIsValid(tp))
2150 elog(ERROR, "cache lookup failed for function %u", funcid);
2151
2153 ReleaseSysCache(tp);
2154 return result;
2155}
2156
2157/*
2158 * get_func_support
2159 *
2160 * Returns the support function OID associated with a given function,
2161 * or InvalidOid if there is none.
2162 */
2165{
2166 HeapTuple tp;
2167
2169 if (HeapTupleIsValid(tp))
2170 {
2173
2174 result = functup->prosupport;
2175 ReleaseSysCache(tp);
2176 return result;
2177 }
2178 else
2179 return (RegProcedure) InvalidOid;
2180}
2181
2182/* ---------- RELATION CACHE ---------- */
2183
2184/*
2185 * get_relname_relid
2186 * Given name and namespace of a relation, look up the OID.
2187 *
2188 * Returns InvalidOid if there is no such relation.
2189 */
2190Oid
2191get_relname_relid(const char *relname, Oid relnamespace)
2192{
2195 ObjectIdGetDatum(relnamespace));
2196}
2197
2198#ifdef NOT_USED
2199/*
2200 * get_relnatts
2201 *
2202 * Returns the number of attributes for a given relation.
2203 */
2204int
2205get_relnatts(Oid relid)
2206{
2207 HeapTuple tp;
2208
2210 if (HeapTupleIsValid(tp))
2211 {
2213 int result;
2214
2215 result = reltup->relnatts;
2216 ReleaseSysCache(tp);
2217 return result;
2218 }
2219 else
2220 return InvalidAttrNumber;
2221}
2222#endif
2223
2224/*
2225 * get_rel_name
2226 * Returns the name of a given relation.
2227 *
2228 * Returns a palloc'd copy of the string, or NULL if no such relation.
2229 *
2230 * NOTE: since relation name is not unique, be wary of code that uses this
2231 * for anything except preparing error messages.
2232 */
2233char *
2235{
2236 HeapTuple tp;
2237
2239 if (HeapTupleIsValid(tp))
2240 {
2242 char *result;
2243
2244 result = pstrdup(NameStr(reltup->relname));
2245 ReleaseSysCache(tp);
2246 return result;
2247 }
2248 else
2249 return NULL;
2250}
2251
2252/*
2253 * get_rel_namespace
2254 *
2255 * Returns the pg_namespace OID associated with a given relation.
2256 */
2257Oid
2259{
2260 HeapTuple tp;
2261
2263 if (HeapTupleIsValid(tp))
2264 {
2266 Oid result;
2267
2268 result = reltup->relnamespace;
2269 ReleaseSysCache(tp);
2270 return result;
2271 }
2272 else
2273 return InvalidOid;
2274}
2275
2276/*
2277 * get_rel_type_id
2278 *
2279 * Returns the pg_type OID associated with a given relation.
2280 *
2281 * Note: not all pg_class entries have associated pg_type OIDs; so be
2282 * careful to check for InvalidOid result.
2283 */
2284Oid
2286{
2287 HeapTuple tp;
2288
2290 if (HeapTupleIsValid(tp))
2291 {
2293 Oid result;
2294
2295 result = reltup->reltype;
2296 ReleaseSysCache(tp);
2297 return result;
2298 }
2299 else
2300 return InvalidOid;
2301}
2302
2303/*
2304 * get_rel_relkind
2305 *
2306 * Returns the relkind associated with a given relation.
2307 */
2308char
2310{
2311 HeapTuple tp;
2312
2314 if (HeapTupleIsValid(tp))
2315 {
2317 char result;
2318
2319 result = reltup->relkind;
2320 ReleaseSysCache(tp);
2321 return result;
2322 }
2323 else
2324 return '\0';
2325}
2326
2327/*
2328 * get_rel_relispartition
2329 *
2330 * Returns the relispartition flag associated with a given relation.
2331 */
2332bool
2334{
2335 HeapTuple tp;
2336
2338 if (HeapTupleIsValid(tp))
2339 {
2341 bool result;
2342
2343 result = reltup->relispartition;
2344 ReleaseSysCache(tp);
2345 return result;
2346 }
2347 else
2348 return false;
2349}
2350
2351/*
2352 * get_rel_tablespace
2353 *
2354 * Returns the pg_tablespace OID associated with a given relation.
2355 *
2356 * Note: InvalidOid might mean either that we couldn't find the relation,
2357 * or that it is in the database's default tablespace.
2358 */
2359Oid
2361{
2362 HeapTuple tp;
2363
2365 if (HeapTupleIsValid(tp))
2366 {
2368 Oid result;
2369
2370 result = reltup->reltablespace;
2371 ReleaseSysCache(tp);
2372 return result;
2373 }
2374 else
2375 return InvalidOid;
2376}
2377
2378/*
2379 * get_rel_persistence
2380 *
2381 * Returns the relpersistence associated with a given relation.
2382 */
2383char
2385{
2386 HeapTuple tp;
2388 char result;
2389
2391 if (!HeapTupleIsValid(tp))
2392 elog(ERROR, "cache lookup failed for relation %u", relid);
2394 result = reltup->relpersistence;
2395 ReleaseSysCache(tp);
2396
2397 return result;
2398}
2399
2400/*
2401 * get_rel_relam
2402 *
2403 * Returns the relam associated with a given relation.
2404 */
2405Oid
2407{
2408 HeapTuple tp;
2410 Oid result;
2411
2413 if (!HeapTupleIsValid(tp))
2414 elog(ERROR, "cache lookup failed for relation %u", relid);
2416 result = reltup->relam;
2417 ReleaseSysCache(tp);
2418
2419 return result;
2420}
2421
2422
2423/* ---------- TRANSFORM CACHE ---------- */
2424
2425Oid
2426get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2427{
2428 HeapTuple tup;
2429
2430 if (!list_member_oid(trftypes, typid))
2431 return InvalidOid;
2432
2434 ObjectIdGetDatum(langid));
2435 if (HeapTupleIsValid(tup))
2436 {
2437 Oid funcid;
2438
2439 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2441 return funcid;
2442 }
2443 else
2444 return InvalidOid;
2445}
2446
2447Oid
2448get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2449{
2450 HeapTuple tup;
2451
2452 if (!list_member_oid(trftypes, typid))
2453 return InvalidOid;
2454
2456 ObjectIdGetDatum(langid));
2457 if (HeapTupleIsValid(tup))
2458 {
2459 Oid funcid;
2460
2461 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2463 return funcid;
2464 }
2465 else
2466 return InvalidOid;
2467}
2468
2469
2470/* ---------- TYPE CACHE ---------- */
2471
2472/*
2473 * get_typisdefined
2474 *
2475 * Given the type OID, determine whether the type is defined
2476 * (if not, it's only a shell).
2477 */
2478bool
2480{
2481 HeapTuple tp;
2482
2484 if (HeapTupleIsValid(tp))
2485 {
2487 bool result;
2488
2489 result = typtup->typisdefined;
2490 ReleaseSysCache(tp);
2491 return result;
2492 }
2493 else
2494 return false;
2495}
2496
2497/*
2498 * get_typlen
2499 *
2500 * Given the type OID, return the length of the type.
2501 */
2502int16
2504{
2505 HeapTuple tp;
2506
2508 if (HeapTupleIsValid(tp))
2509 {
2511 int16 result;
2512
2513 result = typtup->typlen;
2514 ReleaseSysCache(tp);
2515 return result;
2516 }
2517 else
2518 return 0;
2519}
2520
2521/*
2522 * get_typbyval
2523 *
2524 * Given the type OID, determine whether the type is returned by value or
2525 * not. Returns true if by value, false if by reference.
2526 */
2527bool
2529{
2530 HeapTuple tp;
2531
2533 if (HeapTupleIsValid(tp))
2534 {
2536 bool result;
2537
2538 result = typtup->typbyval;
2539 ReleaseSysCache(tp);
2540 return result;
2541 }
2542 else
2543 return false;
2544}
2545
2546/*
2547 * get_typlenbyval
2548 *
2549 * A two-fer: given the type OID, return both typlen and typbyval.
2550 *
2551 * Since both pieces of info are needed to know how to copy a Datum,
2552 * many places need both. Might as well get them with one cache lookup
2553 * instead of two. Also, this routine raises an error instead of
2554 * returning a bogus value when given a bad type OID.
2555 */
2556void
2557get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2558{
2559 HeapTuple tp;
2561
2563 if (!HeapTupleIsValid(tp))
2564 elog(ERROR, "cache lookup failed for type %u", typid);
2566 *typlen = typtup->typlen;
2567 *typbyval = typtup->typbyval;
2568 ReleaseSysCache(tp);
2569}
2570
2571/*
2572 * get_typlenbyvalalign
2573 *
2574 * A three-fer: given the type OID, return typlen, typbyval, typalign.
2575 */
2576void
2577get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2578 char *typalign)
2579{
2580 HeapTuple tp;
2582
2584 if (!HeapTupleIsValid(tp))
2585 elog(ERROR, "cache lookup failed for type %u", typid);
2587 *typlen = typtup->typlen;
2588 *typbyval = typtup->typbyval;
2589 *typalign = typtup->typalign;
2590 ReleaseSysCache(tp);
2591}
2592
2593/*
2594 * getTypeIOParam
2595 * Given a pg_type row, select the type OID to pass to I/O functions
2596 *
2597 * Formerly, all I/O functions were passed pg_type.typelem as their second
2598 * parameter, but we now have a more complex rule about what to pass.
2599 * This knowledge is intended to be centralized here --- direct references
2600 * to typelem elsewhere in the code are wrong, if they are associated with
2601 * I/O calls and not with actual subscripting operations! (But see
2602 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2603 *
2604 * As of PostgreSQL 8.1, output functions receive only the value itself
2605 * and not any auxiliary parameters, so the name of this routine is now
2606 * a bit of a misnomer ... it should be getTypeInputParam.
2607 */
2608Oid
2610{
2612
2613 /*
2614 * Array types get their typelem as parameter; everybody else gets their
2615 * own type OID as parameter.
2616 */
2617 if (OidIsValid(typeStruct->typelem))
2618 return typeStruct->typelem;
2619 else
2620 return typeStruct->oid;
2621}
2622
2623/*
2624 * get_type_io_data
2625 *
2626 * A six-fer: given the type OID, return typlen, typbyval, typalign,
2627 * typdelim, typioparam, and IO function OID. The IO function
2628 * returned is controlled by IOFuncSelector
2629 */
2630void
2633 int16 *typlen,
2634 bool *typbyval,
2635 char *typalign,
2636 char *typdelim,
2637 Oid *typioparam,
2638 Oid *func)
2639{
2642
2643 /*
2644 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2645 * use array_in and array_out during bootstrap.
2646 */
2648 {
2649 Oid typinput;
2650 Oid typoutput;
2651 Oid typcollation;
2652
2654 typlen,
2655 typbyval,
2656 typalign,
2657 typdelim,
2658 typioparam,
2659 &typinput,
2660 &typoutput,
2661 &typcollation);
2662 switch (which_func)
2663 {
2664 case IOFunc_input:
2665 *func = typinput;
2666 break;
2667 case IOFunc_output:
2668 *func = typoutput;
2669 break;
2670 default:
2671 elog(ERROR, "binary I/O not supported during bootstrap");
2672 break;
2673 }
2674 return;
2675 }
2676
2679 elog(ERROR, "cache lookup failed for type %u", typid);
2681
2682 *typlen = typeStruct->typlen;
2683 *typbyval = typeStruct->typbyval;
2684 *typalign = typeStruct->typalign;
2685 *typdelim = typeStruct->typdelim;
2686 *typioparam = getTypeIOParam(typeTuple);
2687 switch (which_func)
2688 {
2689 case IOFunc_input:
2690 *func = typeStruct->typinput;
2691 break;
2692 case IOFunc_output:
2693 *func = typeStruct->typoutput;
2694 break;
2695 case IOFunc_receive:
2696 *func = typeStruct->typreceive;
2697 break;
2698 case IOFunc_send:
2699 *func = typeStruct->typsend;
2700 break;
2701 }
2703}
2704
2705#ifdef NOT_USED
2706char
2707get_typalign(Oid typid)
2708{
2709 HeapTuple tp;
2710
2712 if (HeapTupleIsValid(tp))
2713 {
2715 char result;
2716
2717 result = typtup->typalign;
2718 ReleaseSysCache(tp);
2719 return result;
2720 }
2721 else
2722 return TYPALIGN_INT;
2723}
2724#endif
2725
2726char
2728{
2729 HeapTuple tp;
2730
2732 if (HeapTupleIsValid(tp))
2733 {
2735 char result;
2736
2737 result = typtup->typstorage;
2738 ReleaseSysCache(tp);
2739 return result;
2740 }
2741 else
2742 return TYPSTORAGE_PLAIN;
2743}
2744
2745/*
2746 * get_typdefault
2747 * Given a type OID, return the type's default value, if any.
2748 *
2749 * The result is a palloc'd expression node tree, or NULL if there
2750 * is no defined default for the datatype.
2751 *
2752 * NB: caller should be prepared to coerce result to correct datatype;
2753 * the returned expression tree might produce something of the wrong type.
2754 */
2755Node *
2757{
2760 Datum datum;
2761 bool isNull;
2762 Node *expr;
2763
2766 elog(ERROR, "cache lookup failed for type %u", typid);
2768
2769 /*
2770 * typdefault and typdefaultbin are potentially null, so don't try to
2771 * access 'em as struct fields. Must do it the hard way with
2772 * SysCacheGetAttr.
2773 */
2774 datum = SysCacheGetAttr(TYPEOID,
2775 typeTuple,
2777 &isNull);
2778
2779 if (!isNull)
2780 {
2781 /* We have an expression default */
2782 expr = stringToNode(TextDatumGetCString(datum));
2783 }
2784 else
2785 {
2786 /* Perhaps we have a plain literal default */
2787 datum = SysCacheGetAttr(TYPEOID,
2788 typeTuple,
2790 &isNull);
2791
2792 if (!isNull)
2793 {
2794 char *strDefaultVal;
2795
2796 /* Convert text datum to C string */
2798 /* Convert C string to a value of the given type */
2799 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2801 /* Build a Const node containing the value */
2802 expr = (Node *) makeConst(typid,
2803 -1,
2804 type->typcollation,
2805 type->typlen,
2806 datum,
2807 false,
2808 type->typbyval);
2810 }
2811 else
2812 {
2813 /* No default */
2814 expr = NULL;
2815 }
2816 }
2817
2819
2820 return expr;
2821}
2822
2823/*
2824 * getBaseType
2825 * If the given type is a domain, return its base type;
2826 * otherwise return the type's own OID.
2827 */
2828Oid
2830{
2831 int32 typmod = -1;
2832
2833 return getBaseTypeAndTypmod(typid, &typmod);
2834}
2835
2836/*
2837 * getBaseTypeAndTypmod
2838 * If the given type is a domain, return its base type and typmod;
2839 * otherwise return the type's own OID, and leave *typmod unchanged.
2840 *
2841 * Note that the "applied typmod" should be -1 for every domain level
2842 * above the bottommost; therefore, if the passed-in typid is indeed
2843 * a domain, *typmod should be -1.
2844 */
2845Oid
2847{
2848 /*
2849 * We loop to find the bottom base type in a stack of domains.
2850 */
2851 for (;;)
2852 {
2853 HeapTuple tup;
2855
2857 if (!HeapTupleIsValid(tup))
2858 elog(ERROR, "cache lookup failed for type %u", typid);
2860 if (typTup->typtype != TYPTYPE_DOMAIN)
2861 {
2862 /* Not a domain, so done */
2864 break;
2865 }
2866
2867 Assert(*typmod == -1);
2868 typid = typTup->typbasetype;
2869 *typmod = typTup->typtypmod;
2870
2872 }
2873
2874 return typid;
2875}
2876
2877/*
2878 * get_typavgwidth
2879 *
2880 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2881 * estimate the average width of values of the type. This is used by
2882 * the planner, which doesn't require absolutely correct results;
2883 * it's OK (and expected) to guess if we don't know for sure.
2884 */
2885int32
2887{
2888 int typlen = get_typlen(typid);
2890
2891 /*
2892 * Easy if it's a fixed-width type
2893 */
2894 if (typlen > 0)
2895 return typlen;
2896
2897 /*
2898 * type_maximum_size knows the encoding of typmod for some datatypes;
2899 * don't duplicate that knowledge here.
2900 */
2901 maxwidth = type_maximum_size(typid, typmod);
2902 if (maxwidth > 0)
2903 {
2904 /*
2905 * For BPCHAR, the max width is also the only width. Otherwise we
2906 * need to guess about the typical data width given the max. A sliding
2907 * scale for percentage of max width seems reasonable.
2908 */
2909 if (typid == BPCHAROID)
2910 return maxwidth;
2911 if (maxwidth <= 32)
2912 return maxwidth; /* assume full width */
2913 if (maxwidth < 1000)
2914 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2915
2916 /*
2917 * Beyond 1000, assume we're looking at something like
2918 * "varchar(10000)" where the limit isn't actually reached often, and
2919 * use a fixed estimate.
2920 */
2921 return 32 + (1000 - 32) / 2;
2922 }
2923
2924 /*
2925 * Oops, we have no idea ... wild guess time.
2926 */
2927 return 32;
2928}
2929
2930/*
2931 * get_typtype
2932 *
2933 * Given the type OID, find if it is a basic type, a complex type, etc.
2934 * It returns the null char if the cache lookup fails...
2935 */
2936char
2938{
2939 HeapTuple tp;
2940
2942 if (HeapTupleIsValid(tp))
2943 {
2945 char result;
2946
2947 result = typtup->typtype;
2948 ReleaseSysCache(tp);
2949 return result;
2950 }
2951 else
2952 return '\0';
2953}
2954
2955/*
2956 * type_is_rowtype
2957 *
2958 * Convenience function to determine whether a type OID represents
2959 * a "rowtype" type --- either RECORD or a named composite type
2960 * (including a domain over a named composite type).
2961 */
2962bool
2964{
2965 if (typid == RECORDOID)
2966 return true; /* easy case */
2967 switch (get_typtype(typid))
2968 {
2969 case TYPTYPE_COMPOSITE:
2970 return true;
2971 case TYPTYPE_DOMAIN:
2973 return true;
2974 break;
2975 default:
2976 break;
2977 }
2978 return false;
2979}
2980
2981/*
2982 * type_is_enum
2983 * Returns true if the given type is an enum type.
2984 */
2985bool
2987{
2988 return (get_typtype(typid) == TYPTYPE_ENUM);
2989}
2990
2991/*
2992 * type_is_range
2993 * Returns true if the given type is a range type.
2994 */
2995bool
2997{
2998 return (get_typtype(typid) == TYPTYPE_RANGE);
2999}
3000
3001/*
3002 * type_is_multirange
3003 * Returns true if the given type is a multirange type.
3004 */
3005bool
3007{
3008 return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
3009}
3010
3011/*
3012 * get_type_category_preferred
3013 *
3014 * Given the type OID, fetch its category and preferred-type status.
3015 * Throws error on failure.
3016 */
3017void
3019{
3020 HeapTuple tp;
3022
3024 if (!HeapTupleIsValid(tp))
3025 elog(ERROR, "cache lookup failed for type %u", typid);
3027 *typcategory = typtup->typcategory;
3028 *typispreferred = typtup->typispreferred;
3029 ReleaseSysCache(tp);
3030}
3031
3032/*
3033 * get_typ_typrelid
3034 *
3035 * Given the type OID, get the typrelid (InvalidOid if not a complex
3036 * type).
3037 */
3038Oid
3040{
3041 HeapTuple tp;
3042
3044 if (HeapTupleIsValid(tp))
3045 {
3047 Oid result;
3048
3049 result = typtup->typrelid;
3050 ReleaseSysCache(tp);
3051 return result;
3052 }
3053 else
3054 return InvalidOid;
3055}
3056
3057/*
3058 * get_element_type
3059 *
3060 * Given the type OID, get the typelem (InvalidOid if not an array type).
3061 *
3062 * NB: this only succeeds for "true" arrays having array_subscript_handler
3063 * as typsubscript. For other types, InvalidOid is returned independently
3064 * of whether they have typelem or typsubscript set.
3065 */
3066Oid
3068{
3069 HeapTuple tp;
3070
3072 if (HeapTupleIsValid(tp))
3073 {
3075 Oid result;
3076
3078 result = typtup->typelem;
3079 else
3081 ReleaseSysCache(tp);
3082 return result;
3083 }
3084 else
3085 return InvalidOid;
3086}
3087
3088/*
3089 * get_array_type
3090 *
3091 * Given the type OID, get the corresponding "true" array type.
3092 * Returns InvalidOid if no array type can be found.
3093 */
3094Oid
3096{
3097 HeapTuple tp;
3099
3101 if (HeapTupleIsValid(tp))
3102 {
3103 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
3104 ReleaseSysCache(tp);
3105 }
3106 return result;
3107}
3108
3109/*
3110 * get_promoted_array_type
3111 *
3112 * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
3113 * construct, that is, either the corresponding "true" array type
3114 * if the input is a scalar type that has such an array type,
3115 * or the same type if the input is already a "true" array type.
3116 * Returns InvalidOid if neither rule is satisfied.
3117 */
3118Oid
3120{
3121 Oid array_type = get_array_type(typid);
3122
3123 if (OidIsValid(array_type))
3124 return array_type;
3125 if (OidIsValid(get_element_type(typid)))
3126 return typid;
3127 return InvalidOid;
3128}
3129
3130/*
3131 * get_base_element_type
3132 * Given the type OID, get the typelem, looking "through" any domain
3133 * to its underlying array type.
3134 *
3135 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
3136 * an extra cache lookup. Note that it fails to provide any information
3137 * about the typmod of the array.
3138 */
3139Oid
3141{
3142 /*
3143 * We loop to find the bottom base type in a stack of domains.
3144 */
3145 for (;;)
3146 {
3147 HeapTuple tup;
3149
3151 if (!HeapTupleIsValid(tup))
3152 break;
3154 if (typTup->typtype != TYPTYPE_DOMAIN)
3155 {
3156 /* Not a domain, so stop descending */
3157 Oid result;
3158
3159 /* This test must match get_element_type */
3161 result = typTup->typelem;
3162 else
3165 return result;
3166 }
3167
3168 typid = typTup->typbasetype;
3170 }
3171
3172 /* Like get_element_type, silently return InvalidOid for bogus input */
3173 return InvalidOid;
3174}
3175
3176/*
3177 * getTypeInputInfo
3178 *
3179 * Get info needed for converting values of a type to internal form
3180 */
3181void
3183{
3186
3189 elog(ERROR, "cache lookup failed for type %u", type);
3191
3192 if (!pt->typisdefined)
3193 ereport(ERROR,
3195 errmsg("type %s is only a shell",
3196 format_type_be(type))));
3197 if (!OidIsValid(pt->typinput))
3198 ereport(ERROR,
3200 errmsg("no input function available for type %s",
3201 format_type_be(type))));
3202
3203 *typInput = pt->typinput;
3205
3207}
3208
3209/*
3210 * getTypeOutputInfo
3211 *
3212 * Get info needed for printing values of a type
3213 */
3214void
3216{
3219
3222 elog(ERROR, "cache lookup failed for type %u", type);
3224
3225 if (!pt->typisdefined)
3226 ereport(ERROR,
3228 errmsg("type %s is only a shell",
3229 format_type_be(type))));
3230 if (!OidIsValid(pt->typoutput))
3231 ereport(ERROR,
3233 errmsg("no output function available for type %s",
3234 format_type_be(type))));
3235
3236 *typOutput = pt->typoutput;
3237 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3238
3240}
3241
3242/*
3243 * getTypeBinaryInputInfo
3244 *
3245 * Get info needed for binary input of values of a type
3246 */
3247void
3249{
3252
3255 elog(ERROR, "cache lookup failed for type %u", type);
3257
3258 if (!pt->typisdefined)
3259 ereport(ERROR,
3261 errmsg("type %s is only a shell",
3262 format_type_be(type))));
3263 if (!OidIsValid(pt->typreceive))
3264 ereport(ERROR,
3266 errmsg("no binary input function available for type %s",
3267 format_type_be(type))));
3268
3269 *typReceive = pt->typreceive;
3271
3273}
3274
3275/*
3276 * getTypeBinaryOutputInfo
3277 *
3278 * Get info needed for binary output of values of a type
3279 */
3280void
3282{
3285
3288 elog(ERROR, "cache lookup failed for type %u", type);
3290
3291 if (!pt->typisdefined)
3292 ereport(ERROR,
3294 errmsg("type %s is only a shell",
3295 format_type_be(type))));
3296 if (!OidIsValid(pt->typsend))
3297 ereport(ERROR,
3299 errmsg("no binary output function available for type %s",
3300 format_type_be(type))));
3301
3302 *typSend = pt->typsend;
3303 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3304
3306}
3307
3308/*
3309 * get_typmodin
3310 *
3311 * Given the type OID, return the type's typmodin procedure, if any.
3312 */
3313Oid
3315{
3316 HeapTuple tp;
3317
3319 if (HeapTupleIsValid(tp))
3320 {
3322 Oid result;
3323
3324 result = typtup->typmodin;
3325 ReleaseSysCache(tp);
3326 return result;
3327 }
3328 else
3329 return InvalidOid;
3330}
3331
3332#ifdef NOT_USED
3333/*
3334 * get_typmodout
3335 *
3336 * Given the type OID, return the type's typmodout procedure, if any.
3337 */
3338Oid
3339get_typmodout(Oid typid)
3340{
3341 HeapTuple tp;
3342
3344 if (HeapTupleIsValid(tp))
3345 {
3347 Oid result;
3348
3349 result = typtup->typmodout;
3350 ReleaseSysCache(tp);
3351 return result;
3352 }
3353 else
3354 return InvalidOid;
3355}
3356#endif /* NOT_USED */
3357
3358/*
3359 * get_typcollation
3360 *
3361 * Given the type OID, return the type's typcollation attribute.
3362 */
3363Oid
3365{
3366 HeapTuple tp;
3367
3369 if (HeapTupleIsValid(tp))
3370 {
3372 Oid result;
3373
3374 result = typtup->typcollation;
3375 ReleaseSysCache(tp);
3376 return result;
3377 }
3378 else
3379 return InvalidOid;
3380}
3381
3382
3383/*
3384 * type_is_collatable
3385 *
3386 * Return whether the type cares about collations
3387 */
3388bool
3390{
3391 return OidIsValid(get_typcollation(typid));
3392}
3393
3394
3395/*
3396 * get_typsubscript
3397 *
3398 * Given the type OID, return the type's subscripting handler's OID,
3399 * if it has one.
3400 *
3401 * If typelemp isn't NULL, we also store the type's typelem value there.
3402 * This saves some callers an extra catalog lookup.
3403 */
3406{
3407 HeapTuple tp;
3408
3410 if (HeapTupleIsValid(tp))
3411 {
3413 RegProcedure handler = typform->typsubscript;
3414
3415 if (typelemp)
3416 *typelemp = typform->typelem;
3417 ReleaseSysCache(tp);
3418 return handler;
3419 }
3420 else
3421 {
3422 if (typelemp)
3424 return InvalidOid;
3425 }
3426}
3427
3428/*
3429 * getSubscriptingRoutines
3430 *
3431 * Given the type OID, fetch the type's subscripting methods struct.
3432 * Return NULL if type is not subscriptable.
3433 *
3434 * If typelemp isn't NULL, we also store the type's typelem value there.
3435 * This saves some callers an extra catalog lookup.
3436 */
3437const struct SubscriptRoutines *
3439{
3440 RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3441
3442 if (!OidIsValid(typsubscript))
3443 return NULL;
3444
3445 return (const struct SubscriptRoutines *)
3446 DatumGetPointer(OidFunctionCall0(typsubscript));
3447}
3448
3449
3450/* ---------- STATISTICS CACHE ---------- */
3451
3452/*
3453 * get_attavgwidth
3454 *
3455 * Given the table and attribute number of a column, get the average
3456 * width of entries in the column. Return zero if no data available.
3457 *
3458 * Currently this is only consulted for individual tables, not for inheritance
3459 * trees, so we don't need an "inh" parameter.
3460 *
3461 * Calling a hook at this point looks somewhat strange, but is required
3462 * because the optimizer calls this function without any other way for
3463 * plug-ins to control the result.
3464 */
3465int32
3467{
3468 HeapTuple tp;
3469 int32 stawidth;
3470
3472 {
3473 stawidth = (*get_attavgwidth_hook) (relid, attnum);
3474 if (stawidth > 0)
3475 return stawidth;
3476 }
3478 ObjectIdGetDatum(relid),
3480 BoolGetDatum(false));
3481 if (HeapTupleIsValid(tp))
3482 {
3483 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3484 ReleaseSysCache(tp);
3485 if (stawidth > 0)
3486 return stawidth;
3487 }
3488 return 0;
3489}
3490
3491/*
3492 * get_attstatsslot
3493 *
3494 * Extract the contents of a "slot" of a pg_statistic tuple.
3495 * Returns true if requested slot type was found, else false.
3496 *
3497 * Unlike other routines in this file, this takes a pointer to an
3498 * already-looked-up tuple in the pg_statistic cache. We do this since
3499 * most callers will want to extract more than one value from the cache
3500 * entry, and we don't want to repeat the cache lookup unnecessarily.
3501 * Also, this API allows this routine to be used with statistics tuples
3502 * that have been provided by a stats hook and didn't really come from
3503 * pg_statistic.
3504 *
3505 * sslot: pointer to output area (typically, a local variable in the caller).
3506 * statstuple: pg_statistic tuple to be examined.
3507 * reqkind: STAKIND code for desired statistics slot kind.
3508 * reqop: STAOP value wanted, or InvalidOid if don't care.
3509 * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3510 *
3511 * If a matching slot is found, true is returned, and *sslot is filled thus:
3512 * staop: receives the actual STAOP value.
3513 * stacoll: receives the actual STACOLL value.
3514 * valuetype: receives actual datatype of the elements of stavalues.
3515 * values: receives pointer to an array of the slot's stavalues.
3516 * nvalues: receives number of stavalues.
3517 * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3518 * nnumbers: receives number of stanumbers.
3519 *
3520 * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3521 * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3522 * ATTSTATSSLOT_NUMBERS wasn't specified.
3523 *
3524 * If no matching slot is found, false is returned, and *sslot is zeroed.
3525 *
3526 * Note that the current API doesn't allow for searching for a slot with
3527 * a particular collation. If we ever actually support recording more than
3528 * one collation, we'll have to extend the API, but for now simple is good.
3529 *
3530 * The data referred to by the fields of sslot is locally palloc'd and
3531 * is independent of the original pg_statistic tuple. When the caller
3532 * is done with it, call free_attstatsslot to release the palloc'd data.
3533 *
3534 * If it's desirable to call free_attstatsslot when get_attstatsslot might
3535 * not have been called, memset'ing sslot to zeroes will allow that.
3536 *
3537 * Passing flags=0 can be useful to quickly check if the requested slot type
3538 * exists. In this case no arrays are extracted, so free_attstatsslot need
3539 * not be called.
3540 */
3541bool
3543 int reqkind, Oid reqop, int flags)
3544{
3546 int i;
3547 Datum val;
3550 int narrayelem;
3553
3554 /* initialize *sslot properly */
3555 memset(sslot, 0, sizeof(AttStatsSlot));
3556
3557 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3558 {
3559 if ((&stats->stakind1)[i] == reqkind &&
3560 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3561 break;
3562 }
3563 if (i >= STATISTIC_NUM_SLOTS)
3564 return false; /* not there */
3565
3566 sslot->staop = (&stats->staop1)[i];
3567 sslot->stacoll = (&stats->stacoll1)[i];
3568
3569 if (flags & ATTSTATSSLOT_VALUES)
3570 {
3573
3574 /*
3575 * Detoast the array if needed, and in any case make a copy that's
3576 * under control of this AttStatsSlot.
3577 */
3579
3580 /*
3581 * Extract the actual array element type, and pass it back in case the
3582 * caller needs it.
3583 */
3584 sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3585
3586 /* Need info about element type */
3589 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3591
3592 /* Deconstruct array into Datum elements; NULLs not expected */
3595 typeForm->typlen,
3596 typeForm->typbyval,
3597 typeForm->typalign,
3598 &sslot->values, NULL, &sslot->nvalues);
3599
3600 /*
3601 * If the element type is pass-by-reference, we now have a bunch of
3602 * Datums that are pointers into the statarray, so we need to keep
3603 * that until free_attstatsslot. Otherwise, all the useful info is in
3604 * sslot->values[], so we can free the array object immediately.
3605 */
3606 if (!typeForm->typbyval)
3607 sslot->values_arr = statarray;
3608 else
3610
3612 }
3613
3614 if (flags & ATTSTATSSLOT_NUMBERS)
3615 {
3618
3619 /*
3620 * Detoast the array if needed, and in any case make a copy that's
3621 * under control of this AttStatsSlot.
3622 */
3624
3625 /*
3626 * We expect the array to be a 1-D float4 array; verify that. We don't
3627 * need to use deconstruct_array() since the array data is just going
3628 * to look like a C array of float4 values.
3629 */
3631 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3634 elog(ERROR, "stanumbers is not a 1-D float4 array");
3635
3636 /* Give caller a pointer directly into the statarray */
3637 sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3638 sslot->nnumbers = narrayelem;
3639
3640 /* We'll free the statarray in free_attstatsslot */
3641 sslot->numbers_arr = statarray;
3642 }
3643
3644 return true;
3645}
3646
3647/*
3648 * free_attstatsslot
3649 * Free data allocated by get_attstatsslot
3650 */
3651void
3653{
3654 /* The values[] array was separately palloc'd by deconstruct_array */
3655 if (sslot->values)
3656 pfree(sslot->values);
3657 /* The numbers[] array points into numbers_arr, do not pfree it */
3658 /* Free the detoasted array objects, if any */
3659 if (sslot->values_arr)
3660 pfree(sslot->values_arr);
3661 if (sslot->numbers_arr)
3662 pfree(sslot->numbers_arr);
3663}
3664
3665/* ---------- PG_NAMESPACE CACHE ---------- */
3666
3667/*
3668 * get_namespace_name
3669 * Returns the name of a given namespace
3670 *
3671 * Returns a palloc'd copy of the string, or NULL if no such namespace.
3672 */
3673char *
3675{
3676 HeapTuple tp;
3677
3679 if (HeapTupleIsValid(tp))
3680 {
3682 char *result;
3683
3684 result = pstrdup(NameStr(nsptup->nspname));
3685 ReleaseSysCache(tp);
3686 return result;
3687 }
3688 else
3689 return NULL;
3690}
3691
3692/*
3693 * get_namespace_name_or_temp
3694 * As above, but if it is this backend's temporary namespace, return
3695 * "pg_temp" instead.
3696 */
3697char *
3699{
3701 return pstrdup("pg_temp");
3702 else
3703 return get_namespace_name(nspid);
3704}
3705
3706/*
3707 * get_qualified_objname
3708 * Returns a palloc'd string containing the schema-qualified name of the
3709 * object for the given namespace ID and object name.
3710 */
3711char *
3713{
3714 char *nspname;
3715 char *result;
3716
3718 if (!nspname)
3719 elog(ERROR, "cache lookup failed for namespace %u", nspid);
3720
3721 result = quote_qualified_identifier(nspname, objname);
3722
3723 return result;
3724}
3725
3726/* ---------- PG_RANGE CACHES ---------- */
3727
3728/*
3729 * get_range_subtype
3730 * Returns the subtype of a given range type
3731 *
3732 * Returns InvalidOid if the type is not a range type.
3733 */
3734Oid
3736{
3737 HeapTuple tp;
3738
3740 if (HeapTupleIsValid(tp))
3741 {
3743 Oid result;
3744
3745 result = rngtup->rngsubtype;
3746 ReleaseSysCache(tp);
3747 return result;
3748 }
3749 else
3750 return InvalidOid;
3751}
3752
3753/*
3754 * get_range_collation
3755 * Returns the collation of a given range type
3756 *
3757 * Returns InvalidOid if the type is not a range type,
3758 * or if its subtype is not collatable.
3759 */
3760Oid
3762{
3763 HeapTuple tp;
3764
3766 if (HeapTupleIsValid(tp))
3767 {
3769 Oid result;
3770
3771 result = rngtup->rngcollation;
3772 ReleaseSysCache(tp);
3773 return result;
3774 }
3775 else
3776 return InvalidOid;
3777}
3778
3779/*
3780 * get_range_constructor2
3781 * Gets the 2-arg constructor for the given rangetype.
3782 *
3783 * Raises an error if not found.
3784 */
3787{
3788 HeapTuple tp;
3789
3791 if (HeapTupleIsValid(tp))
3792 {
3795
3796 result = rngtup->rngconstruct2;
3797 ReleaseSysCache(tp);
3798 return result;
3799 }
3800 else
3801 elog(ERROR, "cache lookup failed for range type %u", rangeOid);
3802}
3803
3804/*
3805 * get_range_multirange
3806 * Returns the multirange type of a given range type
3807 *
3808 * Returns InvalidOid if the type is not a range type.
3809 */
3810Oid
3812{
3813 HeapTuple tp;
3814
3816 if (HeapTupleIsValid(tp))
3817 {
3819 Oid result;
3820
3821 result = rngtup->rngmultitypid;
3822 ReleaseSysCache(tp);
3823 return result;
3824 }
3825 else
3826 return InvalidOid;
3827}
3828
3829/*
3830 * get_multirange_range
3831 * Returns the range type of a given multirange
3832 *
3833 * Returns InvalidOid if the type is not a multirange.
3834 */
3835Oid
3837{
3838 HeapTuple tp;
3839
3841 if (HeapTupleIsValid(tp))
3842 {
3844 Oid result;
3845
3846 result = rngtup->rngtypid;
3847 ReleaseSysCache(tp);
3848 return result;
3849 }
3850 else
3851 return InvalidOid;
3852}
3853
3854/* ---------- PG_INDEX CACHE ---------- */
3855
3856/*
3857 * get_index_column_opclass
3858 *
3859 * Given the index OID and column number,
3860 * return opclass of the index column
3861 * or InvalidOid if the index was not found
3862 * or column is non-key one.
3863 */
3864Oid
3866{
3867 HeapTuple tuple;
3868 Form_pg_index rd_index;
3869 Datum datum;
3871 Oid opclass;
3872
3873 /* First we need to know the column's opclass. */
3874
3876 if (!HeapTupleIsValid(tuple))
3877 return InvalidOid;
3878
3879 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3880
3881 /* caller is supposed to guarantee this */
3882 Assert(attno > 0 && attno <= rd_index->indnatts);
3883
3884 /* Non-key attributes don't have an opclass */
3885 if (attno > rd_index->indnkeyatts)
3886 {
3887 ReleaseSysCache(tuple);
3888 return InvalidOid;
3889 }
3890
3892 indclass = ((oidvector *) DatumGetPointer(datum));
3893
3895 opclass = indclass->values[attno - 1];
3896
3897 ReleaseSysCache(tuple);
3898
3899 return opclass;
3900}
3901
3902/*
3903 * get_index_isreplident
3904 *
3905 * Given the index OID, return pg_index.indisreplident.
3906 */
3907bool
3909{
3910 HeapTuple tuple;
3911 Form_pg_index rd_index;
3912 bool result;
3913
3915 if (!HeapTupleIsValid(tuple))
3916 return false;
3917
3918 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3919 result = rd_index->indisreplident;
3920 ReleaseSysCache(tuple);
3921
3922 return result;
3923}
3924
3925/*
3926 * get_index_isvalid
3927 *
3928 * Given the index OID, return pg_index.indisvalid.
3929 */
3930bool
3932{
3933 bool isvalid;
3934 HeapTuple tuple;
3935 Form_pg_index rd_index;
3936
3938 if (!HeapTupleIsValid(tuple))
3939 elog(ERROR, "cache lookup failed for index %u", index_oid);
3940
3941 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3942 isvalid = rd_index->indisvalid;
3943 ReleaseSysCache(tuple);
3944
3945 return isvalid;
3946}
3947
3948/*
3949 * get_index_isclustered
3950 *
3951 * Given the index OID, return pg_index.indisclustered.
3952 */
3953bool
3955{
3956 bool isclustered;
3957 HeapTuple tuple;
3958 Form_pg_index rd_index;
3959
3961 if (!HeapTupleIsValid(tuple))
3962 elog(ERROR, "cache lookup failed for index %u", index_oid);
3963
3964 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3965 isclustered = rd_index->indisclustered;
3966 ReleaseSysCache(tuple);
3967
3968 return isclustered;
3969}
3970
3971/*
3972 * get_publication_oid - given a publication name, look up the OID
3973 *
3974 * If missing_ok is false, throw an error if name not found. If true, just
3975 * return InvalidOid.
3976 */
3977Oid
3978get_publication_oid(const char *pubname, bool missing_ok)
3979{
3980 Oid oid;
3981
3983 CStringGetDatum(pubname));
3984 if (!OidIsValid(oid) && !missing_ok)
3985 ereport(ERROR,
3987 errmsg("publication \"%s\" does not exist", pubname)));
3988 return oid;
3989}
3990
3991/*
3992 * get_publication_name - given a publication Oid, look up the name
3993 *
3994 * If missing_ok is false, throw an error if name not found. If true, just
3995 * return NULL.
3996 */
3997char *
3998get_publication_name(Oid pubid, bool missing_ok)
3999{
4000 HeapTuple tup;
4001 char *pubname;
4003
4005
4006 if (!HeapTupleIsValid(tup))
4007 {
4008 if (!missing_ok)
4009 elog(ERROR, "cache lookup failed for publication %u", pubid);
4010 return NULL;
4011 }
4012
4014 pubname = pstrdup(NameStr(pubform->pubname));
4015
4017
4018 return pubname;
4019}
4020
4021/*
4022 * get_subscription_oid - given a subscription name, look up the OID
4023 *
4024 * If missing_ok is false, throw an error if name not found. If true, just
4025 * return InvalidOid.
4026 */
4027Oid
4028get_subscription_oid(const char *subname, bool missing_ok)
4029{
4030 Oid oid;
4031
4034 if (!OidIsValid(oid) && !missing_ok)
4035 ereport(ERROR,
4037 errmsg("subscription \"%s\" does not exist", subname)));
4038 return oid;
4039}
4040
4041/*
4042 * get_subscription_name - given a subscription OID, look up the name
4043 *
4044 * If missing_ok is false, throw an error if name not found. If true, just
4045 * return NULL.
4046 */
4047char *
4048get_subscription_name(Oid subid, bool missing_ok)
4049{
4050 HeapTuple tup;
4051 char *subname;
4053
4055
4056 if (!HeapTupleIsValid(tup))
4057 {
4058 if (!missing_ok)
4059 elog(ERROR, "cache lookup failed for subscription %u", subid);
4060 return NULL;
4061 }
4062
4064 subname = pstrdup(NameStr(subform->subname));
4065
4067
4068 return subname;
4069}
4070
4071char *
4073{
4074 HeapTuple tuple;
4075 char *labelname;
4076
4078 if (!tuple)
4079 {
4080 elog(ERROR, "cache lookup failed for label %u", labeloid);
4081 return NULL;
4082 }
4084 ReleaseSysCache(tuple);
4085
4086 return labelname;
4087}
4088
4089char *
4091{
4092 HeapTuple tuple;
4093 char *propname;
4094
4096 if (!tuple)
4097 {
4098 elog(ERROR, "cache lookup failed for property %u", propoid);
4099 return NULL;
4100 }
4102 ReleaseSysCache(tuple);
4103
4104 return propname;
4105}
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:835
#define Assert(condition)
Definition c.h:943
int16_t int16
Definition c.h:619
regproc RegProcedure
Definition c.h:734
int32_t int32
Definition c.h:620
float float4
Definition c.h:713
#define OidIsValid(objectId)
Definition c.h:858
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:3735
char * get_rel_name(Oid relid)
Definition lsyscache.c:2234
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:2029
Oid get_opclass_method(Oid opclass)
Definition lsyscache.c:1504
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:2333
char * get_propgraph_property_name(Oid propoid)
Definition lsyscache.c:4090
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:947
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2384
char get_func_prokind(Oid funcid)
Definition lsyscache.c:2124
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3931
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition lsyscache.c:1225
RegProcedure get_range_constructor2(Oid rangeOid)
Definition lsyscache.c:3786
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition lsyscache.c:3281
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:1076
RegProcedure get_oprrest(Oid opno)
Definition lsyscache.c:1863
void free_attstatsslot(AttStatsSlot *sslot)
Definition lsyscache.c:3652
bool comparison_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:886
Oid get_constraint_index(Oid conoid)
Definition lsyscache.c:1331
bool get_func_retset(Oid funcid)
Definition lsyscache.c:2048
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:3067
Oid get_opclass_input_type(Oid opclass)
Definition lsyscache.c:1456
bool type_is_rowtype(Oid typid)
Definition lsyscache.c:2963
bool type_is_range(Oid typid)
Definition lsyscache.c:2996
char func_parallel(Oid funcid)
Definition lsyscache.c:2105
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1434
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1106
bool type_is_enum(Oid typid)
Definition lsyscache.c:2986
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3836
Oid get_typmodin(Oid typid)
Definition lsyscache.c:3314
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:2727
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition lsyscache.c:1479
RegProcedure get_func_support(Oid funcid)
Definition lsyscache.c:2164
char * get_database_name(Oid dbid)
Definition lsyscache.c:1384
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3215
bool get_typisdefined(Oid typid)
Definition lsyscache.c:2479
char * get_opname(Oid opno)
Definition lsyscache.c:1602
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1188
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2577
int32 get_attavgwidth(Oid relid, AttrNumber attnum)
Definition lsyscache.c:3466
bool get_index_isreplident(Oid index_oid)
Definition lsyscache.c:3908
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:1014
RegProcedure get_oprjoin(Oid opno)
Definition lsyscache.c:1887
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition lsyscache.c:326
bool op_strict(Oid opno)
Definition lsyscache.c:1783
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1731
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2309
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2557
Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
Definition lsyscache.c:2002
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition lsyscache.c:3978
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2258
static bool get_opmethod_canorder(Oid amoid)
Definition lsyscache.c:223
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1577
Oid get_typcollation(Oid typid)
Definition lsyscache.c:3364
Oid get_op_rettype(Oid opno)
Definition lsyscache.c:1625
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:87
char * get_collation_name(Oid colloid)
Definition lsyscache.c:1253
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2285
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1405
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3698
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3182
char func_volatile(Oid funcid)
Definition lsyscache.c:2086
bool equality_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:834
get_attavgwidth_hook_type get_attavgwidth_hook
Definition lsyscache.c:57
bool op_is_safe_index_member(Oid opno)
Definition lsyscache.c:972
bool get_index_isclustered(Oid index_oid)
Definition lsyscache.c:3954
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:4072
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:2448
bool func_strict(Oid funcid)
Definition lsyscache.c:2067
Oid get_index_column_opclass(Oid index_oid, int attno)
Definition lsyscache.c:3865
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:1299
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045
bool get_func_leakproof(Oid funcid)
Definition lsyscache.c:2143
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition lsyscache.c:3438
Node * get_typdefault(Oid typid)
Definition lsyscache.c:2756
bool get_collation_isdeterministic(Oid colloid)
Definition lsyscache.c:1272
List * get_op_index_interpretation(Oid opno)
Definition lsyscache.c:729
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition lsyscache.c:4028
char * get_subscription_name(Oid subid, bool missing_ok)
Definition lsyscache.c:4048
Oid get_range_collation(Oid rangeOid)
Definition lsyscache.c:3761
char * get_opfamily_name(Oid opfid, bool missing_ok)
Definition lsyscache.c:1545
char * get_func_name(Oid funcid)
Definition lsyscache.c:1914
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3811
Oid get_rel_relam(Oid relid)
Definition lsyscache.c:2406
char op_volatile(Oid opno)
Definition lsyscache.c:1799
Oid get_func_namespace(Oid funcid)
Definition lsyscache.c:1938
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3389
Oid get_rel_tablespace(Oid relid)
Definition lsyscache.c:2360
int get_func_nargs(Oid funcid)
Definition lsyscache.c:1980
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:2631
int16 get_typlen(Oid typid)
Definition lsyscache.c:2503
Oid get_typ_typrelid(Oid typid)
Definition lsyscache.c:3039
char get_typtype(Oid typid)
Definition lsyscache.c:2937
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:3140
Oid getTypeIOParam(HeapTuple typeTuple)
Definition lsyscache.c:2609
Oid get_opfamily_method(Oid opfid)
Definition lsyscache.c:1528
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition lsyscache.c:2846
char * get_qualified_objname(Oid nspid, char *objname)
Definition lsyscache.c:3712
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition lsyscache.c:2426
char * get_publication_name(Oid pubid, bool missing_ok)
Definition lsyscache.c:3998
Oid getBaseType(Oid typid)
Definition lsyscache.c:2829
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:2528
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1678
List * get_mergejoin_opfamilies(Oid opno)
Definition lsyscache.c:430
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3674
Oid get_array_type(Oid typid)
Definition lsyscache.c:3095
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1961
Oid get_promoted_array_type(Oid typid)
Definition lsyscache.c:3119
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1131
char get_constraint_type(Oid conoid)
Definition lsyscache.c:1361
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition lsyscache.c:2886
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition lsyscache.c:70
RegProcedure get_typsubscript(Oid typid, Oid *typelemp)
Definition lsyscache.c:3405
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
Definition lsyscache.c:3018
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition lsyscache.c:3542
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2191
Oid get_negator(Oid opno)
Definition lsyscache.c:1839
Oid get_commutator(Oid opno)
Definition lsyscache.c:1815
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:1650
bool type_is_multirange(Oid typid)
Definition lsyscache.c:3006
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition lsyscache.c:3248
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition lsyscache.c:1161
#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:135
Definition c.h:815
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