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