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 */
476bool
479{
480 bool result = false;
482 int i;
483
484 /* Ensure output args are initialized on failure */
485 if (lhs_opno)
487 if (rhs_opno)
489
490 /*
491 * Search pg_amop to see if the target operator is registered as the "="
492 * operator of any hash opfamily. If the operator is registered in
493 * multiple opfamilies, assume we can use any one.
494 */
496
497 for (i = 0; i < catlist->n_members; i++)
498 {
499 HeapTuple tuple = &catlist->members[i]->tuple;
501
502 if (aform->amopmethod == HASH_AM_OID &&
503 aform->amopstrategy == HTEqualStrategyNumber)
504 {
505 /* No extra lookup needed if given operator is single-type */
506 if (aform->amoplefttype == aform->amoprighttype)
507 {
508 if (lhs_opno)
509 *lhs_opno = opno;
510 if (rhs_opno)
511 *rhs_opno = opno;
512 result = true;
513 break;
514 }
515
516 /*
517 * Get the matching single-type operator(s). Failure probably
518 * shouldn't happen --- it implies a bogus opfamily --- but
519 * continue looking if so.
520 */
521 if (lhs_opno)
522 {
523 *lhs_opno = get_opfamily_member(aform->amopfamily,
524 aform->amoplefttype,
525 aform->amoplefttype,
527 if (!OidIsValid(*lhs_opno))
528 continue;
529 /* Matching LHS found, done if caller doesn't want RHS */
530 if (!rhs_opno)
531 {
532 result = true;
533 break;
534 }
535 }
536 if (rhs_opno)
537 {
538 *rhs_opno = get_opfamily_member(aform->amopfamily,
539 aform->amoprighttype,
540 aform->amoprighttype,
542 if (!OidIsValid(*rhs_opno))
543 {
544 /* Forget any LHS operator from this opfamily */
545 if (lhs_opno)
547 continue;
548 }
549 /* Matching RHS found, so done */
550 result = true;
551 break;
552 }
553 }
554 }
555
557
558 return result;
559}
560
561/*
562 * get_op_hash_functions
563 * Get the OID(s) of the standard hash support function(s) compatible with
564 * the given operator, operating on its LHS and/or RHS datatype as required.
565 *
566 * A function for the LHS type is sought and returned into *lhs_procno if
567 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
568 * and returned into *rhs_procno if rhs_procno isn't NULL.
569 *
570 * If the given operator is not cross-type, the results should be the same
571 * function, but in cross-type situations they will be different.
572 *
573 * Returns true if able to find the requested function(s), false if not.
574 * (This indicates that the operator should not have been marked oprcanhash.)
575 */
576bool
579{
580 bool result = false;
582 int i;
583
584 /* Ensure output args are initialized on failure */
585 if (lhs_procno)
587 if (rhs_procno)
589
590 /*
591 * Search pg_amop to see if the target operator is registered as the "="
592 * operator of any hash opfamily. If the operator is registered in
593 * multiple opfamilies, assume we can use any one.
594 */
596
597 for (i = 0; i < catlist->n_members; i++)
598 {
599 HeapTuple tuple = &catlist->members[i]->tuple;
601
602 if (aform->amopmethod == HASH_AM_OID &&
603 aform->amopstrategy == HTEqualStrategyNumber)
604 {
605 /*
606 * Get the matching support function(s). Failure probably
607 * shouldn't happen --- it implies a bogus opfamily --- but
608 * continue looking if so.
609 */
610 if (lhs_procno)
611 {
612 *lhs_procno = get_opfamily_proc(aform->amopfamily,
613 aform->amoplefttype,
614 aform->amoplefttype,
616 if (!OidIsValid(*lhs_procno))
617 continue;
618 /* Matching LHS found, done if caller doesn't want RHS */
619 if (!rhs_procno)
620 {
621 result = true;
622 break;
623 }
624 /* Only one lookup needed if given operator is single-type */
625 if (aform->amoplefttype == aform->amoprighttype)
626 {
628 result = true;
629 break;
630 }
631 }
632 if (rhs_procno)
633 {
634 *rhs_procno = get_opfamily_proc(aform->amopfamily,
635 aform->amoprighttype,
636 aform->amoprighttype,
638 if (!OidIsValid(*rhs_procno))
639 {
640 /* Forget any LHS function from this opfamily */
641 if (lhs_procno)
643 continue;
644 }
645 /* Matching RHS found, so done */
646 result = true;
647 break;
648 }
649 }
650 }
651
653
654 return result;
655}
656
657/*
658 * get_op_index_interpretation
659 * Given an operator's OID, find out which amcanorder opfamilies it belongs to,
660 * and what properties it has within each one. The results are returned
661 * as a palloc'd list of OpIndexInterpretation structs.
662 *
663 * In addition to the normal btree operators, we consider a <> operator to be
664 * a "member" of an opfamily if its negator is an equality operator of the
665 * opfamily. COMPARE_NE is returned as the strategy number for this case.
666 */
667List *
669{
670 List *result = NIL;
673 int i;
674
675 /*
676 * Find all the pg_amop entries containing the operator.
677 */
679
680 for (i = 0; i < catlist->n_members; i++)
681 {
682 HeapTuple op_tuple = &catlist->members[i]->tuple;
684 CompareType cmptype;
685
686 /* must be ordering index */
687 if (!get_opmethod_canorder(op_form->amopmethod))
688 continue;
689
690 /* Get the operator's comparison type */
691 cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
692 op_form->amopmethod,
693 op_form->amopfamily,
694 true);
695
696 /* should not happen */
697 if (cmptype == COMPARE_INVALID)
698 continue;
699
701 thisresult->opfamily_id = op_form->amopfamily;
702 thisresult->cmptype = cmptype;
703 thisresult->oplefttype = op_form->amoplefttype;
704 thisresult->oprighttype = op_form->amoprighttype;
706 }
707
709
710 /*
711 * If we didn't find any btree opfamily containing the operator, perhaps
712 * it is a <> operator. See if it has a negator that is in an opfamily.
713 */
714 if (result == NIL)
715 {
716 Oid op_negator = get_negator(opno);
717
719 {
722
723 for (i = 0; i < catlist->n_members; i++)
724 {
725 HeapTuple op_tuple = &catlist->members[i]->tuple;
727 const IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
728 CompareType cmptype;
729
730 /* must be ordering index */
731 if (!amroutine->amcanorder)
732 continue;
733
734 /* Get the operator's comparison type */
735 cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
736 op_form->amopmethod,
737 op_form->amopfamily,
738 true);
739
740 /* Only consider negators that are = */
741 if (cmptype != COMPARE_EQ)
742 continue;
743
744 /* OK, report it as COMPARE_NE */
746 thisresult->opfamily_id = op_form->amopfamily;
747 thisresult->cmptype = COMPARE_NE;
748 thisresult->oplefttype = op_form->amoplefttype;
749 thisresult->oprighttype = op_form->amoprighttype;
751 }
752
754 }
755 }
756
757 return result;
758}
759
760/*
761 * equality_ops_are_compatible
762 * Return true if the two given equality operators have compatible
763 * semantics.
764 *
765 * This is trivially true if they are the same operator. Otherwise,
766 * we look to see if they both belong to an opfamily that guarantees
767 * compatible semantics for equality. Either finding allows us to assume
768 * that they have compatible notions of equality. (The reason we need
769 * to do these pushups is that one might be a cross-type operator; for
770 * instance int24eq vs int4eq.)
771 */
772bool
774{
775 bool result;
777 int i;
778
779 /* Easy if they're the same operator */
780 if (opno1 == opno2)
781 return true;
782
783 /*
784 * We search through all the pg_amop entries for opno1.
785 */
787
788 result = false;
789 for (i = 0; i < catlist->n_members; i++)
790 {
791 HeapTuple op_tuple = &catlist->members[i]->tuple;
793
794 /*
795 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
796 * check it first
797 */
798 if (op_in_opfamily(opno2, op_form->amopfamily) &&
800 {
801 result = true;
802 break;
803 }
804 }
805
807
808 return result;
809}
810
811/*
812 * comparison_ops_are_compatible
813 * Return true if the two given comparison operators have compatible
814 * semantics.
815 *
816 * This is trivially true if they are the same operator. Otherwise, we look
817 * to see if they both belong to an opfamily that guarantees compatible
818 * semantics for ordering. (For example, for btree, '<' and '>=' ops match if
819 * they belong to the same family.)
820 *
821 * (This is identical to equality_ops_are_compatible(), except that we check
822 * amconsistentordering instead of amconsistentequality.)
823 */
824bool
826{
827 bool result;
829 int i;
830
831 /* Easy if they're the same operator */
832 if (opno1 == opno2)
833 return true;
834
835 /*
836 * We search through all the pg_amop entries for opno1.
837 */
839
840 result = false;
841 for (i = 0; i < catlist->n_members; i++)
842 {
843 HeapTuple op_tuple = &catlist->members[i]->tuple;
845
846 /*
847 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
848 * check it first
849 */
850 if (op_in_opfamily(opno2, op_form->amopfamily) &&
852 {
853 result = true;
854 break;
855 }
856 }
857
859
860 return result;
861}
862
863/*
864 * collations_agree_on_equality
865 * Return true if the two collations have equivalent notions of equality,
866 * so that a uniqueness or equality proof established under one side
867 * carries over to a comparison performed under the other side.
868 *
869 * Note: this is equality compatibility only. Do NOT use this to reason
870 * about ordering.
871 *
872 * An InvalidOid on either side denotes the absence of a collation -- that
873 * side's operation is not collation-sensitive (e.g. a non-collatable column
874 * type). Absence of a collation cannot conflict with the other side's
875 * collation, so we treat such pairs as agreeing on equality. This generalizes
876 * the asymmetric treatment in IndexCollMatchesExprColl().
877 *
878 * Otherwise the collations have equivalent equality if they match, or if both
879 * are deterministic: by definition a deterministic collation treats two
880 * strings as equal iff they are byte-wise equal (see CREATE COLLATION), so any
881 * two deterministic collations share the same equality relation. A mismatch
882 * involving a nondeterministic collation, however, may mean the two equality
883 * relations disagree, and the proof is unsound.
884 */
885bool
887{
888 if (!OidIsValid(coll1) || !OidIsValid(coll2))
889 return true;
890
891 if (coll1 == coll2)
892 return true;
893
896 return false;
897
898 return true;
899}
900
901/*
902 * op_is_safe_index_member
903 * Check if the operator is a member of a B-tree or Hash operator family.
904 *
905 * We use this check as a proxy for "null-safety": if an operator is trusted by
906 * the btree or hash opfamily, it implies that the operator adheres to standard
907 * boolean behavior, and would not return NULL when given valid non-null
908 * inputs, as doing so would break index integrity.
909 */
910bool
912{
913 bool result = false;
915 int i;
916
917 /*
918 * Search pg_amop to see if the target operator is registered for any
919 * btree or hash opfamily.
920 */
922
923 for (i = 0; i < catlist->n_members; i++)
924 {
925 HeapTuple tuple = &catlist->members[i]->tuple;
927
928 /* Check if the AM is B-tree or Hash */
929 if (aform->amopmethod == BTREE_AM_OID ||
930 aform->amopmethod == HASH_AM_OID)
931 {
932 result = true;
933 break;
934 }
935 }
936
938
939 return result;
940}
941
942
943/* ---------- AMPROC CACHES ---------- */
944
945/*
946 * get_opfamily_proc
947 * Get the OID of the specified support function
948 * for the specified opfamily and datatypes.
949 *
950 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
951 */
952Oid
953get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
954{
955 HeapTuple tp;
958
960 ObjectIdGetDatum(opfamily),
961 ObjectIdGetDatum(lefttype),
962 ObjectIdGetDatum(righttype),
964 if (!HeapTupleIsValid(tp))
965 return InvalidOid;
967 result = amproc_tup->amproc;
968 ReleaseSysCache(tp);
969 return result;
970}
971
972
973/* ---------- ATTRIBUTE CACHES ---------- */
974
975/*
976 * get_attname
977 * Given the relation id and the attribute number, return the "attname"
978 * field from the attribute relation as a palloc'ed string.
979 *
980 * If no such attribute exists and missing_ok is true, NULL is returned;
981 * otherwise a not-intended-for-user-consumption error is thrown.
982 */
983char *
984get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
985{
986 HeapTuple tp;
987
990 if (HeapTupleIsValid(tp))
991 {
993 char *result;
994
995 result = pstrdup(NameStr(att_tup->attname));
996 ReleaseSysCache(tp);
997 return result;
998 }
999
1000 if (!missing_ok)
1001 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1002 attnum, relid);
1003 return NULL;
1004}
1005
1006/*
1007 * get_attnum
1008 *
1009 * Given the relation id and the attribute name,
1010 * return the "attnum" field from the attribute relation.
1011 *
1012 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
1013 */
1015get_attnum(Oid relid, const char *attname)
1016{
1017 HeapTuple tp;
1018
1019 tp = SearchSysCacheAttName(relid, attname);
1020 if (HeapTupleIsValid(tp))
1021 {
1024
1025 result = att_tup->attnum;
1026 ReleaseSysCache(tp);
1027 return result;
1028 }
1029 else
1030 return InvalidAttrNumber;
1031}
1032
1033/*
1034 * get_attgenerated
1035 *
1036 * Given the relation id and the attribute number,
1037 * return the "attgenerated" field from the attribute relation.
1038 *
1039 * Errors if not found.
1040 *
1041 * Since not generated is represented by '\0', this can also be used as a
1042 * Boolean test.
1043 */
1044char
1046{
1047 HeapTuple tp;
1049 char result;
1050
1052 ObjectIdGetDatum(relid),
1054 if (!HeapTupleIsValid(tp))
1055 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1056 attnum, relid);
1058 result = att_tup->attgenerated;
1059 ReleaseSysCache(tp);
1060 return result;
1061}
1062
1063/*
1064 * get_atttype
1065 *
1066 * Given the relation OID and the attribute number with the relation,
1067 * return the attribute type OID.
1068 */
1069Oid
1071{
1072 HeapTuple tp;
1073
1075 ObjectIdGetDatum(relid),
1077 if (HeapTupleIsValid(tp))
1078 {
1080 Oid result;
1081
1082 result = att_tup->atttypid;
1083 ReleaseSysCache(tp);
1084 return result;
1085 }
1086 else
1087 return InvalidOid;
1088}
1089
1090/*
1091 * get_atttypetypmodcoll
1092 *
1093 * A three-fer: given the relation id and the attribute number,
1094 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
1095 *
1096 * Unlike the otherwise-similar get_atttype, this routine
1097 * raises an error if it can't obtain the information.
1098 */
1099void
1101 Oid *typid, int32 *typmod, Oid *collid)
1102{
1103 HeapTuple tp;
1105
1107 ObjectIdGetDatum(relid),
1109 if (!HeapTupleIsValid(tp))
1110 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1111 attnum, relid);
1113
1114 *typid = att_tup->atttypid;
1115 *typmod = att_tup->atttypmod;
1116 *collid = att_tup->attcollation;
1117 ReleaseSysCache(tp);
1118}
1119
1120/*
1121 * get_attoptions
1122 *
1123 * Given the relation id and the attribute number,
1124 * return the attribute options text[] datum, if any.
1125 */
1126Datum
1128{
1129 HeapTuple tuple;
1130 Datum attopts;
1131 Datum result;
1132 bool isnull;
1133
1134 tuple = SearchSysCache2(ATTNUM,
1135 ObjectIdGetDatum(relid),
1137
1138 if (!HeapTupleIsValid(tuple))
1139 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1140 attnum, relid);
1141
1143 &isnull);
1144
1145 if (isnull)
1146 result = (Datum) 0;
1147 else
1148 result = datumCopy(attopts, false, -1); /* text[] */
1149
1150 ReleaseSysCache(tuple);
1151
1152 return result;
1153}
1154
1155/* ---------- PG_CAST CACHE ---------- */
1156
1157/*
1158 * get_cast_oid - given two type OIDs, look up a cast OID
1159 *
1160 * If missing_ok is false, throw an error if the cast is not found. If
1161 * true, just return InvalidOid.
1162 */
1163Oid
1165{
1166 Oid oid;
1167
1171 if (!OidIsValid(oid) && !missing_ok)
1172 ereport(ERROR,
1174 errmsg("cast from type %s to type %s does not exist",
1177 return oid;
1178}
1179
1180/* ---------- COLLATION CACHE ---------- */
1181
1182/*
1183 * get_collation_name
1184 * Returns the name of a given pg_collation entry.
1185 *
1186 * Returns a palloc'd copy of the string, or NULL if no such collation.
1187 *
1188 * NOTE: since collation name is not unique, be wary of code that uses this
1189 * for anything except preparing error messages.
1190 */
1191char *
1193{
1194 HeapTuple tp;
1195
1197 if (HeapTupleIsValid(tp))
1198 {
1200 char *result;
1201
1202 result = pstrdup(NameStr(colltup->collname));
1203 ReleaseSysCache(tp);
1204 return result;
1205 }
1206 else
1207 return NULL;
1208}
1209
1210bool
1212{
1213 HeapTuple tp;
1215 bool result;
1216
1218 if (!HeapTupleIsValid(tp))
1219 elog(ERROR, "cache lookup failed for collation %u", colloid);
1221 result = colltup->collisdeterministic;
1222 ReleaseSysCache(tp);
1223 return result;
1224}
1225
1226/* ---------- CONSTRAINT CACHE ---------- */
1227
1228/*
1229 * get_constraint_name
1230 * Returns the name of a given pg_constraint entry.
1231 *
1232 * Returns a palloc'd copy of the string, or NULL if no such constraint.
1233 *
1234 * NOTE: since constraint name is not unique, be wary of code that uses this
1235 * for anything except preparing error messages.
1236 */
1237char *
1239{
1240 HeapTuple tp;
1241
1243 if (HeapTupleIsValid(tp))
1244 {
1246 char *result;
1247
1248 result = pstrdup(NameStr(contup->conname));
1249 ReleaseSysCache(tp);
1250 return result;
1251 }
1252 else
1253 return NULL;
1254}
1255
1256/*
1257 * get_constraint_index
1258 * Given the OID of a unique, primary-key, or exclusion constraint,
1259 * return the OID of the underlying index.
1260 *
1261 * Returns InvalidOid if the constraint could not be found or is of
1262 * the wrong type.
1263 *
1264 * The intent of this function is to return the index "owned" by the
1265 * specified constraint. Therefore we must check contype, since some
1266 * pg_constraint entries (e.g. for foreign-key constraints) store the
1267 * OID of an index that is referenced but not owned by the constraint.
1268 */
1269Oid
1271{
1272 HeapTuple tp;
1273
1275 if (HeapTupleIsValid(tp))
1276 {
1278 Oid result;
1279
1280 if (contup->contype == CONSTRAINT_UNIQUE ||
1281 contup->contype == CONSTRAINT_PRIMARY ||
1282 contup->contype == CONSTRAINT_EXCLUSION)
1283 result = contup->conindid;
1284 else
1286 ReleaseSysCache(tp);
1287 return result;
1288 }
1289 else
1290 return InvalidOid;
1291}
1292
1293/*
1294 * get_constraint_type
1295 * Return the pg_constraint.contype value for the given constraint.
1296 *
1297 * No frills.
1298 */
1299char
1301{
1302 HeapTuple tp;
1303 char contype;
1304
1306 if (!HeapTupleIsValid(tp))
1307 elog(ERROR, "cache lookup failed for constraint %u", conoid);
1308
1309 contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
1310 ReleaseSysCache(tp);
1311
1312 return contype;
1313}
1314
1315/* ---------- DATABASE CACHE ---------- */
1316
1317/*
1318 * get_database_name - given a database OID, look up the name
1319 *
1320 * Returns a palloc'd string, or NULL if no such database.
1321 */
1322char *
1324{
1326 char *result;
1327
1330 {
1333 }
1334 else
1335 result = NULL;
1336
1337 return result;
1338}
1339
1340
1341/* ---------- LANGUAGE CACHE ---------- */
1342
1343char *
1345{
1346 HeapTuple tp;
1347
1349 if (HeapTupleIsValid(tp))
1350 {
1352 char *result;
1353
1354 result = pstrdup(NameStr(lantup->lanname));
1355 ReleaseSysCache(tp);
1356 return result;
1357 }
1358
1359 if (!missing_ok)
1360 elog(ERROR, "cache lookup failed for language %u",
1361 langoid);
1362 return NULL;
1363}
1364
1365/* ---------- OPCLASS CACHE ---------- */
1366
1367/*
1368 * get_opclass_family
1369 *
1370 * Returns the OID of the operator family the opclass belongs to.
1371 */
1372Oid
1374{
1375 HeapTuple tp;
1377 Oid result;
1378
1379 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1380 if (!HeapTupleIsValid(tp))
1381 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1383
1384 result = cla_tup->opcfamily;
1385 ReleaseSysCache(tp);
1386 return result;
1387}
1388
1389/*
1390 * get_opclass_input_type
1391 *
1392 * Returns the OID of the datatype the opclass indexes.
1393 */
1394Oid
1396{
1397 HeapTuple tp;
1399 Oid result;
1400
1401 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1402 if (!HeapTupleIsValid(tp))
1403 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1405
1406 result = cla_tup->opcintype;
1407 ReleaseSysCache(tp);
1408 return result;
1409}
1410
1411/*
1412 * get_opclass_opfamily_and_input_type
1413 *
1414 * Returns the OID of the operator family the opclass belongs to,
1415 * the OID of the datatype the opclass indexes
1416 */
1417bool
1418get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1419{
1420 HeapTuple tp;
1422
1423 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1424 if (!HeapTupleIsValid(tp))
1425 return false;
1426
1428
1429 *opfamily = cla_tup->opcfamily;
1430 *opcintype = cla_tup->opcintype;
1431
1432 ReleaseSysCache(tp);
1433
1434 return true;
1435}
1436
1437/*
1438 * get_opclass_method
1439 *
1440 * Returns the OID of the index access method the opclass belongs to.
1441 */
1442Oid
1444{
1445 HeapTuple tp;
1447 Oid result;
1448
1449 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1450 if (!HeapTupleIsValid(tp))
1451 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1453
1454 result = cla_tup->opcmethod;
1455 ReleaseSysCache(tp);
1456 return result;
1457}
1458
1459/* ---------- OPFAMILY CACHE ---------- */
1460
1461/*
1462 * get_opfamily_method
1463 *
1464 * Returns the OID of the index access method the opfamily is for.
1465 */
1466Oid
1468{
1469 HeapTuple tp;
1471 Oid result;
1472
1474 if (!HeapTupleIsValid(tp))
1475 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1477
1478 result = opfform->opfmethod;
1479 ReleaseSysCache(tp);
1480 return result;
1481}
1482
1483char *
1484get_opfamily_name(Oid opfid, bool missing_ok)
1485{
1486 HeapTuple tup;
1487 char *opfname;
1489
1491
1492 if (!HeapTupleIsValid(tup))
1493 {
1494 if (!missing_ok)
1495 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1496 return NULL;
1497 }
1498
1500 opfname = pstrdup(NameStr(opfform->opfname));
1501
1503
1504 return opfname;
1505}
1506
1507/* ---------- OPERATOR CACHE ---------- */
1508
1509/*
1510 * get_opcode
1511 *
1512 * Returns the regproc id of the routine used to implement an
1513 * operator given the operator oid.
1514 */
1517{
1518 HeapTuple tp;
1519
1521 if (HeapTupleIsValid(tp))
1522 {
1525
1526 result = optup->oprcode;
1527 ReleaseSysCache(tp);
1528 return result;
1529 }
1530 else
1531 return (RegProcedure) InvalidOid;
1532}
1533
1534/*
1535 * get_opname
1536 * returns the name of the operator with the given opno
1537 *
1538 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1539 */
1540char *
1542{
1543 HeapTuple tp;
1544
1546 if (HeapTupleIsValid(tp))
1547 {
1549 char *result;
1550
1551 result = pstrdup(NameStr(optup->oprname));
1552 ReleaseSysCache(tp);
1553 return result;
1554 }
1555 else
1556 return NULL;
1557}
1558
1559/*
1560 * get_op_rettype
1561 * Given operator oid, return the operator's result type.
1562 */
1563Oid
1565{
1566 HeapTuple tp;
1567
1569 if (HeapTupleIsValid(tp))
1570 {
1572 Oid result;
1573
1574 result = optup->oprresult;
1575 ReleaseSysCache(tp);
1576 return result;
1577 }
1578 else
1579 return InvalidOid;
1580}
1581
1582/*
1583 * op_input_types
1584 *
1585 * Returns the left and right input datatypes for an operator
1586 * (InvalidOid if not relevant).
1587 */
1588void
1589op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1590{
1591 HeapTuple tp;
1593
1595 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1596 elog(ERROR, "cache lookup failed for operator %u", opno);
1598 *lefttype = optup->oprleft;
1599 *righttype = optup->oprright;
1600 ReleaseSysCache(tp);
1601}
1602
1603/*
1604 * op_mergejoinable
1605 *
1606 * Returns true if the operator is potentially mergejoinable. (The planner
1607 * will fail to find any mergejoin plans unless there are suitable btree
1608 * opfamily entries for this operator and associated sortops. The pg_operator
1609 * flag is just a hint to tell the planner whether to bother looking.)
1610 *
1611 * In some cases (currently only array_eq and record_eq), mergejoinability
1612 * depends on the specific input data type the operator is invoked for, so
1613 * that must be passed as well. We currently assume that only one input's type
1614 * is needed to check this --- by convention, pass the left input's data type.
1615 */
1616bool
1617op_mergejoinable(Oid opno, Oid inputtype)
1618{
1619 bool result = false;
1620 HeapTuple tp;
1621 TypeCacheEntry *typentry;
1622
1623 /*
1624 * For array_eq or record_eq, we can sort if the element or field types
1625 * are all sortable. We could implement all the checks for that here, but
1626 * the typcache already does that and caches the results too, so let's
1627 * rely on the typcache.
1628 */
1629 if (opno == ARRAY_EQ_OP)
1630 {
1631 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1632 if (typentry->cmp_proc == F_BTARRAYCMP)
1633 result = true;
1634 }
1635 else if (opno == RECORD_EQ_OP)
1636 {
1637 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1638 if (typentry->cmp_proc == F_BTRECORDCMP)
1639 result = true;
1640 }
1641 else
1642 {
1643 /* For all other operators, rely on pg_operator.oprcanmerge */
1645 if (HeapTupleIsValid(tp))
1646 {
1648
1649 result = optup->oprcanmerge;
1650 ReleaseSysCache(tp);
1651 }
1652 }
1653 return result;
1654}
1655
1656/*
1657 * op_hashjoinable
1658 *
1659 * Returns true if the operator is hashjoinable. (There must be a suitable
1660 * hash opfamily entry for this operator if it is so marked.)
1661 *
1662 * In some cases (currently only array_eq), hashjoinability depends on the
1663 * specific input data type the operator is invoked for, so that must be
1664 * passed as well. We currently assume that only one input's type is needed
1665 * to check this --- by convention, pass the left input's data type.
1666 */
1667bool
1668op_hashjoinable(Oid opno, Oid inputtype)
1669{
1670 bool result = false;
1671 HeapTuple tp;
1672 TypeCacheEntry *typentry;
1673
1674 /* As in op_mergejoinable, let the typcache handle the hard cases */
1675 if (opno == ARRAY_EQ_OP)
1676 {
1677 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1678 if (typentry->hash_proc == F_HASH_ARRAY)
1679 result = true;
1680 }
1681 else if (opno == RECORD_EQ_OP)
1682 {
1683 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1684 if (typentry->hash_proc == F_HASH_RECORD)
1685 result = true;
1686 }
1687 else
1688 {
1689 /* For all other operators, rely on pg_operator.oprcanhash */
1691 if (HeapTupleIsValid(tp))
1692 {
1694
1695 result = optup->oprcanhash;
1696 ReleaseSysCache(tp);
1697 }
1698 }
1699 return result;
1700}
1701
1702/*
1703 * op_strict
1704 *
1705 * Get the proisstrict flag for the operator's underlying function.
1706 */
1707bool
1709{
1710 RegProcedure funcid = get_opcode(opno);
1711
1712 if (funcid == (RegProcedure) InvalidOid)
1713 elog(ERROR, "operator %u does not exist", opno);
1714
1715 return func_strict((Oid) funcid);
1716}
1717
1718/*
1719 * op_volatile
1720 *
1721 * Get the provolatile flag for the operator's underlying function.
1722 */
1723char
1725{
1726 RegProcedure funcid = get_opcode(opno);
1727
1728 if (funcid == (RegProcedure) InvalidOid)
1729 elog(ERROR, "operator %u does not exist", opno);
1730
1731 return func_volatile((Oid) funcid);
1732}
1733
1734/*
1735 * get_commutator
1736 *
1737 * Returns the corresponding commutator of an operator.
1738 */
1739Oid
1741{
1742 HeapTuple tp;
1743
1745 if (HeapTupleIsValid(tp))
1746 {
1748 Oid result;
1749
1750 result = optup->oprcom;
1751 ReleaseSysCache(tp);
1752 return result;
1753 }
1754 else
1755 return InvalidOid;
1756}
1757
1758/*
1759 * get_negator
1760 *
1761 * Returns the corresponding negator of an operator.
1762 */
1763Oid
1765{
1766 HeapTuple tp;
1767
1769 if (HeapTupleIsValid(tp))
1770 {
1772 Oid result;
1773
1774 result = optup->oprnegate;
1775 ReleaseSysCache(tp);
1776 return result;
1777 }
1778 else
1779 return InvalidOid;
1780}
1781
1782/*
1783 * get_oprrest
1784 *
1785 * Returns procedure id for computing selectivity of an operator.
1786 */
1789{
1790 HeapTuple tp;
1791
1793 if (HeapTupleIsValid(tp))
1794 {
1797
1798 result = optup->oprrest;
1799 ReleaseSysCache(tp);
1800 return result;
1801 }
1802 else
1803 return (RegProcedure) InvalidOid;
1804}
1805
1806/*
1807 * get_oprjoin
1808 *
1809 * Returns procedure id for computing selectivity of a join.
1810 */
1813{
1814 HeapTuple tp;
1815
1817 if (HeapTupleIsValid(tp))
1818 {
1821
1822 result = optup->oprjoin;
1823 ReleaseSysCache(tp);
1824 return result;
1825 }
1826 else
1827 return (RegProcedure) InvalidOid;
1828}
1829
1830/* ---------- FUNCTION CACHE ---------- */
1831
1832/*
1833 * get_func_name
1834 * returns the name of the function with the given funcid
1835 *
1836 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1837 */
1838char *
1840{
1841 HeapTuple tp;
1842
1844 if (HeapTupleIsValid(tp))
1845 {
1847 char *result;
1848
1849 result = pstrdup(NameStr(functup->proname));
1850 ReleaseSysCache(tp);
1851 return result;
1852 }
1853 else
1854 return NULL;
1855}
1856
1857/*
1858 * get_func_namespace
1859 *
1860 * Returns the pg_namespace OID associated with a given function.
1861 */
1862Oid
1864{
1865 HeapTuple tp;
1866
1868 if (HeapTupleIsValid(tp))
1869 {
1871 Oid result;
1872
1873 result = functup->pronamespace;
1874 ReleaseSysCache(tp);
1875 return result;
1876 }
1877 else
1878 return InvalidOid;
1879}
1880
1881/*
1882 * get_func_rettype
1883 * Given procedure id, return the function's result type.
1884 */
1885Oid
1887{
1888 HeapTuple tp;
1889 Oid result;
1890
1892 if (!HeapTupleIsValid(tp))
1893 elog(ERROR, "cache lookup failed for function %u", funcid);
1894
1895 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1896 ReleaseSysCache(tp);
1897 return result;
1898}
1899
1900/*
1901 * get_func_nargs
1902 * Given procedure id, return the number of arguments.
1903 */
1904int
1906{
1907 HeapTuple tp;
1908 int result;
1909
1911 if (!HeapTupleIsValid(tp))
1912 elog(ERROR, "cache lookup failed for function %u", funcid);
1913
1915 ReleaseSysCache(tp);
1916 return result;
1917}
1918
1919/*
1920 * get_func_signature
1921 * Given procedure id, return the function's argument and result types.
1922 * (The return value is the result type.)
1923 *
1924 * The arguments are returned as a palloc'd array.
1925 */
1926Oid
1927get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1928{
1929 HeapTuple tp;
1931 Oid result;
1932
1934 if (!HeapTupleIsValid(tp))
1935 elog(ERROR, "cache lookup failed for function %u", funcid);
1936
1938
1939 result = procstruct->prorettype;
1940 *nargs = (int) procstruct->pronargs;
1941 Assert(*nargs == procstruct->proargtypes.dim1);
1942 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1943 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1944
1945 ReleaseSysCache(tp);
1946 return result;
1947}
1948
1949/*
1950 * get_func_variadictype
1951 * Given procedure id, return the function's provariadic field.
1952 */
1953Oid
1955{
1956 HeapTuple tp;
1957 Oid result;
1958
1960 if (!HeapTupleIsValid(tp))
1961 elog(ERROR, "cache lookup failed for function %u", funcid);
1962
1964 ReleaseSysCache(tp);
1965 return result;
1966}
1967
1968/*
1969 * get_func_retset
1970 * Given procedure id, return the function's proretset flag.
1971 */
1972bool
1974{
1975 HeapTuple tp;
1976 bool result;
1977
1979 if (!HeapTupleIsValid(tp))
1980 elog(ERROR, "cache lookup failed for function %u", funcid);
1981
1983 ReleaseSysCache(tp);
1984 return result;
1985}
1986
1987/*
1988 * func_strict
1989 * Given procedure id, return the function's proisstrict flag.
1990 */
1991bool
1993{
1994 HeapTuple tp;
1995 bool result;
1996
1998 if (!HeapTupleIsValid(tp))
1999 elog(ERROR, "cache lookup failed for function %u", funcid);
2000
2002 ReleaseSysCache(tp);
2003 return result;
2004}
2005
2006/*
2007 * func_volatile
2008 * Given procedure id, return the function's provolatile flag.
2009 */
2010char
2012{
2013 HeapTuple tp;
2014 char result;
2015
2017 if (!HeapTupleIsValid(tp))
2018 elog(ERROR, "cache lookup failed for function %u", funcid);
2019
2021 ReleaseSysCache(tp);
2022 return result;
2023}
2024
2025/*
2026 * func_parallel
2027 * Given procedure id, return the function's proparallel flag.
2028 */
2029char
2031{
2032 HeapTuple tp;
2033 char result;
2034
2036 if (!HeapTupleIsValid(tp))
2037 elog(ERROR, "cache lookup failed for function %u", funcid);
2038
2040 ReleaseSysCache(tp);
2041 return result;
2042}
2043
2044/*
2045 * get_func_prokind
2046 * Given procedure id, return the routine kind.
2047 */
2048char
2050{
2051 HeapTuple tp;
2052 char result;
2053
2055 if (!HeapTupleIsValid(tp))
2056 elog(ERROR, "cache lookup failed for function %u", funcid);
2057
2058 result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
2059 ReleaseSysCache(tp);
2060 return result;
2061}
2062
2063/*
2064 * get_func_leakproof
2065 * Given procedure id, return the function's leakproof field.
2066 */
2067bool
2069{
2070 HeapTuple tp;
2071 bool result;
2072
2074 if (!HeapTupleIsValid(tp))
2075 elog(ERROR, "cache lookup failed for function %u", funcid);
2076
2078 ReleaseSysCache(tp);
2079 return result;
2080}
2081
2082/*
2083 * get_func_support
2084 *
2085 * Returns the support function OID associated with a given function,
2086 * or InvalidOid if there is none.
2087 */
2090{
2091 HeapTuple tp;
2092
2094 if (HeapTupleIsValid(tp))
2095 {
2098
2099 result = functup->prosupport;
2100 ReleaseSysCache(tp);
2101 return result;
2102 }
2103 else
2104 return (RegProcedure) InvalidOid;
2105}
2106
2107/* ---------- RELATION CACHE ---------- */
2108
2109/*
2110 * get_relname_relid
2111 * Given name and namespace of a relation, look up the OID.
2112 *
2113 * Returns InvalidOid if there is no such relation.
2114 */
2115Oid
2116get_relname_relid(const char *relname, Oid relnamespace)
2117{
2120 ObjectIdGetDatum(relnamespace));
2121}
2122
2123#ifdef NOT_USED
2124/*
2125 * get_relnatts
2126 *
2127 * Returns the number of attributes for a given relation.
2128 */
2129int
2130get_relnatts(Oid relid)
2131{
2132 HeapTuple tp;
2133
2135 if (HeapTupleIsValid(tp))
2136 {
2138 int result;
2139
2140 result = reltup->relnatts;
2141 ReleaseSysCache(tp);
2142 return result;
2143 }
2144 else
2145 return InvalidAttrNumber;
2146}
2147#endif
2148
2149/*
2150 * get_rel_name
2151 * Returns the name of a given relation.
2152 *
2153 * Returns a palloc'd copy of the string, or NULL if no such relation.
2154 *
2155 * NOTE: since relation name is not unique, be wary of code that uses this
2156 * for anything except preparing error messages.
2157 */
2158char *
2160{
2161 HeapTuple tp;
2162
2164 if (HeapTupleIsValid(tp))
2165 {
2167 char *result;
2168
2169 result = pstrdup(NameStr(reltup->relname));
2170 ReleaseSysCache(tp);
2171 return result;
2172 }
2173 else
2174 return NULL;
2175}
2176
2177/*
2178 * get_rel_namespace
2179 *
2180 * Returns the pg_namespace OID associated with a given relation.
2181 */
2182Oid
2184{
2185 HeapTuple tp;
2186
2188 if (HeapTupleIsValid(tp))
2189 {
2191 Oid result;
2192
2193 result = reltup->relnamespace;
2194 ReleaseSysCache(tp);
2195 return result;
2196 }
2197 else
2198 return InvalidOid;
2199}
2200
2201/*
2202 * get_rel_type_id
2203 *
2204 * Returns the pg_type OID associated with a given relation.
2205 *
2206 * Note: not all pg_class entries have associated pg_type OIDs; so be
2207 * careful to check for InvalidOid result.
2208 */
2209Oid
2211{
2212 HeapTuple tp;
2213
2215 if (HeapTupleIsValid(tp))
2216 {
2218 Oid result;
2219
2220 result = reltup->reltype;
2221 ReleaseSysCache(tp);
2222 return result;
2223 }
2224 else
2225 return InvalidOid;
2226}
2227
2228/*
2229 * get_rel_relkind
2230 *
2231 * Returns the relkind associated with a given relation.
2232 */
2233char
2235{
2236 HeapTuple tp;
2237
2239 if (HeapTupleIsValid(tp))
2240 {
2242 char result;
2243
2244 result = reltup->relkind;
2245 ReleaseSysCache(tp);
2246 return result;
2247 }
2248 else
2249 return '\0';
2250}
2251
2252/*
2253 * get_rel_relispartition
2254 *
2255 * Returns the relispartition flag associated with a given relation.
2256 */
2257bool
2259{
2260 HeapTuple tp;
2261
2263 if (HeapTupleIsValid(tp))
2264 {
2266 bool result;
2267
2268 result = reltup->relispartition;
2269 ReleaseSysCache(tp);
2270 return result;
2271 }
2272 else
2273 return false;
2274}
2275
2276/*
2277 * get_rel_tablespace
2278 *
2279 * Returns the pg_tablespace OID associated with a given relation.
2280 *
2281 * Note: InvalidOid might mean either that we couldn't find the relation,
2282 * or that it is in the database's default tablespace.
2283 */
2284Oid
2286{
2287 HeapTuple tp;
2288
2290 if (HeapTupleIsValid(tp))
2291 {
2293 Oid result;
2294
2295 result = reltup->reltablespace;
2296 ReleaseSysCache(tp);
2297 return result;
2298 }
2299 else
2300 return InvalidOid;
2301}
2302
2303/*
2304 * get_rel_persistence
2305 *
2306 * Returns the relpersistence associated with a given relation.
2307 */
2308char
2310{
2311 HeapTuple tp;
2313 char result;
2314
2316 if (!HeapTupleIsValid(tp))
2317 elog(ERROR, "cache lookup failed for relation %u", relid);
2319 result = reltup->relpersistence;
2320 ReleaseSysCache(tp);
2321
2322 return result;
2323}
2324
2325/*
2326 * get_rel_relam
2327 *
2328 * Returns the relam associated with a given relation.
2329 */
2330Oid
2332{
2333 HeapTuple tp;
2335 Oid result;
2336
2338 if (!HeapTupleIsValid(tp))
2339 elog(ERROR, "cache lookup failed for relation %u", relid);
2341 result = reltup->relam;
2342 ReleaseSysCache(tp);
2343
2344 return result;
2345}
2346
2347
2348/* ---------- TRANSFORM CACHE ---------- */
2349
2350Oid
2351get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2352{
2353 HeapTuple tup;
2354
2355 if (!list_member_oid(trftypes, typid))
2356 return InvalidOid;
2357
2359 ObjectIdGetDatum(langid));
2360 if (HeapTupleIsValid(tup))
2361 {
2362 Oid funcid;
2363
2364 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2366 return funcid;
2367 }
2368 else
2369 return InvalidOid;
2370}
2371
2372Oid
2373get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2374{
2375 HeapTuple tup;
2376
2377 if (!list_member_oid(trftypes, typid))
2378 return InvalidOid;
2379
2381 ObjectIdGetDatum(langid));
2382 if (HeapTupleIsValid(tup))
2383 {
2384 Oid funcid;
2385
2386 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2388 return funcid;
2389 }
2390 else
2391 return InvalidOid;
2392}
2393
2394
2395/* ---------- TYPE CACHE ---------- */
2396
2397/*
2398 * get_typisdefined
2399 *
2400 * Given the type OID, determine whether the type is defined
2401 * (if not, it's only a shell).
2402 */
2403bool
2405{
2406 HeapTuple tp;
2407
2409 if (HeapTupleIsValid(tp))
2410 {
2412 bool result;
2413
2414 result = typtup->typisdefined;
2415 ReleaseSysCache(tp);
2416 return result;
2417 }
2418 else
2419 return false;
2420}
2421
2422/*
2423 * get_typlen
2424 *
2425 * Given the type OID, return the length of the type.
2426 */
2427int16
2429{
2430 HeapTuple tp;
2431
2433 if (HeapTupleIsValid(tp))
2434 {
2436 int16 result;
2437
2438 result = typtup->typlen;
2439 ReleaseSysCache(tp);
2440 return result;
2441 }
2442 else
2443 return 0;
2444}
2445
2446/*
2447 * get_typbyval
2448 *
2449 * Given the type OID, determine whether the type is returned by value or
2450 * not. Returns true if by value, false if by reference.
2451 */
2452bool
2454{
2455 HeapTuple tp;
2456
2458 if (HeapTupleIsValid(tp))
2459 {
2461 bool result;
2462
2463 result = typtup->typbyval;
2464 ReleaseSysCache(tp);
2465 return result;
2466 }
2467 else
2468 return false;
2469}
2470
2471/*
2472 * get_typlenbyval
2473 *
2474 * A two-fer: given the type OID, return both typlen and typbyval.
2475 *
2476 * Since both pieces of info are needed to know how to copy a Datum,
2477 * many places need both. Might as well get them with one cache lookup
2478 * instead of two. Also, this routine raises an error instead of
2479 * returning a bogus value when given a bad type OID.
2480 */
2481void
2482get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2483{
2484 HeapTuple tp;
2486
2488 if (!HeapTupleIsValid(tp))
2489 elog(ERROR, "cache lookup failed for type %u", typid);
2491 *typlen = typtup->typlen;
2492 *typbyval = typtup->typbyval;
2493 ReleaseSysCache(tp);
2494}
2495
2496/*
2497 * get_typlenbyvalalign
2498 *
2499 * A three-fer: given the type OID, return typlen, typbyval, typalign.
2500 */
2501void
2502get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2503 char *typalign)
2504{
2505 HeapTuple tp;
2507
2509 if (!HeapTupleIsValid(tp))
2510 elog(ERROR, "cache lookup failed for type %u", typid);
2512 *typlen = typtup->typlen;
2513 *typbyval = typtup->typbyval;
2514 *typalign = typtup->typalign;
2515 ReleaseSysCache(tp);
2516}
2517
2518/*
2519 * getTypeIOParam
2520 * Given a pg_type row, select the type OID to pass to I/O functions
2521 *
2522 * Formerly, all I/O functions were passed pg_type.typelem as their second
2523 * parameter, but we now have a more complex rule about what to pass.
2524 * This knowledge is intended to be centralized here --- direct references
2525 * to typelem elsewhere in the code are wrong, if they are associated with
2526 * I/O calls and not with actual subscripting operations! (But see
2527 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2528 *
2529 * As of PostgreSQL 8.1, output functions receive only the value itself
2530 * and not any auxiliary parameters, so the name of this routine is now
2531 * a bit of a misnomer ... it should be getTypeInputParam.
2532 */
2533Oid
2535{
2537
2538 /*
2539 * Array types get their typelem as parameter; everybody else gets their
2540 * own type OID as parameter.
2541 */
2542 if (OidIsValid(typeStruct->typelem))
2543 return typeStruct->typelem;
2544 else
2545 return typeStruct->oid;
2546}
2547
2548/*
2549 * get_type_io_data
2550 *
2551 * A six-fer: given the type OID, return typlen, typbyval, typalign,
2552 * typdelim, typioparam, and IO function OID. The IO function
2553 * returned is controlled by IOFuncSelector
2554 */
2555void
2558 int16 *typlen,
2559 bool *typbyval,
2560 char *typalign,
2561 char *typdelim,
2562 Oid *typioparam,
2563 Oid *func)
2564{
2567
2568 /*
2569 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2570 * use array_in and array_out during bootstrap.
2571 */
2573 {
2574 Oid typinput;
2575 Oid typoutput;
2576 Oid typcollation;
2577
2579 typlen,
2580 typbyval,
2581 typalign,
2582 typdelim,
2583 typioparam,
2584 &typinput,
2585 &typoutput,
2586 &typcollation);
2587 switch (which_func)
2588 {
2589 case IOFunc_input:
2590 *func = typinput;
2591 break;
2592 case IOFunc_output:
2593 *func = typoutput;
2594 break;
2595 default:
2596 elog(ERROR, "binary I/O not supported during bootstrap");
2597 break;
2598 }
2599 return;
2600 }
2601
2604 elog(ERROR, "cache lookup failed for type %u", typid);
2606
2607 *typlen = typeStruct->typlen;
2608 *typbyval = typeStruct->typbyval;
2609 *typalign = typeStruct->typalign;
2610 *typdelim = typeStruct->typdelim;
2611 *typioparam = getTypeIOParam(typeTuple);
2612 switch (which_func)
2613 {
2614 case IOFunc_input:
2615 *func = typeStruct->typinput;
2616 break;
2617 case IOFunc_output:
2618 *func = typeStruct->typoutput;
2619 break;
2620 case IOFunc_receive:
2621 *func = typeStruct->typreceive;
2622 break;
2623 case IOFunc_send:
2624 *func = typeStruct->typsend;
2625 break;
2626 }
2628}
2629
2630#ifdef NOT_USED
2631char
2632get_typalign(Oid typid)
2633{
2634 HeapTuple tp;
2635
2637 if (HeapTupleIsValid(tp))
2638 {
2640 char result;
2641
2642 result = typtup->typalign;
2643 ReleaseSysCache(tp);
2644 return result;
2645 }
2646 else
2647 return TYPALIGN_INT;
2648}
2649#endif
2650
2651char
2653{
2654 HeapTuple tp;
2655
2657 if (HeapTupleIsValid(tp))
2658 {
2660 char result;
2661
2662 result = typtup->typstorage;
2663 ReleaseSysCache(tp);
2664 return result;
2665 }
2666 else
2667 return TYPSTORAGE_PLAIN;
2668}
2669
2670/*
2671 * get_typdefault
2672 * Given a type OID, return the type's default value, if any.
2673 *
2674 * The result is a palloc'd expression node tree, or NULL if there
2675 * is no defined default for the datatype.
2676 *
2677 * NB: caller should be prepared to coerce result to correct datatype;
2678 * the returned expression tree might produce something of the wrong type.
2679 */
2680Node *
2682{
2685 Datum datum;
2686 bool isNull;
2687 Node *expr;
2688
2691 elog(ERROR, "cache lookup failed for type %u", typid);
2693
2694 /*
2695 * typdefault and typdefaultbin are potentially null, so don't try to
2696 * access 'em as struct fields. Must do it the hard way with
2697 * SysCacheGetAttr.
2698 */
2699 datum = SysCacheGetAttr(TYPEOID,
2700 typeTuple,
2702 &isNull);
2703
2704 if (!isNull)
2705 {
2706 /* We have an expression default */
2707 expr = stringToNode(TextDatumGetCString(datum));
2708 }
2709 else
2710 {
2711 /* Perhaps we have a plain literal default */
2712 datum = SysCacheGetAttr(TYPEOID,
2713 typeTuple,
2715 &isNull);
2716
2717 if (!isNull)
2718 {
2719 char *strDefaultVal;
2720
2721 /* Convert text datum to C string */
2723 /* Convert C string to a value of the given type */
2724 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2726 /* Build a Const node containing the value */
2727 expr = (Node *) makeConst(typid,
2728 -1,
2729 type->typcollation,
2730 type->typlen,
2731 datum,
2732 false,
2733 type->typbyval);
2735 }
2736 else
2737 {
2738 /* No default */
2739 expr = NULL;
2740 }
2741 }
2742
2744
2745 return expr;
2746}
2747
2748/*
2749 * getBaseType
2750 * If the given type is a domain, return its base type;
2751 * otherwise return the type's own OID.
2752 */
2753Oid
2755{
2756 int32 typmod = -1;
2757
2758 return getBaseTypeAndTypmod(typid, &typmod);
2759}
2760
2761/*
2762 * getBaseTypeAndTypmod
2763 * If the given type is a domain, return its base type and typmod;
2764 * otherwise return the type's own OID, and leave *typmod unchanged.
2765 *
2766 * Note that the "applied typmod" should be -1 for every domain level
2767 * above the bottommost; therefore, if the passed-in typid is indeed
2768 * a domain, *typmod should be -1.
2769 */
2770Oid
2772{
2773 /*
2774 * We loop to find the bottom base type in a stack of domains.
2775 */
2776 for (;;)
2777 {
2778 HeapTuple tup;
2780
2782 if (!HeapTupleIsValid(tup))
2783 elog(ERROR, "cache lookup failed for type %u", typid);
2785 if (typTup->typtype != TYPTYPE_DOMAIN)
2786 {
2787 /* Not a domain, so done */
2789 break;
2790 }
2791
2792 Assert(*typmod == -1);
2793 typid = typTup->typbasetype;
2794 *typmod = typTup->typtypmod;
2795
2797 }
2798
2799 return typid;
2800}
2801
2802/*
2803 * get_typavgwidth
2804 *
2805 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2806 * estimate the average width of values of the type. This is used by
2807 * the planner, which doesn't require absolutely correct results;
2808 * it's OK (and expected) to guess if we don't know for sure.
2809 */
2810int32
2812{
2813 int typlen = get_typlen(typid);
2815
2816 /*
2817 * Easy if it's a fixed-width type
2818 */
2819 if (typlen > 0)
2820 return typlen;
2821
2822 /*
2823 * type_maximum_size knows the encoding of typmod for some datatypes;
2824 * don't duplicate that knowledge here.
2825 */
2826 maxwidth = type_maximum_size(typid, typmod);
2827 if (maxwidth > 0)
2828 {
2829 /*
2830 * For BPCHAR, the max width is also the only width. Otherwise we
2831 * need to guess about the typical data width given the max. A sliding
2832 * scale for percentage of max width seems reasonable.
2833 */
2834 if (typid == BPCHAROID)
2835 return maxwidth;
2836 if (maxwidth <= 32)
2837 return maxwidth; /* assume full width */
2838 if (maxwidth < 1000)
2839 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2840
2841 /*
2842 * Beyond 1000, assume we're looking at something like
2843 * "varchar(10000)" where the limit isn't actually reached often, and
2844 * use a fixed estimate.
2845 */
2846 return 32 + (1000 - 32) / 2;
2847 }
2848
2849 /*
2850 * Oops, we have no idea ... wild guess time.
2851 */
2852 return 32;
2853}
2854
2855/*
2856 * get_typtype
2857 *
2858 * Given the type OID, find if it is a basic type, a complex type, etc.
2859 * It returns the null char if the cache lookup fails...
2860 */
2861char
2863{
2864 HeapTuple tp;
2865
2867 if (HeapTupleIsValid(tp))
2868 {
2870 char result;
2871
2872 result = typtup->typtype;
2873 ReleaseSysCache(tp);
2874 return result;
2875 }
2876 else
2877 return '\0';
2878}
2879
2880/*
2881 * type_is_rowtype
2882 *
2883 * Convenience function to determine whether a type OID represents
2884 * a "rowtype" type --- either RECORD or a named composite type
2885 * (including a domain over a named composite type).
2886 */
2887bool
2889{
2890 if (typid == RECORDOID)
2891 return true; /* easy case */
2892 switch (get_typtype(typid))
2893 {
2894 case TYPTYPE_COMPOSITE:
2895 return true;
2896 case TYPTYPE_DOMAIN:
2898 return true;
2899 break;
2900 default:
2901 break;
2902 }
2903 return false;
2904}
2905
2906/*
2907 * type_is_enum
2908 * Returns true if the given type is an enum type.
2909 */
2910bool
2912{
2913 return (get_typtype(typid) == TYPTYPE_ENUM);
2914}
2915
2916/*
2917 * type_is_range
2918 * Returns true if the given type is a range type.
2919 */
2920bool
2922{
2923 return (get_typtype(typid) == TYPTYPE_RANGE);
2924}
2925
2926/*
2927 * type_is_multirange
2928 * Returns true if the given type is a multirange type.
2929 */
2930bool
2932{
2933 return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
2934}
2935
2936/*
2937 * get_type_category_preferred
2938 *
2939 * Given the type OID, fetch its category and preferred-type status.
2940 * Throws error on failure.
2941 */
2942void
2944{
2945 HeapTuple tp;
2947
2949 if (!HeapTupleIsValid(tp))
2950 elog(ERROR, "cache lookup failed for type %u", typid);
2952 *typcategory = typtup->typcategory;
2953 *typispreferred = typtup->typispreferred;
2954 ReleaseSysCache(tp);
2955}
2956
2957/*
2958 * get_typ_typrelid
2959 *
2960 * Given the type OID, get the typrelid (InvalidOid if not a complex
2961 * type).
2962 */
2963Oid
2965{
2966 HeapTuple tp;
2967
2969 if (HeapTupleIsValid(tp))
2970 {
2972 Oid result;
2973
2974 result = typtup->typrelid;
2975 ReleaseSysCache(tp);
2976 return result;
2977 }
2978 else
2979 return InvalidOid;
2980}
2981
2982/*
2983 * get_element_type
2984 *
2985 * Given the type OID, get the typelem (InvalidOid if not an array type).
2986 *
2987 * NB: this only succeeds for "true" arrays having array_subscript_handler
2988 * as typsubscript. For other types, InvalidOid is returned independently
2989 * of whether they have typelem or typsubscript set.
2990 */
2991Oid
2993{
2994 HeapTuple tp;
2995
2997 if (HeapTupleIsValid(tp))
2998 {
3000 Oid result;
3001
3003 result = typtup->typelem;
3004 else
3006 ReleaseSysCache(tp);
3007 return result;
3008 }
3009 else
3010 return InvalidOid;
3011}
3012
3013/*
3014 * get_array_type
3015 *
3016 * Given the type OID, get the corresponding "true" array type.
3017 * Returns InvalidOid if no array type can be found.
3018 */
3019Oid
3021{
3022 HeapTuple tp;
3024
3026 if (HeapTupleIsValid(tp))
3027 {
3028 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
3029 ReleaseSysCache(tp);
3030 }
3031 return result;
3032}
3033
3034/*
3035 * get_promoted_array_type
3036 *
3037 * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
3038 * construct, that is, either the corresponding "true" array type
3039 * if the input is a scalar type that has such an array type,
3040 * or the same type if the input is already a "true" array type.
3041 * Returns InvalidOid if neither rule is satisfied.
3042 */
3043Oid
3045{
3046 Oid array_type = get_array_type(typid);
3047
3048 if (OidIsValid(array_type))
3049 return array_type;
3050 if (OidIsValid(get_element_type(typid)))
3051 return typid;
3052 return InvalidOid;
3053}
3054
3055/*
3056 * get_base_element_type
3057 * Given the type OID, get the typelem, looking "through" any domain
3058 * to its underlying array type.
3059 *
3060 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
3061 * an extra cache lookup. Note that it fails to provide any information
3062 * about the typmod of the array.
3063 */
3064Oid
3066{
3067 /*
3068 * We loop to find the bottom base type in a stack of domains.
3069 */
3070 for (;;)
3071 {
3072 HeapTuple tup;
3074
3076 if (!HeapTupleIsValid(tup))
3077 break;
3079 if (typTup->typtype != TYPTYPE_DOMAIN)
3080 {
3081 /* Not a domain, so stop descending */
3082 Oid result;
3083
3084 /* This test must match get_element_type */
3086 result = typTup->typelem;
3087 else
3090 return result;
3091 }
3092
3093 typid = typTup->typbasetype;
3095 }
3096
3097 /* Like get_element_type, silently return InvalidOid for bogus input */
3098 return InvalidOid;
3099}
3100
3101/*
3102 * getTypeInputInfo
3103 *
3104 * Get info needed for converting values of a type to internal form
3105 */
3106void
3108{
3111
3114 elog(ERROR, "cache lookup failed for type %u", type);
3116
3117 if (!pt->typisdefined)
3118 ereport(ERROR,
3120 errmsg("type %s is only a shell",
3121 format_type_be(type))));
3122 if (!OidIsValid(pt->typinput))
3123 ereport(ERROR,
3125 errmsg("no input function available for type %s",
3126 format_type_be(type))));
3127
3128 *typInput = pt->typinput;
3130
3132}
3133
3134/*
3135 * getTypeOutputInfo
3136 *
3137 * Get info needed for printing values of a type
3138 */
3139void
3141{
3144
3147 elog(ERROR, "cache lookup failed for type %u", type);
3149
3150 if (!pt->typisdefined)
3151 ereport(ERROR,
3153 errmsg("type %s is only a shell",
3154 format_type_be(type))));
3155 if (!OidIsValid(pt->typoutput))
3156 ereport(ERROR,
3158 errmsg("no output function available for type %s",
3159 format_type_be(type))));
3160
3161 *typOutput = pt->typoutput;
3162 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3163
3165}
3166
3167/*
3168 * getTypeBinaryInputInfo
3169 *
3170 * Get info needed for binary input of values of a type
3171 */
3172void
3174{
3177
3180 elog(ERROR, "cache lookup failed for type %u", type);
3182
3183 if (!pt->typisdefined)
3184 ereport(ERROR,
3186 errmsg("type %s is only a shell",
3187 format_type_be(type))));
3188 if (!OidIsValid(pt->typreceive))
3189 ereport(ERROR,
3191 errmsg("no binary input function available for type %s",
3192 format_type_be(type))));
3193
3194 *typReceive = pt->typreceive;
3196
3198}
3199
3200/*
3201 * getTypeBinaryOutputInfo
3202 *
3203 * Get info needed for binary output of values of a type
3204 */
3205void
3207{
3210
3213 elog(ERROR, "cache lookup failed for type %u", type);
3215
3216 if (!pt->typisdefined)
3217 ereport(ERROR,
3219 errmsg("type %s is only a shell",
3220 format_type_be(type))));
3221 if (!OidIsValid(pt->typsend))
3222 ereport(ERROR,
3224 errmsg("no binary output function available for type %s",
3225 format_type_be(type))));
3226
3227 *typSend = pt->typsend;
3228 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3229
3231}
3232
3233/*
3234 * get_typmodin
3235 *
3236 * Given the type OID, return the type's typmodin procedure, if any.
3237 */
3238Oid
3240{
3241 HeapTuple tp;
3242
3244 if (HeapTupleIsValid(tp))
3245 {
3247 Oid result;
3248
3249 result = typtup->typmodin;
3250 ReleaseSysCache(tp);
3251 return result;
3252 }
3253 else
3254 return InvalidOid;
3255}
3256
3257#ifdef NOT_USED
3258/*
3259 * get_typmodout
3260 *
3261 * Given the type OID, return the type's typmodout procedure, if any.
3262 */
3263Oid
3264get_typmodout(Oid typid)
3265{
3266 HeapTuple tp;
3267
3269 if (HeapTupleIsValid(tp))
3270 {
3272 Oid result;
3273
3274 result = typtup->typmodout;
3275 ReleaseSysCache(tp);
3276 return result;
3277 }
3278 else
3279 return InvalidOid;
3280}
3281#endif /* NOT_USED */
3282
3283/*
3284 * get_typcollation
3285 *
3286 * Given the type OID, return the type's typcollation attribute.
3287 */
3288Oid
3290{
3291 HeapTuple tp;
3292
3294 if (HeapTupleIsValid(tp))
3295 {
3297 Oid result;
3298
3299 result = typtup->typcollation;
3300 ReleaseSysCache(tp);
3301 return result;
3302 }
3303 else
3304 return InvalidOid;
3305}
3306
3307
3308/*
3309 * type_is_collatable
3310 *
3311 * Return whether the type cares about collations
3312 */
3313bool
3315{
3316 return OidIsValid(get_typcollation(typid));
3317}
3318
3319
3320/*
3321 * get_typsubscript
3322 *
3323 * Given the type OID, return the type's subscripting handler's OID,
3324 * if it has one.
3325 *
3326 * If typelemp isn't NULL, we also store the type's typelem value there.
3327 * This saves some callers an extra catalog lookup.
3328 */
3331{
3332 HeapTuple tp;
3333
3335 if (HeapTupleIsValid(tp))
3336 {
3338 RegProcedure handler = typform->typsubscript;
3339
3340 if (typelemp)
3341 *typelemp = typform->typelem;
3342 ReleaseSysCache(tp);
3343 return handler;
3344 }
3345 else
3346 {
3347 if (typelemp)
3349 return InvalidOid;
3350 }
3351}
3352
3353/*
3354 * getSubscriptingRoutines
3355 *
3356 * Given the type OID, fetch the type's subscripting methods struct.
3357 * Return NULL if type is not subscriptable.
3358 *
3359 * If typelemp isn't NULL, we also store the type's typelem value there.
3360 * This saves some callers an extra catalog lookup.
3361 */
3362const struct SubscriptRoutines *
3364{
3365 RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3366
3367 if (!OidIsValid(typsubscript))
3368 return NULL;
3369
3370 return (const struct SubscriptRoutines *)
3371 DatumGetPointer(OidFunctionCall0(typsubscript));
3372}
3373
3374
3375/* ---------- STATISTICS CACHE ---------- */
3376
3377/*
3378 * get_attavgwidth
3379 *
3380 * Given the table and attribute number of a column, get the average
3381 * width of entries in the column. Return zero if no data available.
3382 *
3383 * Currently this is only consulted for individual tables, not for inheritance
3384 * trees, so we don't need an "inh" parameter.
3385 *
3386 * Calling a hook at this point looks somewhat strange, but is required
3387 * because the optimizer calls this function without any other way for
3388 * plug-ins to control the result.
3389 */
3390int32
3392{
3393 HeapTuple tp;
3394 int32 stawidth;
3395
3397 {
3398 stawidth = (*get_attavgwidth_hook) (relid, attnum);
3399 if (stawidth > 0)
3400 return stawidth;
3401 }
3403 ObjectIdGetDatum(relid),
3405 BoolGetDatum(false));
3406 if (HeapTupleIsValid(tp))
3407 {
3408 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3409 ReleaseSysCache(tp);
3410 if (stawidth > 0)
3411 return stawidth;
3412 }
3413 return 0;
3414}
3415
3416/*
3417 * get_attstatsslot
3418 *
3419 * Extract the contents of a "slot" of a pg_statistic tuple.
3420 * Returns true if requested slot type was found, else false.
3421 *
3422 * Unlike other routines in this file, this takes a pointer to an
3423 * already-looked-up tuple in the pg_statistic cache. We do this since
3424 * most callers will want to extract more than one value from the cache
3425 * entry, and we don't want to repeat the cache lookup unnecessarily.
3426 * Also, this API allows this routine to be used with statistics tuples
3427 * that have been provided by a stats hook and didn't really come from
3428 * pg_statistic.
3429 *
3430 * sslot: pointer to output area (typically, a local variable in the caller).
3431 * statstuple: pg_statistic tuple to be examined.
3432 * reqkind: STAKIND code for desired statistics slot kind.
3433 * reqop: STAOP value wanted, or InvalidOid if don't care.
3434 * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3435 *
3436 * If a matching slot is found, true is returned, and *sslot is filled thus:
3437 * staop: receives the actual STAOP value.
3438 * stacoll: receives the actual STACOLL value.
3439 * valuetype: receives actual datatype of the elements of stavalues.
3440 * values: receives pointer to an array of the slot's stavalues.
3441 * nvalues: receives number of stavalues.
3442 * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3443 * nnumbers: receives number of stanumbers.
3444 *
3445 * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3446 * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3447 * ATTSTATSSLOT_NUMBERS wasn't specified.
3448 *
3449 * If no matching slot is found, false is returned, and *sslot is zeroed.
3450 *
3451 * Note that the current API doesn't allow for searching for a slot with
3452 * a particular collation. If we ever actually support recording more than
3453 * one collation, we'll have to extend the API, but for now simple is good.
3454 *
3455 * The data referred to by the fields of sslot is locally palloc'd and
3456 * is independent of the original pg_statistic tuple. When the caller
3457 * is done with it, call free_attstatsslot to release the palloc'd data.
3458 *
3459 * If it's desirable to call free_attstatsslot when get_attstatsslot might
3460 * not have been called, memset'ing sslot to zeroes will allow that.
3461 *
3462 * Passing flags=0 can be useful to quickly check if the requested slot type
3463 * exists. In this case no arrays are extracted, so free_attstatsslot need
3464 * not be called.
3465 */
3466bool
3468 int reqkind, Oid reqop, int flags)
3469{
3471 int i;
3472 Datum val;
3475 int narrayelem;
3478
3479 /* initialize *sslot properly */
3480 memset(sslot, 0, sizeof(AttStatsSlot));
3481
3482 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3483 {
3484 if ((&stats->stakind1)[i] == reqkind &&
3485 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3486 break;
3487 }
3488 if (i >= STATISTIC_NUM_SLOTS)
3489 return false; /* not there */
3490
3491 sslot->staop = (&stats->staop1)[i];
3492 sslot->stacoll = (&stats->stacoll1)[i];
3493
3494 if (flags & ATTSTATSSLOT_VALUES)
3495 {
3498
3499 /*
3500 * Detoast the array if needed, and in any case make a copy that's
3501 * under control of this AttStatsSlot.
3502 */
3504
3505 /*
3506 * Extract the actual array element type, and pass it back in case the
3507 * caller needs it.
3508 */
3509 sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3510
3511 /* Need info about element type */
3514 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3516
3517 /* Deconstruct array into Datum elements; NULLs not expected */
3520 typeForm->typlen,
3521 typeForm->typbyval,
3522 typeForm->typalign,
3523 &sslot->values, NULL, &sslot->nvalues);
3524
3525 /*
3526 * If the element type is pass-by-reference, we now have a bunch of
3527 * Datums that are pointers into the statarray, so we need to keep
3528 * that until free_attstatsslot. Otherwise, all the useful info is in
3529 * sslot->values[], so we can free the array object immediately.
3530 */
3531 if (!typeForm->typbyval)
3532 sslot->values_arr = statarray;
3533 else
3535
3537 }
3538
3539 if (flags & ATTSTATSSLOT_NUMBERS)
3540 {
3543
3544 /*
3545 * Detoast the array if needed, and in any case make a copy that's
3546 * under control of this AttStatsSlot.
3547 */
3549
3550 /*
3551 * We expect the array to be a 1-D float4 array; verify that. We don't
3552 * need to use deconstruct_array() since the array data is just going
3553 * to look like a C array of float4 values.
3554 */
3556 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3559 elog(ERROR, "stanumbers is not a 1-D float4 array");
3560
3561 /* Give caller a pointer directly into the statarray */
3562 sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3563 sslot->nnumbers = narrayelem;
3564
3565 /* We'll free the statarray in free_attstatsslot */
3566 sslot->numbers_arr = statarray;
3567 }
3568
3569 return true;
3570}
3571
3572/*
3573 * free_attstatsslot
3574 * Free data allocated by get_attstatsslot
3575 */
3576void
3578{
3579 /* The values[] array was separately palloc'd by deconstruct_array */
3580 if (sslot->values)
3581 pfree(sslot->values);
3582 /* The numbers[] array points into numbers_arr, do not pfree it */
3583 /* Free the detoasted array objects, if any */
3584 if (sslot->values_arr)
3585 pfree(sslot->values_arr);
3586 if (sslot->numbers_arr)
3587 pfree(sslot->numbers_arr);
3588}
3589
3590/* ---------- PG_NAMESPACE CACHE ---------- */
3591
3592/*
3593 * get_namespace_name
3594 * Returns the name of a given namespace
3595 *
3596 * Returns a palloc'd copy of the string, or NULL if no such namespace.
3597 */
3598char *
3600{
3601 HeapTuple tp;
3602
3604 if (HeapTupleIsValid(tp))
3605 {
3607 char *result;
3608
3609 result = pstrdup(NameStr(nsptup->nspname));
3610 ReleaseSysCache(tp);
3611 return result;
3612 }
3613 else
3614 return NULL;
3615}
3616
3617/*
3618 * get_namespace_name_or_temp
3619 * As above, but if it is this backend's temporary namespace, return
3620 * "pg_temp" instead.
3621 */
3622char *
3624{
3626 return pstrdup("pg_temp");
3627 else
3628 return get_namespace_name(nspid);
3629}
3630
3631/*
3632 * get_qualified_objname
3633 * Returns a palloc'd string containing the schema-qualified name of the
3634 * object for the given namespace ID and object name.
3635 */
3636char *
3638{
3639 char *nspname;
3640 char *result;
3641
3643 if (!nspname)
3644 elog(ERROR, "cache lookup failed for namespace %u", nspid);
3645
3646 result = quote_qualified_identifier(nspname, objname);
3647
3648 return result;
3649}
3650
3651/* ---------- PG_RANGE CACHES ---------- */
3652
3653/*
3654 * get_range_subtype
3655 * Returns the subtype of a given range type
3656 *
3657 * Returns InvalidOid if the type is not a range type.
3658 */
3659Oid
3661{
3662 HeapTuple tp;
3663
3665 if (HeapTupleIsValid(tp))
3666 {
3668 Oid result;
3669
3670 result = rngtup->rngsubtype;
3671 ReleaseSysCache(tp);
3672 return result;
3673 }
3674 else
3675 return InvalidOid;
3676}
3677
3678/*
3679 * get_range_collation
3680 * Returns the collation of a given range type
3681 *
3682 * Returns InvalidOid if the type is not a range type,
3683 * or if its subtype is not collatable.
3684 */
3685Oid
3687{
3688 HeapTuple tp;
3689
3691 if (HeapTupleIsValid(tp))
3692 {
3694 Oid result;
3695
3696 result = rngtup->rngcollation;
3697 ReleaseSysCache(tp);
3698 return result;
3699 }
3700 else
3701 return InvalidOid;
3702}
3703
3704/*
3705 * get_range_constructor2
3706 * Gets the 2-arg constructor for the given rangetype.
3707 *
3708 * Raises an error if not found.
3709 */
3712{
3713 HeapTuple tp;
3714
3716 if (HeapTupleIsValid(tp))
3717 {
3720
3721 result = rngtup->rngconstruct2;
3722 ReleaseSysCache(tp);
3723 return result;
3724 }
3725 else
3726 elog(ERROR, "cache lookup failed for range type %u", rangeOid);
3727}
3728
3729/*
3730 * get_range_multirange
3731 * Returns the multirange type of a given range type
3732 *
3733 * Returns InvalidOid if the type is not a range type.
3734 */
3735Oid
3737{
3738 HeapTuple tp;
3739
3741 if (HeapTupleIsValid(tp))
3742 {
3744 Oid result;
3745
3746 result = rngtup->rngmultitypid;
3747 ReleaseSysCache(tp);
3748 return result;
3749 }
3750 else
3751 return InvalidOid;
3752}
3753
3754/*
3755 * get_multirange_range
3756 * Returns the range type of a given multirange
3757 *
3758 * Returns InvalidOid if the type is not a multirange.
3759 */
3760Oid
3762{
3763 HeapTuple tp;
3764
3766 if (HeapTupleIsValid(tp))
3767 {
3769 Oid result;
3770
3771 result = rngtup->rngtypid;
3772 ReleaseSysCache(tp);
3773 return result;
3774 }
3775 else
3776 return InvalidOid;
3777}
3778
3779/* ---------- PG_INDEX CACHE ---------- */
3780
3781/*
3782 * get_index_column_opclass
3783 *
3784 * Given the index OID and column number,
3785 * return opclass of the index column
3786 * or InvalidOid if the index was not found
3787 * or column is non-key one.
3788 */
3789Oid
3791{
3792 HeapTuple tuple;
3793 Form_pg_index rd_index;
3794 Datum datum;
3796 Oid opclass;
3797
3798 /* First we need to know the column's opclass. */
3799
3801 if (!HeapTupleIsValid(tuple))
3802 return InvalidOid;
3803
3804 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3805
3806 /* caller is supposed to guarantee this */
3807 Assert(attno > 0 && attno <= rd_index->indnatts);
3808
3809 /* Non-key attributes don't have an opclass */
3810 if (attno > rd_index->indnkeyatts)
3811 {
3812 ReleaseSysCache(tuple);
3813 return InvalidOid;
3814 }
3815
3817 indclass = ((oidvector *) DatumGetPointer(datum));
3818
3820 opclass = indclass->values[attno - 1];
3821
3822 ReleaseSysCache(tuple);
3823
3824 return opclass;
3825}
3826
3827/*
3828 * get_index_isreplident
3829 *
3830 * Given the index OID, return pg_index.indisreplident.
3831 */
3832bool
3834{
3835 HeapTuple tuple;
3836 Form_pg_index rd_index;
3837 bool result;
3838
3840 if (!HeapTupleIsValid(tuple))
3841 return false;
3842
3843 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3844 result = rd_index->indisreplident;
3845 ReleaseSysCache(tuple);
3846
3847 return result;
3848}
3849
3850/*
3851 * get_index_isvalid
3852 *
3853 * Given the index OID, return pg_index.indisvalid.
3854 */
3855bool
3857{
3858 bool isvalid;
3859 HeapTuple tuple;
3860 Form_pg_index rd_index;
3861
3863 if (!HeapTupleIsValid(tuple))
3864 elog(ERROR, "cache lookup failed for index %u", index_oid);
3865
3866 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3867 isvalid = rd_index->indisvalid;
3868 ReleaseSysCache(tuple);
3869
3870 return isvalid;
3871}
3872
3873/*
3874 * get_index_isclustered
3875 *
3876 * Given the index OID, return pg_index.indisclustered.
3877 */
3878bool
3880{
3881 bool isclustered;
3882 HeapTuple tuple;
3883 Form_pg_index rd_index;
3884
3886 if (!HeapTupleIsValid(tuple))
3887 elog(ERROR, "cache lookup failed for index %u", index_oid);
3888
3889 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3890 isclustered = rd_index->indisclustered;
3891 ReleaseSysCache(tuple);
3892
3893 return isclustered;
3894}
3895
3896/*
3897 * get_publication_oid - given a publication name, look up the OID
3898 *
3899 * If missing_ok is false, throw an error if name not found. If true, just
3900 * return InvalidOid.
3901 */
3902Oid
3903get_publication_oid(const char *pubname, bool missing_ok)
3904{
3905 Oid oid;
3906
3908 CStringGetDatum(pubname));
3909 if (!OidIsValid(oid) && !missing_ok)
3910 ereport(ERROR,
3912 errmsg("publication \"%s\" does not exist", pubname)));
3913 return oid;
3914}
3915
3916/*
3917 * get_publication_name - given a publication Oid, look up the name
3918 *
3919 * If missing_ok is false, throw an error if name not found. If true, just
3920 * return NULL.
3921 */
3922char *
3923get_publication_name(Oid pubid, bool missing_ok)
3924{
3925 HeapTuple tup;
3926 char *pubname;
3928
3930
3931 if (!HeapTupleIsValid(tup))
3932 {
3933 if (!missing_ok)
3934 elog(ERROR, "cache lookup failed for publication %u", pubid);
3935 return NULL;
3936 }
3937
3939 pubname = pstrdup(NameStr(pubform->pubname));
3940
3942
3943 return pubname;
3944}
3945
3946/*
3947 * get_subscription_oid - given a subscription name, look up the OID
3948 *
3949 * If missing_ok is false, throw an error if name not found. If true, just
3950 * return InvalidOid.
3951 */
3952Oid
3953get_subscription_oid(const char *subname, bool missing_ok)
3954{
3955 Oid oid;
3956
3959 if (!OidIsValid(oid) && !missing_ok)
3960 ereport(ERROR,
3962 errmsg("subscription \"%s\" does not exist", subname)));
3963 return oid;
3964}
3965
3966/*
3967 * get_subscription_name - given a subscription OID, look up the name
3968 *
3969 * If missing_ok is false, throw an error if name not found. If true, just
3970 * return NULL.
3971 */
3972char *
3973get_subscription_name(Oid subid, bool missing_ok)
3974{
3975 HeapTuple tup;
3976 char *subname;
3978
3980
3981 if (!HeapTupleIsValid(tup))
3982 {
3983 if (!missing_ok)
3984 elog(ERROR, "cache lookup failed for subscription %u", subid);
3985 return NULL;
3986 }
3987
3989 subname = pstrdup(NameStr(subform->subname));
3990
3992
3993 return subname;
3994}
3995
3996char *
3998{
3999 HeapTuple tuple;
4000 char *labelname;
4001
4003 if (!tuple)
4004 {
4005 elog(ERROR, "cache lookup failed for label %u", labeloid);
4006 return NULL;
4007 }
4009 ReleaseSysCache(tuple);
4010
4011 return labelname;
4012}
4013
4014char *
4016{
4017 HeapTuple tuple;
4018 char *propname;
4019
4021 if (!tuple)
4022 {
4023 elog(ERROR, "cache lookup failed for property %u", propoid);
4024 return NULL;
4025 }
4027 ReleaseSysCache(tuple);
4028
4029 return propname;
4030}
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:3660
char * get_rel_name(Oid relid)
Definition lsyscache.c:2159
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:1954
Oid get_opclass_method(Oid opclass)
Definition lsyscache.c:1443
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition lsyscache.c:477
bool get_rel_relispartition(Oid relid)
Definition lsyscache.c:2258
char * get_propgraph_property_name(Oid propoid)
Definition lsyscache.c:4015
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:886
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2309
char get_func_prokind(Oid funcid)
Definition lsyscache.c:2049
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3856
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition lsyscache.c:1164
RegProcedure get_range_constructor2(Oid rangeOid)
Definition lsyscache.c:3711
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition lsyscache.c:3206
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:1015
RegProcedure get_oprrest(Oid opno)
Definition lsyscache.c:1788
void free_attstatsslot(AttStatsSlot *sslot)
Definition lsyscache.c:3577
bool comparison_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:825
Oid get_constraint_index(Oid conoid)
Definition lsyscache.c:1270
bool get_func_retset(Oid funcid)
Definition lsyscache.c:1973
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:2992
Oid get_opclass_input_type(Oid opclass)
Definition lsyscache.c:1395
bool type_is_rowtype(Oid typid)
Definition lsyscache.c:2888
bool type_is_range(Oid typid)
Definition lsyscache.c:2921
char func_parallel(Oid funcid)
Definition lsyscache.c:2030
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1373
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1045
bool type_is_enum(Oid typid)
Definition lsyscache.c:2911
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3761
Oid get_typmodin(Oid typid)
Definition lsyscache.c:3239
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:2652
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition lsyscache.c:1418
RegProcedure get_func_support(Oid funcid)
Definition lsyscache.c:2089
char * get_database_name(Oid dbid)
Definition lsyscache.c:1323
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3140
bool get_typisdefined(Oid typid)
Definition lsyscache.c:2404
char * get_opname(Oid opno)
Definition lsyscache.c:1541
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1127
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2502
int32 get_attavgwidth(Oid relid, AttrNumber attnum)
Definition lsyscache.c:3391
bool get_index_isreplident(Oid index_oid)
Definition lsyscache.c:3833
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:953
RegProcedure get_oprjoin(Oid opno)
Definition lsyscache.c:1812
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition lsyscache.c:326
bool op_strict(Oid opno)
Definition lsyscache.c:1708
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1668
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2234
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2482
Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
Definition lsyscache.c:1927
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition lsyscache.c:3903
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2183
static bool get_opmethod_canorder(Oid amoid)
Definition lsyscache.c:223
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1516
Oid get_typcollation(Oid typid)
Definition lsyscache.c:3289
Oid get_op_rettype(Oid opno)
Definition lsyscache.c:1564
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:87
char * get_collation_name(Oid colloid)
Definition lsyscache.c:1192
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2210
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1344
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3623
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3107
char func_volatile(Oid funcid)
Definition lsyscache.c:2011
bool equality_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:773
get_attavgwidth_hook_type get_attavgwidth_hook
Definition lsyscache.c:57
bool op_is_safe_index_member(Oid opno)
Definition lsyscache.c:911
bool get_index_isclustered(Oid index_oid)
Definition lsyscache.c:3879
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:3997
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:2373
bool func_strict(Oid funcid)
Definition lsyscache.c:1992
Oid get_index_column_opclass(Oid index_oid, int attno)
Definition lsyscache.c:3790
char * get_constraint_name(Oid conoid)
Definition lsyscache.c:1238
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:984
bool get_func_leakproof(Oid funcid)
Definition lsyscache.c:2068
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition lsyscache.c:3363
Node * get_typdefault(Oid typid)
Definition lsyscache.c:2681
bool get_collation_isdeterministic(Oid colloid)
Definition lsyscache.c:1211
List * get_op_index_interpretation(Oid opno)
Definition lsyscache.c:668
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition lsyscache.c:3953
char * get_subscription_name(Oid subid, bool missing_ok)
Definition lsyscache.c:3973
Oid get_range_collation(Oid rangeOid)
Definition lsyscache.c:3686
char * get_opfamily_name(Oid opfid, bool missing_ok)
Definition lsyscache.c:1484
char * get_func_name(Oid funcid)
Definition lsyscache.c:1839
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3736
Oid get_rel_relam(Oid relid)
Definition lsyscache.c:2331
char op_volatile(Oid opno)
Definition lsyscache.c:1724
Oid get_func_namespace(Oid funcid)
Definition lsyscache.c:1863
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3314
Oid get_rel_tablespace(Oid relid)
Definition lsyscache.c:2285
int get_func_nargs(Oid funcid)
Definition lsyscache.c:1905
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:2556
int16 get_typlen(Oid typid)
Definition lsyscache.c:2428
Oid get_typ_typrelid(Oid typid)
Definition lsyscache.c:2964
char get_typtype(Oid typid)
Definition lsyscache.c:2862
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:3065
Oid getTypeIOParam(HeapTuple typeTuple)
Definition lsyscache.c:2534
Oid get_opfamily_method(Oid opfid)
Definition lsyscache.c:1467
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition lsyscache.c:2771
char * get_qualified_objname(Oid nspid, char *objname)
Definition lsyscache.c:3637
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition lsyscache.c:2351
char * get_publication_name(Oid pubid, bool missing_ok)
Definition lsyscache.c:3923
Oid getBaseType(Oid typid)
Definition lsyscache.c:2754
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:577
bool get_typbyval(Oid typid)
Definition lsyscache.c:2453
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1617
List * get_mergejoin_opfamilies(Oid opno)
Definition lsyscache.c:430
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3599
Oid get_array_type(Oid typid)
Definition lsyscache.c:3020
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1886
Oid get_promoted_array_type(Oid typid)
Definition lsyscache.c:3044
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1070
char get_constraint_type(Oid conoid)
Definition lsyscache.c:1300
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition lsyscache.c:2811
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition lsyscache.c:70
RegProcedure get_typsubscript(Oid typid, Oid *typelemp)
Definition lsyscache.c:3330
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
Definition lsyscache.c:2943
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition lsyscache.c:3467
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2116
Oid get_negator(Oid opno)
Definition lsyscache.c:1764
Oid get_commutator(Oid opno)
Definition lsyscache.c:1740
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:1589
bool type_is_multirange(Oid typid)
Definition lsyscache.c:2931
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition lsyscache.c:3173
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition lsyscache.c:1100
#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:495
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