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"
38#include "catalog/pg_range.h"
42#include "catalog/pg_type.h"
43#include "miscadmin.h"
44#include "nodes/makefuncs.h"
45#include "utils/array.h"
46#include "utils/builtins.h"
47#include "utils/catcache.h"
48#include "utils/datum.h"
49#include "utils/fmgroids.h"
50#include "utils/lsyscache.h"
51#include "utils/syscache.h"
52#include "utils/typcache.h"
53
54/* Hook for plugins to get control in get_attavgwidth() */
56
57
58/* ---------- AMOP CACHES ---------- */
59
60/*
61 * op_in_opfamily
62 *
63 * Return t iff operator 'opno' is in operator family 'opfamily'.
64 *
65 * This function only considers search operators, not ordering operators.
66 */
67bool
68op_in_opfamily(Oid opno, Oid opfamily)
69{
71 ObjectIdGetDatum(opno),
73 ObjectIdGetDatum(opfamily));
74}
75
76/*
77 * get_op_opfamily_strategy
78 *
79 * Get the operator's strategy number within the specified opfamily,
80 * or 0 if it's not a member of the opfamily.
81 *
82 * This function only considers search operators, not ordering operators.
83 */
84int
86{
87 HeapTuple tp;
89 int result;
90
92 ObjectIdGetDatum(opno),
94 ObjectIdGetDatum(opfamily));
95 if (!HeapTupleIsValid(tp))
96 return 0;
98 result = amop_tup->amopstrategy;
100 return result;
101}
102
103/*
104 * get_op_opfamily_sortfamily
105 *
106 * If the operator is an ordering operator within the specified opfamily,
107 * return its amopsortfamily OID; else return InvalidOid.
108 */
109Oid
111{
112 HeapTuple tp;
114 Oid result;
115
117 ObjectIdGetDatum(opno),
119 ObjectIdGetDatum(opfamily));
120 if (!HeapTupleIsValid(tp))
121 return InvalidOid;
123 result = amop_tup->amopsortfamily;
124 ReleaseSysCache(tp);
125 return result;
126}
127
128/*
129 * get_op_opfamily_properties
130 *
131 * Get the operator's strategy number and declared input data types
132 * within the specified opfamily.
133 *
134 * Caller should already have verified that opno is a member of opfamily,
135 * therefore we raise an error if the tuple is not found.
136 */
137void
139 int *strategy,
140 Oid *lefttype,
141 Oid *righttype)
142{
143 HeapTuple tp;
145
147 ObjectIdGetDatum(opno),
149 ObjectIdGetDatum(opfamily));
150 if (!HeapTupleIsValid(tp))
151 elog(ERROR, "operator %u is not a member of opfamily %u",
152 opno, opfamily);
154 *strategy = amop_tup->amopstrategy;
155 *lefttype = amop_tup->amoplefttype;
156 *righttype = amop_tup->amoprighttype;
157 ReleaseSysCache(tp);
158}
159
160/*
161 * get_opfamily_member
162 * Get the OID of the operator that implements the specified strategy
163 * with the specified datatypes for the specified opfamily.
164 *
165 * Returns InvalidOid if there is no pg_amop entry for the given keys.
166 */
167Oid
168get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
169 int16 strategy)
170{
171 HeapTuple tp;
173 Oid result;
174
176 ObjectIdGetDatum(opfamily),
177 ObjectIdGetDatum(lefttype),
178 ObjectIdGetDatum(righttype),
179 Int16GetDatum(strategy));
180 if (!HeapTupleIsValid(tp))
181 return InvalidOid;
183 result = amop_tup->amopopr;
184 ReleaseSysCache(tp);
185 return result;
186}
187
188/*
189 * get_opfamily_member_for_cmptype
190 * Get the OID of the operator that implements the specified comparison
191 * type with the specified datatypes for the specified opfamily.
192 *
193 * Returns InvalidOid if there is no mapping for the comparison type or no
194 * pg_amop entry for the given keys.
195 */
196Oid
197get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype,
198 CompareType cmptype)
199{
201 StrategyNumber strategy;
202
203 opmethod = get_opfamily_method(opfamily);
204 strategy = IndexAmTranslateCompareType(cmptype, opmethod, opfamily, true);
205 if (!strategy)
206 return InvalidOid;
207 return get_opfamily_member(opfamily, lefttype, righttype, strategy);
208}
209
210/*
211 * get_opmethod_canorder
212 * Return amcanorder field for given index AM.
213 *
214 * To speed things up in the common cases, we're hardcoding the results from
215 * the built-in index types. Note that we also need to hardcode the negative
216 * results from the built-in non-btree index types, since you'll usually get a
217 * few hits for those as well. It would be nice to organize and cache this a
218 * bit differently to avoid the hardcoding.
219 */
220static bool
222{
223 switch (amoid)
224 {
225 case BTREE_AM_OID:
226 return true;
227 case HASH_AM_OID:
228 case GIST_AM_OID:
229 case GIN_AM_OID:
230 case SPGIST_AM_OID:
231 case BRIN_AM_OID:
232 return false;
233 default:
235 }
236}
237
238/*
239 * get_ordering_op_properties
240 * Given the OID of an ordering operator (a "<" or ">" operator),
241 * determine its opfamily, its declared input datatype, and its
242 * comparison type.
243 *
244 * Returns true if successful, false if no matching pg_amop entry exists.
245 * (This indicates that the operator is not a valid ordering operator.)
246 *
247 * Note: the operator could be registered in multiple families, for example
248 * if someone were to build a "reverse sort" opfamily. This would result in
249 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
250 * or NULLS LAST, as well as inefficient planning due to failure to match up
251 * pathkeys that should be the same. So we want a determinate result here.
252 * Because of the way the syscache search works, we'll use the interpretation
253 * associated with the opfamily with smallest OID, which is probably
254 * determinate enough. Since there is no longer any particularly good reason
255 * to build reverse-sort opfamilies, it doesn't seem worth expending any
256 * additional effort on ensuring consistency.
257 */
258bool
260 Oid *opfamily, Oid *opcintype, CompareType *cmptype)
261{
262 bool result = false;
264 int i;
265
266 /* ensure outputs are initialized on failure */
267 *opfamily = InvalidOid;
268 *opcintype = InvalidOid;
269 *cmptype = COMPARE_INVALID;
270
271 /*
272 * Search pg_amop to see if the target operator is registered as the "<"
273 * or ">" operator of any btree opfamily.
274 */
276
277 for (i = 0; i < catlist->n_members; i++)
278 {
279 HeapTuple tuple = &catlist->members[i]->tuple;
282
283 /* must be ordering index */
284 if (!get_opmethod_canorder(aform->amopmethod))
285 continue;
286
288 aform->amopmethod,
289 aform->amopfamily,
290 true);
291
293 {
294 /* Found it ... should have consistent input types */
295 if (aform->amoplefttype == aform->amoprighttype)
296 {
297 /* Found a suitable opfamily, return info */
298 *opfamily = aform->amopfamily;
299 *opcintype = aform->amoplefttype;
300 *cmptype = am_cmptype;
301 result = true;
302 break;
303 }
304 }
305 }
306
308
309 return result;
310}
311
312/*
313 * get_equality_op_for_ordering_op
314 * Get the OID of the datatype-specific equality operator
315 * associated with an ordering operator (a "<" or ">" operator).
316 *
317 * If "reverse" isn't NULL, also set *reverse to false if the operator is "<",
318 * true if it's ">"
319 *
320 * Returns InvalidOid if no matching equality operator can be found.
321 * (This indicates that the operator is not a valid ordering operator.)
322 */
323Oid
325{
326 Oid result = InvalidOid;
327 Oid opfamily;
328 Oid opcintype;
329 CompareType cmptype;
330
331 /* Find the operator in pg_amop */
333 &opfamily, &opcintype, &cmptype))
334 {
335 /* Found a suitable opfamily, get matching equality operator */
336 result = get_opfamily_member_for_cmptype(opfamily,
337 opcintype,
338 opcintype,
339 COMPARE_EQ);
340 if (reverse)
341 *reverse = (cmptype == COMPARE_GT);
342 }
343
344 return result;
345}
346
347/*
348 * get_ordering_op_for_equality_op
349 * Get the OID of a datatype-specific "less than" ordering operator
350 * associated with an equality operator. (If there are multiple
351 * possibilities, assume any one will do.)
352 *
353 * This function is used when we have to sort data before unique-ifying,
354 * and don't much care which sorting op is used as long as it's compatible
355 * with the intended equality operator. Since we need a sorting operator,
356 * it should be single-data-type even if the given operator is cross-type.
357 * The caller specifies whether to find an op for the LHS or RHS data type.
358 *
359 * Returns InvalidOid if no matching ordering operator can be found.
360 */
361Oid
363{
364 Oid result = InvalidOid;
366 int i;
367
368 /*
369 * Search pg_amop to see if the target operator is registered as the "="
370 * operator of any btree opfamily.
371 */
373
374 for (i = 0; i < catlist->n_members; i++)
375 {
376 HeapTuple tuple = &catlist->members[i]->tuple;
378 CompareType cmptype;
379
380 /* must be ordering index */
381 if (!get_opmethod_canorder(aform->amopmethod))
382 continue;
383
384 cmptype = IndexAmTranslateStrategy(aform->amopstrategy,
385 aform->amopmethod,
386 aform->amopfamily,
387 true);
388 if (cmptype == COMPARE_EQ)
389 {
390 /* Found a suitable opfamily, get matching ordering operator */
391 Oid typid;
392
393 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
394 result = get_opfamily_member_for_cmptype(aform->amopfamily,
395 typid, typid,
396 COMPARE_LT);
397 if (OidIsValid(result))
398 break;
399 /* failure probably shouldn't happen, but keep looking if so */
400 }
401 }
402
404
405 return result;
406}
407
408/*
409 * get_mergejoin_opfamilies
410 * Given a putatively mergejoinable operator, return a list of the OIDs
411 * of the amcanorder opfamilies in which it represents equality.
412 *
413 * It is possible (though at present unusual) for an operator to be equality
414 * in more than one opfamily, hence the result is a list. This also lets us
415 * return NIL if the operator is not found in any opfamilies.
416 *
417 * The planner currently uses simple equal() tests to compare the lists
418 * returned by this function, which makes the list order relevant, though
419 * strictly speaking it should not be. Because of the way syscache list
420 * searches are handled, in normal operation the result will be sorted by OID
421 * so everything works fine. If running with system index usage disabled,
422 * the result ordering is unspecified and hence the planner might fail to
423 * recognize optimization opportunities ... but that's hardly a scenario in
424 * which performance is good anyway, so there's no point in expending code
425 * or cycles here to guarantee the ordering in that case.
426 */
427List *
429{
430 List *result = NIL;
432 int i;
433
434 /*
435 * Search pg_amop to see if the target operator is registered as the "="
436 * operator of any opfamily of an ordering index type.
437 */
439
440 for (i = 0; i < catlist->n_members; i++)
441 {
442 HeapTuple tuple = &catlist->members[i]->tuple;
444
445 /* must be ordering index equality */
446 if (get_opmethod_canorder(aform->amopmethod) &&
447 IndexAmTranslateStrategy(aform->amopstrategy,
448 aform->amopmethod,
449 aform->amopfamily,
450 true) == COMPARE_EQ)
451 result = lappend_oid(result, aform->amopfamily);
452 }
453
455
456 return result;
457}
458
459/*
460 * get_compatible_hash_operators
461 * Get the OID(s) of hash equality operator(s) compatible with the given
462 * operator, but operating on its LHS and/or RHS datatype.
463 *
464 * An operator for the LHS type is sought and returned into *lhs_opno if
465 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
466 * and returned into *rhs_opno if rhs_opno isn't NULL.
467 *
468 * If the given operator is not cross-type, the results should be the same
469 * operator, but in cross-type situations they will be different.
470 *
471 * Returns true if able to find the requested operator(s), false if not.
472 * (This indicates that the operator should not have been marked oprcanhash.)
473 */
474bool
477{
478 bool result = false;
480 int i;
481
482 /* Ensure output args are initialized on failure */
483 if (lhs_opno)
485 if (rhs_opno)
487
488 /*
489 * Search pg_amop to see if the target operator is registered as the "="
490 * operator of any hash opfamily. If the operator is registered in
491 * multiple opfamilies, assume we can use any one.
492 */
494
495 for (i = 0; i < catlist->n_members; i++)
496 {
497 HeapTuple tuple = &catlist->members[i]->tuple;
499
500 if (aform->amopmethod == HASH_AM_OID &&
501 aform->amopstrategy == HTEqualStrategyNumber)
502 {
503 /* No extra lookup needed if given operator is single-type */
504 if (aform->amoplefttype == aform->amoprighttype)
505 {
506 if (lhs_opno)
507 *lhs_opno = opno;
508 if (rhs_opno)
509 *rhs_opno = opno;
510 result = true;
511 break;
512 }
513
514 /*
515 * Get the matching single-type operator(s). Failure probably
516 * shouldn't happen --- it implies a bogus opfamily --- but
517 * continue looking if so.
518 */
519 if (lhs_opno)
520 {
521 *lhs_opno = get_opfamily_member(aform->amopfamily,
522 aform->amoplefttype,
523 aform->amoplefttype,
525 if (!OidIsValid(*lhs_opno))
526 continue;
527 /* Matching LHS found, done if caller doesn't want RHS */
528 if (!rhs_opno)
529 {
530 result = true;
531 break;
532 }
533 }
534 if (rhs_opno)
535 {
536 *rhs_opno = get_opfamily_member(aform->amopfamily,
537 aform->amoprighttype,
538 aform->amoprighttype,
540 if (!OidIsValid(*rhs_opno))
541 {
542 /* Forget any LHS operator from this opfamily */
543 if (lhs_opno)
545 continue;
546 }
547 /* Matching RHS found, so done */
548 result = true;
549 break;
550 }
551 }
552 }
553
555
556 return result;
557}
558
559/*
560 * get_op_hash_functions
561 * Get the OID(s) of the standard hash support function(s) compatible with
562 * the given operator, operating on its LHS and/or RHS datatype as required.
563 *
564 * A function for the LHS type is sought and returned into *lhs_procno if
565 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
566 * and returned into *rhs_procno if rhs_procno isn't NULL.
567 *
568 * If the given operator is not cross-type, the results should be the same
569 * function, but in cross-type situations they will be different.
570 *
571 * Returns true if able to find the requested function(s), false if not.
572 * (This indicates that the operator should not have been marked oprcanhash.)
573 */
574bool
577{
578 bool result = false;
580 int i;
581
582 /* Ensure output args are initialized on failure */
583 if (lhs_procno)
585 if (rhs_procno)
587
588 /*
589 * Search pg_amop to see if the target operator is registered as the "="
590 * operator of any hash opfamily. If the operator is registered in
591 * multiple opfamilies, assume we can use any one.
592 */
594
595 for (i = 0; i < catlist->n_members; i++)
596 {
597 HeapTuple tuple = &catlist->members[i]->tuple;
599
600 if (aform->amopmethod == HASH_AM_OID &&
601 aform->amopstrategy == HTEqualStrategyNumber)
602 {
603 /*
604 * Get the matching support function(s). Failure probably
605 * shouldn't happen --- it implies a bogus opfamily --- but
606 * continue looking if so.
607 */
608 if (lhs_procno)
609 {
610 *lhs_procno = get_opfamily_proc(aform->amopfamily,
611 aform->amoplefttype,
612 aform->amoplefttype,
614 if (!OidIsValid(*lhs_procno))
615 continue;
616 /* Matching LHS found, done if caller doesn't want RHS */
617 if (!rhs_procno)
618 {
619 result = true;
620 break;
621 }
622 /* Only one lookup needed if given operator is single-type */
623 if (aform->amoplefttype == aform->amoprighttype)
624 {
626 result = true;
627 break;
628 }
629 }
630 if (rhs_procno)
631 {
632 *rhs_procno = get_opfamily_proc(aform->amopfamily,
633 aform->amoprighttype,
634 aform->amoprighttype,
636 if (!OidIsValid(*rhs_procno))
637 {
638 /* Forget any LHS function from this opfamily */
639 if (lhs_procno)
641 continue;
642 }
643 /* Matching RHS found, so done */
644 result = true;
645 break;
646 }
647 }
648 }
649
651
652 return result;
653}
654
655/*
656 * get_op_index_interpretation
657 * Given an operator's OID, find out which amcanorder opfamilies it belongs to,
658 * and what properties it has within each one. The results are returned
659 * as a palloc'd list of OpIndexInterpretation structs.
660 *
661 * In addition to the normal btree operators, we consider a <> operator to be
662 * a "member" of an opfamily if its negator is an equality operator of the
663 * opfamily. COMPARE_NE is returned as the strategy number for this case.
664 */
665List *
667{
668 List *result = NIL;
671 int i;
672
673 /*
674 * Find all the pg_amop entries containing the operator.
675 */
677
678 for (i = 0; i < catlist->n_members; i++)
679 {
680 HeapTuple op_tuple = &catlist->members[i]->tuple;
682 CompareType cmptype;
683
684 /* must be ordering index */
685 if (!get_opmethod_canorder(op_form->amopmethod))
686 continue;
687
688 /* Get the operator's comparison type */
689 cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
690 op_form->amopmethod,
691 op_form->amopfamily,
692 true);
693
694 /* should not happen */
695 if (cmptype == COMPARE_INVALID)
696 continue;
697
699 thisresult->opfamily_id = op_form->amopfamily;
700 thisresult->cmptype = cmptype;
701 thisresult->oplefttype = op_form->amoplefttype;
702 thisresult->oprighttype = op_form->amoprighttype;
703 result = lappend(result, thisresult);
704 }
705
707
708 /*
709 * If we didn't find any btree opfamily containing the operator, perhaps
710 * it is a <> operator. See if it has a negator that is in an opfamily.
711 */
712 if (result == NIL)
713 {
714 Oid op_negator = get_negator(opno);
715
717 {
720
721 for (i = 0; i < catlist->n_members; i++)
722 {
723 HeapTuple op_tuple = &catlist->members[i]->tuple;
725 const IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
726 CompareType cmptype;
727
728 /* must be ordering index */
729 if (!amroutine->amcanorder)
730 continue;
731
732 /* Get the operator's comparison type */
733 cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
734 op_form->amopmethod,
735 op_form->amopfamily,
736 true);
737
738 /* Only consider negators that are = */
739 if (cmptype != COMPARE_EQ)
740 continue;
741
742 /* OK, report it as COMPARE_NE */
744 thisresult->opfamily_id = op_form->amopfamily;
745 thisresult->cmptype = COMPARE_NE;
746 thisresult->oplefttype = op_form->amoplefttype;
747 thisresult->oprighttype = op_form->amoprighttype;
748 result = lappend(result, thisresult);
749 }
750
752 }
753 }
754
755 return result;
756}
757
758/*
759 * equality_ops_are_compatible
760 * Return true if the two given equality operators have compatible
761 * semantics.
762 *
763 * This is trivially true if they are the same operator. Otherwise,
764 * we look to see if they both belong to an opfamily that guarantees
765 * compatible semantics for equality. Either finding allows us to assume
766 * that they have compatible notions of equality. (The reason we need
767 * to do these pushups is that one might be a cross-type operator; for
768 * instance int24eq vs int4eq.)
769 */
770bool
772{
773 bool result;
775 int i;
776
777 /* Easy if they're the same operator */
778 if (opno1 == opno2)
779 return true;
780
781 /*
782 * We search through all the pg_amop entries for opno1.
783 */
785
786 result = false;
787 for (i = 0; i < catlist->n_members; i++)
788 {
789 HeapTuple op_tuple = &catlist->members[i]->tuple;
791
792 /*
793 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
794 * check it first
795 */
796 if (op_in_opfamily(opno2, op_form->amopfamily) &&
798 {
799 result = true;
800 break;
801 }
802 }
803
805
806 return result;
807}
808
809/*
810 * comparison_ops_are_compatible
811 * Return true if the two given comparison operators have compatible
812 * semantics.
813 *
814 * This is trivially true if they are the same operator. Otherwise, we look
815 * to see if they both belong to an opfamily that guarantees compatible
816 * semantics for ordering. (For example, for btree, '<' and '>=' ops match if
817 * they belong to the same family.)
818 *
819 * (This is identical to equality_ops_are_compatible(), except that we check
820 * amconsistentordering instead of amconsistentequality.)
821 */
822bool
824{
825 bool result;
827 int i;
828
829 /* Easy if they're the same operator */
830 if (opno1 == opno2)
831 return true;
832
833 /*
834 * We search through all the pg_amop entries for opno1.
835 */
837
838 result = false;
839 for (i = 0; i < catlist->n_members; i++)
840 {
841 HeapTuple op_tuple = &catlist->members[i]->tuple;
843
844 /*
845 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
846 * check it first
847 */
848 if (op_in_opfamily(opno2, op_form->amopfamily) &&
850 {
851 result = true;
852 break;
853 }
854 }
855
857
858 return result;
859}
860
861
862/* ---------- AMPROC CACHES ---------- */
863
864/*
865 * get_opfamily_proc
866 * Get the OID of the specified support function
867 * for the specified opfamily and datatypes.
868 *
869 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
870 */
871Oid
872get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
873{
874 HeapTuple tp;
876 RegProcedure result;
877
879 ObjectIdGetDatum(opfamily),
880 ObjectIdGetDatum(lefttype),
881 ObjectIdGetDatum(righttype),
883 if (!HeapTupleIsValid(tp))
884 return InvalidOid;
886 result = amproc_tup->amproc;
887 ReleaseSysCache(tp);
888 return result;
889}
890
891
892/* ---------- ATTRIBUTE CACHES ---------- */
893
894/*
895 * get_attname
896 * Given the relation id and the attribute number, return the "attname"
897 * field from the attribute relation as a palloc'ed string.
898 *
899 * If no such attribute exists and missing_ok is true, NULL is returned;
900 * otherwise a not-intended-for-user-consumption error is thrown.
901 */
902char *
903get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
904{
905 HeapTuple tp;
906
909 if (HeapTupleIsValid(tp))
910 {
912 char *result;
913
914 result = pstrdup(NameStr(att_tup->attname));
915 ReleaseSysCache(tp);
916 return result;
917 }
918
919 if (!missing_ok)
920 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
921 attnum, relid);
922 return NULL;
923}
924
925/*
926 * get_attnum
927 *
928 * Given the relation id and the attribute name,
929 * return the "attnum" field from the attribute relation.
930 *
931 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
932 */
934get_attnum(Oid relid, const char *attname)
935{
936 HeapTuple tp;
937
938 tp = SearchSysCacheAttName(relid, attname);
939 if (HeapTupleIsValid(tp))
940 {
942 AttrNumber result;
943
944 result = att_tup->attnum;
945 ReleaseSysCache(tp);
946 return result;
947 }
948 else
949 return InvalidAttrNumber;
950}
951
952/*
953 * get_attgenerated
954 *
955 * Given the relation id and the attribute number,
956 * return the "attgenerated" field from the attribute relation.
957 *
958 * Errors if not found.
959 *
960 * Since not generated is represented by '\0', this can also be used as a
961 * Boolean test.
962 */
963char
965{
966 HeapTuple tp;
968 char result;
969
971 ObjectIdGetDatum(relid),
973 if (!HeapTupleIsValid(tp))
974 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
975 attnum, relid);
977 result = att_tup->attgenerated;
978 ReleaseSysCache(tp);
979 return result;
980}
981
982/*
983 * get_atttype
984 *
985 * Given the relation OID and the attribute number with the relation,
986 * return the attribute type OID.
987 */
988Oid
990{
991 HeapTuple tp;
992
994 ObjectIdGetDatum(relid),
996 if (HeapTupleIsValid(tp))
997 {
999 Oid result;
1000
1001 result = att_tup->atttypid;
1002 ReleaseSysCache(tp);
1003 return result;
1004 }
1005 else
1006 return InvalidOid;
1007}
1008
1009/*
1010 * get_atttypetypmodcoll
1011 *
1012 * A three-fer: given the relation id and the attribute number,
1013 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
1014 *
1015 * Unlike the otherwise-similar get_atttype, this routine
1016 * raises an error if it can't obtain the information.
1017 */
1018void
1020 Oid *typid, int32 *typmod, Oid *collid)
1021{
1022 HeapTuple tp;
1024
1026 ObjectIdGetDatum(relid),
1028 if (!HeapTupleIsValid(tp))
1029 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1030 attnum, relid);
1032
1033 *typid = att_tup->atttypid;
1034 *typmod = att_tup->atttypmod;
1035 *collid = att_tup->attcollation;
1036 ReleaseSysCache(tp);
1037}
1038
1039/*
1040 * get_attoptions
1041 *
1042 * Given the relation id and the attribute number,
1043 * return the attribute options text[] datum, if any.
1044 */
1045Datum
1047{
1048 HeapTuple tuple;
1049 Datum attopts;
1050 Datum result;
1051 bool isnull;
1052
1053 tuple = SearchSysCache2(ATTNUM,
1054 ObjectIdGetDatum(relid),
1056
1057 if (!HeapTupleIsValid(tuple))
1058 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1059 attnum, relid);
1060
1062 &isnull);
1063
1064 if (isnull)
1065 result = (Datum) 0;
1066 else
1067 result = datumCopy(attopts, false, -1); /* text[] */
1068
1069 ReleaseSysCache(tuple);
1070
1071 return result;
1072}
1073
1074/* ---------- PG_CAST CACHE ---------- */
1075
1076/*
1077 * get_cast_oid - given two type OIDs, look up a cast OID
1078 *
1079 * If missing_ok is false, throw an error if the cast is not found. If
1080 * true, just return InvalidOid.
1081 */
1082Oid
1084{
1085 Oid oid;
1086
1090 if (!OidIsValid(oid) && !missing_ok)
1091 ereport(ERROR,
1093 errmsg("cast from type %s to type %s does not exist",
1096 return oid;
1097}
1098
1099/* ---------- COLLATION CACHE ---------- */
1100
1101/*
1102 * get_collation_name
1103 * Returns the name of a given pg_collation entry.
1104 *
1105 * Returns a palloc'd copy of the string, or NULL if no such collation.
1106 *
1107 * NOTE: since collation name is not unique, be wary of code that uses this
1108 * for anything except preparing error messages.
1109 */
1110char *
1112{
1113 HeapTuple tp;
1114
1116 if (HeapTupleIsValid(tp))
1117 {
1119 char *result;
1120
1121 result = pstrdup(NameStr(colltup->collname));
1122 ReleaseSysCache(tp);
1123 return result;
1124 }
1125 else
1126 return NULL;
1127}
1128
1129bool
1131{
1132 HeapTuple tp;
1134 bool result;
1135
1137 if (!HeapTupleIsValid(tp))
1138 elog(ERROR, "cache lookup failed for collation %u", colloid);
1140 result = colltup->collisdeterministic;
1141 ReleaseSysCache(tp);
1142 return result;
1143}
1144
1145/* ---------- CONSTRAINT CACHE ---------- */
1146
1147/*
1148 * get_constraint_name
1149 * Returns the name of a given pg_constraint entry.
1150 *
1151 * Returns a palloc'd copy of the string, or NULL if no such constraint.
1152 *
1153 * NOTE: since constraint name is not unique, be wary of code that uses this
1154 * for anything except preparing error messages.
1155 */
1156char *
1158{
1159 HeapTuple tp;
1160
1162 if (HeapTupleIsValid(tp))
1163 {
1165 char *result;
1166
1167 result = pstrdup(NameStr(contup->conname));
1168 ReleaseSysCache(tp);
1169 return result;
1170 }
1171 else
1172 return NULL;
1173}
1174
1175/*
1176 * get_constraint_index
1177 * Given the OID of a unique, primary-key, or exclusion constraint,
1178 * return the OID of the underlying index.
1179 *
1180 * Returns InvalidOid if the constraint could not be found or is of
1181 * the wrong type.
1182 *
1183 * The intent of this function is to return the index "owned" by the
1184 * specified constraint. Therefore we must check contype, since some
1185 * pg_constraint entries (e.g. for foreign-key constraints) store the
1186 * OID of an index that is referenced but not owned by the constraint.
1187 */
1188Oid
1190{
1191 HeapTuple tp;
1192
1194 if (HeapTupleIsValid(tp))
1195 {
1197 Oid result;
1198
1199 if (contup->contype == CONSTRAINT_UNIQUE ||
1200 contup->contype == CONSTRAINT_PRIMARY ||
1201 contup->contype == CONSTRAINT_EXCLUSION)
1202 result = contup->conindid;
1203 else
1204 result = InvalidOid;
1205 ReleaseSysCache(tp);
1206 return result;
1207 }
1208 else
1209 return InvalidOid;
1210}
1211
1212/*
1213 * get_constraint_type
1214 * Return the pg_constraint.contype value for the given constraint.
1215 *
1216 * No frills.
1217 */
1218char
1220{
1221 HeapTuple tp;
1222 char contype;
1223
1225 if (!HeapTupleIsValid(tp))
1226 elog(ERROR, "cache lookup failed for constraint %u", conoid);
1227
1228 contype = ((Form_pg_constraint) GETSTRUCT(tp))->contype;
1229 ReleaseSysCache(tp);
1230
1231 return contype;
1232}
1233
1234/* ---------- DATABASE CACHE ---------- */
1235
1236/*
1237 * get_database_name - given a database OID, look up the name
1238 *
1239 * Returns a palloc'd string, or NULL if no such database.
1240 */
1241char *
1243{
1245 char *result;
1246
1249 {
1252 }
1253 else
1254 result = NULL;
1255
1256 return result;
1257}
1258
1259
1260/* ---------- LANGUAGE CACHE ---------- */
1261
1262char *
1264{
1265 HeapTuple tp;
1266
1268 if (HeapTupleIsValid(tp))
1269 {
1271 char *result;
1272
1273 result = pstrdup(NameStr(lantup->lanname));
1274 ReleaseSysCache(tp);
1275 return result;
1276 }
1277
1278 if (!missing_ok)
1279 elog(ERROR, "cache lookup failed for language %u",
1280 langoid);
1281 return NULL;
1282}
1283
1284/* ---------- OPCLASS CACHE ---------- */
1285
1286/*
1287 * get_opclass_family
1288 *
1289 * Returns the OID of the operator family the opclass belongs to.
1290 */
1291Oid
1293{
1294 HeapTuple tp;
1296 Oid result;
1297
1298 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1299 if (!HeapTupleIsValid(tp))
1300 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1302
1303 result = cla_tup->opcfamily;
1304 ReleaseSysCache(tp);
1305 return result;
1306}
1307
1308/*
1309 * get_opclass_input_type
1310 *
1311 * Returns the OID of the datatype the opclass indexes.
1312 */
1313Oid
1315{
1316 HeapTuple tp;
1318 Oid result;
1319
1320 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1321 if (!HeapTupleIsValid(tp))
1322 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1324
1325 result = cla_tup->opcintype;
1326 ReleaseSysCache(tp);
1327 return result;
1328}
1329
1330/*
1331 * get_opclass_opfamily_and_input_type
1332 *
1333 * Returns the OID of the operator family the opclass belongs to,
1334 * the OID of the datatype the opclass indexes
1335 */
1336bool
1337get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1338{
1339 HeapTuple tp;
1341
1342 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1343 if (!HeapTupleIsValid(tp))
1344 return false;
1345
1347
1348 *opfamily = cla_tup->opcfamily;
1349 *opcintype = cla_tup->opcintype;
1350
1351 ReleaseSysCache(tp);
1352
1353 return true;
1354}
1355
1356/*
1357 * get_opclass_method
1358 *
1359 * Returns the OID of the index access method 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->opcmethod;
1374 ReleaseSysCache(tp);
1375 return result;
1376}
1377
1378/* ---------- OPFAMILY CACHE ---------- */
1379
1380/*
1381 * get_opfamily_method
1382 *
1383 * Returns the OID of the index access method the opfamily is for.
1384 */
1385Oid
1387{
1388 HeapTuple tp;
1390 Oid result;
1391
1393 if (!HeapTupleIsValid(tp))
1394 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1396
1397 result = opfform->opfmethod;
1398 ReleaseSysCache(tp);
1399 return result;
1400}
1401
1402char *
1403get_opfamily_name(Oid opfid, bool missing_ok)
1404{
1405 HeapTuple tup;
1406 char *opfname;
1408
1410
1411 if (!HeapTupleIsValid(tup))
1412 {
1413 if (!missing_ok)
1414 elog(ERROR, "cache lookup failed for operator family %u", opfid);
1415 return NULL;
1416 }
1417
1419 opfname = pstrdup(NameStr(opfform->opfname));
1420
1422
1423 return opfname;
1424}
1425
1426/* ---------- OPERATOR CACHE ---------- */
1427
1428/*
1429 * get_opcode
1430 *
1431 * Returns the regproc id of the routine used to implement an
1432 * operator given the operator oid.
1433 */
1436{
1437 HeapTuple tp;
1438
1440 if (HeapTupleIsValid(tp))
1441 {
1443 RegProcedure result;
1444
1445 result = optup->oprcode;
1446 ReleaseSysCache(tp);
1447 return result;
1448 }
1449 else
1450 return (RegProcedure) InvalidOid;
1451}
1452
1453/*
1454 * get_opname
1455 * returns the name of the operator with the given opno
1456 *
1457 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1458 */
1459char *
1461{
1462 HeapTuple tp;
1463
1465 if (HeapTupleIsValid(tp))
1466 {
1468 char *result;
1469
1470 result = pstrdup(NameStr(optup->oprname));
1471 ReleaseSysCache(tp);
1472 return result;
1473 }
1474 else
1475 return NULL;
1476}
1477
1478/*
1479 * get_op_rettype
1480 * Given operator oid, return the operator's result type.
1481 */
1482Oid
1484{
1485 HeapTuple tp;
1486
1488 if (HeapTupleIsValid(tp))
1489 {
1491 Oid result;
1492
1493 result = optup->oprresult;
1494 ReleaseSysCache(tp);
1495 return result;
1496 }
1497 else
1498 return InvalidOid;
1499}
1500
1501/*
1502 * op_input_types
1503 *
1504 * Returns the left and right input datatypes for an operator
1505 * (InvalidOid if not relevant).
1506 */
1507void
1508op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1509{
1510 HeapTuple tp;
1512
1514 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1515 elog(ERROR, "cache lookup failed for operator %u", opno);
1517 *lefttype = optup->oprleft;
1518 *righttype = optup->oprright;
1519 ReleaseSysCache(tp);
1520}
1521
1522/*
1523 * op_mergejoinable
1524 *
1525 * Returns true if the operator is potentially mergejoinable. (The planner
1526 * will fail to find any mergejoin plans unless there are suitable btree
1527 * opfamily entries for this operator and associated sortops. The pg_operator
1528 * flag is just a hint to tell the planner whether to bother looking.)
1529 *
1530 * In some cases (currently only array_eq and record_eq), mergejoinability
1531 * depends on the specific input data type the operator is invoked for, so
1532 * that must be passed as well. We currently assume that only one input's type
1533 * is needed to check this --- by convention, pass the left input's data type.
1534 */
1535bool
1536op_mergejoinable(Oid opno, Oid inputtype)
1537{
1538 bool result = false;
1539 HeapTuple tp;
1540 TypeCacheEntry *typentry;
1541
1542 /*
1543 * For array_eq or record_eq, we can sort if the element or field types
1544 * are all sortable. We could implement all the checks for that here, but
1545 * the typcache already does that and caches the results too, so let's
1546 * rely on the typcache.
1547 */
1548 if (opno == ARRAY_EQ_OP)
1549 {
1550 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1551 if (typentry->cmp_proc == F_BTARRAYCMP)
1552 result = true;
1553 }
1554 else if (opno == RECORD_EQ_OP)
1555 {
1556 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1557 if (typentry->cmp_proc == F_BTRECORDCMP)
1558 result = true;
1559 }
1560 else
1561 {
1562 /* For all other operators, rely on pg_operator.oprcanmerge */
1564 if (HeapTupleIsValid(tp))
1565 {
1567
1568 result = optup->oprcanmerge;
1569 ReleaseSysCache(tp);
1570 }
1571 }
1572 return result;
1573}
1574
1575/*
1576 * op_hashjoinable
1577 *
1578 * Returns true if the operator is hashjoinable. (There must be a suitable
1579 * hash opfamily entry for this operator if it is so marked.)
1580 *
1581 * In some cases (currently only array_eq), hashjoinability depends on the
1582 * specific input data type the operator is invoked for, so that must be
1583 * passed as well. We currently assume that only one input's type is needed
1584 * to check this --- by convention, pass the left input's data type.
1585 */
1586bool
1587op_hashjoinable(Oid opno, Oid inputtype)
1588{
1589 bool result = false;
1590 HeapTuple tp;
1591 TypeCacheEntry *typentry;
1592
1593 /* As in op_mergejoinable, let the typcache handle the hard cases */
1594 if (opno == ARRAY_EQ_OP)
1595 {
1596 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1597 if (typentry->hash_proc == F_HASH_ARRAY)
1598 result = true;
1599 }
1600 else if (opno == RECORD_EQ_OP)
1601 {
1602 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1603 if (typentry->hash_proc == F_HASH_RECORD)
1604 result = true;
1605 }
1606 else
1607 {
1608 /* For all other operators, rely on pg_operator.oprcanhash */
1610 if (HeapTupleIsValid(tp))
1611 {
1613
1614 result = optup->oprcanhash;
1615 ReleaseSysCache(tp);
1616 }
1617 }
1618 return result;
1619}
1620
1621/*
1622 * op_strict
1623 *
1624 * Get the proisstrict flag for the operator's underlying function.
1625 */
1626bool
1628{
1629 RegProcedure funcid = get_opcode(opno);
1630
1631 if (funcid == (RegProcedure) InvalidOid)
1632 elog(ERROR, "operator %u does not exist", opno);
1633
1634 return func_strict((Oid) funcid);
1635}
1636
1637/*
1638 * op_volatile
1639 *
1640 * Get the provolatile flag for the operator's underlying function.
1641 */
1642char
1644{
1645 RegProcedure funcid = get_opcode(opno);
1646
1647 if (funcid == (RegProcedure) InvalidOid)
1648 elog(ERROR, "operator %u does not exist", opno);
1649
1650 return func_volatile((Oid) funcid);
1651}
1652
1653/*
1654 * get_commutator
1655 *
1656 * Returns the corresponding commutator of an operator.
1657 */
1658Oid
1660{
1661 HeapTuple tp;
1662
1664 if (HeapTupleIsValid(tp))
1665 {
1667 Oid result;
1668
1669 result = optup->oprcom;
1670 ReleaseSysCache(tp);
1671 return result;
1672 }
1673 else
1674 return InvalidOid;
1675}
1676
1677/*
1678 * get_negator
1679 *
1680 * Returns the corresponding negator of an operator.
1681 */
1682Oid
1684{
1685 HeapTuple tp;
1686
1688 if (HeapTupleIsValid(tp))
1689 {
1691 Oid result;
1692
1693 result = optup->oprnegate;
1694 ReleaseSysCache(tp);
1695 return result;
1696 }
1697 else
1698 return InvalidOid;
1699}
1700
1701/*
1702 * get_oprrest
1703 *
1704 * Returns procedure id for computing selectivity of an operator.
1705 */
1708{
1709 HeapTuple tp;
1710
1712 if (HeapTupleIsValid(tp))
1713 {
1715 RegProcedure result;
1716
1717 result = optup->oprrest;
1718 ReleaseSysCache(tp);
1719 return result;
1720 }
1721 else
1722 return (RegProcedure) InvalidOid;
1723}
1724
1725/*
1726 * get_oprjoin
1727 *
1728 * Returns procedure id for computing selectivity of a join.
1729 */
1732{
1733 HeapTuple tp;
1734
1736 if (HeapTupleIsValid(tp))
1737 {
1739 RegProcedure result;
1740
1741 result = optup->oprjoin;
1742 ReleaseSysCache(tp);
1743 return result;
1744 }
1745 else
1746 return (RegProcedure) InvalidOid;
1747}
1748
1749/* ---------- FUNCTION CACHE ---------- */
1750
1751/*
1752 * get_func_name
1753 * returns the name of the function with the given funcid
1754 *
1755 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1756 */
1757char *
1759{
1760 HeapTuple tp;
1761
1763 if (HeapTupleIsValid(tp))
1764 {
1766 char *result;
1767
1768 result = pstrdup(NameStr(functup->proname));
1769 ReleaseSysCache(tp);
1770 return result;
1771 }
1772 else
1773 return NULL;
1774}
1775
1776/*
1777 * get_func_namespace
1778 *
1779 * Returns the pg_namespace OID associated with a given function.
1780 */
1781Oid
1783{
1784 HeapTuple tp;
1785
1787 if (HeapTupleIsValid(tp))
1788 {
1790 Oid result;
1791
1792 result = functup->pronamespace;
1793 ReleaseSysCache(tp);
1794 return result;
1795 }
1796 else
1797 return InvalidOid;
1798}
1799
1800/*
1801 * get_func_rettype
1802 * Given procedure id, return the function's result type.
1803 */
1804Oid
1806{
1807 HeapTuple tp;
1808 Oid result;
1809
1811 if (!HeapTupleIsValid(tp))
1812 elog(ERROR, "cache lookup failed for function %u", funcid);
1813
1814 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1815 ReleaseSysCache(tp);
1816 return result;
1817}
1818
1819/*
1820 * get_func_nargs
1821 * Given procedure id, return the number of arguments.
1822 */
1823int
1825{
1826 HeapTuple tp;
1827 int result;
1828
1830 if (!HeapTupleIsValid(tp))
1831 elog(ERROR, "cache lookup failed for function %u", funcid);
1832
1833 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1834 ReleaseSysCache(tp);
1835 return result;
1836}
1837
1838/*
1839 * get_func_signature
1840 * Given procedure id, return the function's argument and result types.
1841 * (The return value is the result type.)
1842 *
1843 * The arguments are returned as a palloc'd array.
1844 */
1845Oid
1846get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1847{
1848 HeapTuple tp;
1850 Oid result;
1851
1853 if (!HeapTupleIsValid(tp))
1854 elog(ERROR, "cache lookup failed for function %u", funcid);
1855
1857
1858 result = procstruct->prorettype;
1859 *nargs = (int) procstruct->pronargs;
1860 Assert(*nargs == procstruct->proargtypes.dim1);
1861 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1862 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1863
1864 ReleaseSysCache(tp);
1865 return result;
1866}
1867
1868/*
1869 * get_func_variadictype
1870 * Given procedure id, return the function's provariadic field.
1871 */
1872Oid
1874{
1875 HeapTuple tp;
1876 Oid result;
1877
1879 if (!HeapTupleIsValid(tp))
1880 elog(ERROR, "cache lookup failed for function %u", funcid);
1881
1882 result = ((Form_pg_proc) GETSTRUCT(tp))->provariadic;
1883 ReleaseSysCache(tp);
1884 return result;
1885}
1886
1887/*
1888 * get_func_retset
1889 * Given procedure id, return the function's proretset flag.
1890 */
1891bool
1893{
1894 HeapTuple tp;
1895 bool result;
1896
1898 if (!HeapTupleIsValid(tp))
1899 elog(ERROR, "cache lookup failed for function %u", funcid);
1900
1901 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1902 ReleaseSysCache(tp);
1903 return result;
1904}
1905
1906/*
1907 * func_strict
1908 * Given procedure id, return the function's proisstrict flag.
1909 */
1910bool
1912{
1913 HeapTuple tp;
1914 bool result;
1915
1917 if (!HeapTupleIsValid(tp))
1918 elog(ERROR, "cache lookup failed for function %u", funcid);
1919
1920 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1921 ReleaseSysCache(tp);
1922 return result;
1923}
1924
1925/*
1926 * func_volatile
1927 * Given procedure id, return the function's provolatile flag.
1928 */
1929char
1931{
1932 HeapTuple tp;
1933 char result;
1934
1936 if (!HeapTupleIsValid(tp))
1937 elog(ERROR, "cache lookup failed for function %u", funcid);
1938
1939 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1940 ReleaseSysCache(tp);
1941 return result;
1942}
1943
1944/*
1945 * func_parallel
1946 * Given procedure id, return the function's proparallel flag.
1947 */
1948char
1950{
1951 HeapTuple tp;
1952 char result;
1953
1955 if (!HeapTupleIsValid(tp))
1956 elog(ERROR, "cache lookup failed for function %u", funcid);
1957
1958 result = ((Form_pg_proc) GETSTRUCT(tp))->proparallel;
1959 ReleaseSysCache(tp);
1960 return result;
1961}
1962
1963/*
1964 * get_func_prokind
1965 * Given procedure id, return the routine kind.
1966 */
1967char
1969{
1970 HeapTuple tp;
1971 char result;
1972
1974 if (!HeapTupleIsValid(tp))
1975 elog(ERROR, "cache lookup failed for function %u", funcid);
1976
1977 result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
1978 ReleaseSysCache(tp);
1979 return result;
1980}
1981
1982/*
1983 * get_func_leakproof
1984 * Given procedure id, return the function's leakproof field.
1985 */
1986bool
1988{
1989 HeapTuple tp;
1990 bool result;
1991
1993 if (!HeapTupleIsValid(tp))
1994 elog(ERROR, "cache lookup failed for function %u", funcid);
1995
1996 result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
1997 ReleaseSysCache(tp);
1998 return result;
1999}
2000
2001/*
2002 * get_func_support
2003 *
2004 * Returns the support function OID associated with a given function,
2005 * or InvalidOid if there is none.
2006 */
2009{
2010 HeapTuple tp;
2011
2013 if (HeapTupleIsValid(tp))
2014 {
2016 RegProcedure result;
2017
2018 result = functup->prosupport;
2019 ReleaseSysCache(tp);
2020 return result;
2021 }
2022 else
2023 return (RegProcedure) InvalidOid;
2024}
2025
2026/* ---------- RELATION CACHE ---------- */
2027
2028/*
2029 * get_relname_relid
2030 * Given name and namespace of a relation, look up the OID.
2031 *
2032 * Returns InvalidOid if there is no such relation.
2033 */
2034Oid
2035get_relname_relid(const char *relname, Oid relnamespace)
2036{
2039 ObjectIdGetDatum(relnamespace));
2040}
2041
2042#ifdef NOT_USED
2043/*
2044 * get_relnatts
2045 *
2046 * Returns the number of attributes for a given relation.
2047 */
2048int
2049get_relnatts(Oid relid)
2050{
2051 HeapTuple tp;
2052
2054 if (HeapTupleIsValid(tp))
2055 {
2057 int result;
2058
2059 result = reltup->relnatts;
2060 ReleaseSysCache(tp);
2061 return result;
2062 }
2063 else
2064 return InvalidAttrNumber;
2065}
2066#endif
2067
2068/*
2069 * get_rel_name
2070 * Returns the name of a given relation.
2071 *
2072 * Returns a palloc'd copy of the string, or NULL if no such relation.
2073 *
2074 * NOTE: since relation name is not unique, be wary of code that uses this
2075 * for anything except preparing error messages.
2076 */
2077char *
2079{
2080 HeapTuple tp;
2081
2083 if (HeapTupleIsValid(tp))
2084 {
2086 char *result;
2087
2088 result = pstrdup(NameStr(reltup->relname));
2089 ReleaseSysCache(tp);
2090 return result;
2091 }
2092 else
2093 return NULL;
2094}
2095
2096/*
2097 * get_rel_namespace
2098 *
2099 * Returns the pg_namespace OID associated with a given relation.
2100 */
2101Oid
2103{
2104 HeapTuple tp;
2105
2107 if (HeapTupleIsValid(tp))
2108 {
2110 Oid result;
2111
2112 result = reltup->relnamespace;
2113 ReleaseSysCache(tp);
2114 return result;
2115 }
2116 else
2117 return InvalidOid;
2118}
2119
2120/*
2121 * get_rel_type_id
2122 *
2123 * Returns the pg_type OID associated with a given relation.
2124 *
2125 * Note: not all pg_class entries have associated pg_type OIDs; so be
2126 * careful to check for InvalidOid result.
2127 */
2128Oid
2130{
2131 HeapTuple tp;
2132
2134 if (HeapTupleIsValid(tp))
2135 {
2137 Oid result;
2138
2139 result = reltup->reltype;
2140 ReleaseSysCache(tp);
2141 return result;
2142 }
2143 else
2144 return InvalidOid;
2145}
2146
2147/*
2148 * get_rel_relkind
2149 *
2150 * Returns the relkind associated with a given relation.
2151 */
2152char
2154{
2155 HeapTuple tp;
2156
2158 if (HeapTupleIsValid(tp))
2159 {
2161 char result;
2162
2163 result = reltup->relkind;
2164 ReleaseSysCache(tp);
2165 return result;
2166 }
2167 else
2168 return '\0';
2169}
2170
2171/*
2172 * get_rel_relispartition
2173 *
2174 * Returns the relispartition flag associated with a given relation.
2175 */
2176bool
2178{
2179 HeapTuple tp;
2180
2182 if (HeapTupleIsValid(tp))
2183 {
2185 bool result;
2186
2187 result = reltup->relispartition;
2188 ReleaseSysCache(tp);
2189 return result;
2190 }
2191 else
2192 return false;
2193}
2194
2195/*
2196 * get_rel_tablespace
2197 *
2198 * Returns the pg_tablespace OID associated with a given relation.
2199 *
2200 * Note: InvalidOid might mean either that we couldn't find the relation,
2201 * or that it is in the database's default tablespace.
2202 */
2203Oid
2205{
2206 HeapTuple tp;
2207
2209 if (HeapTupleIsValid(tp))
2210 {
2212 Oid result;
2213
2214 result = reltup->reltablespace;
2215 ReleaseSysCache(tp);
2216 return result;
2217 }
2218 else
2219 return InvalidOid;
2220}
2221
2222/*
2223 * get_rel_persistence
2224 *
2225 * Returns the relpersistence associated with a given relation.
2226 */
2227char
2229{
2230 HeapTuple tp;
2232 char result;
2233
2235 if (!HeapTupleIsValid(tp))
2236 elog(ERROR, "cache lookup failed for relation %u", relid);
2238 result = reltup->relpersistence;
2239 ReleaseSysCache(tp);
2240
2241 return result;
2242}
2243
2244/*
2245 * get_rel_relam
2246 *
2247 * Returns the relam associated with a given relation.
2248 */
2249Oid
2251{
2252 HeapTuple tp;
2254 Oid result;
2255
2257 if (!HeapTupleIsValid(tp))
2258 elog(ERROR, "cache lookup failed for relation %u", relid);
2260 result = reltup->relam;
2261 ReleaseSysCache(tp);
2262
2263 return result;
2264}
2265
2266
2267/* ---------- TRANSFORM CACHE ---------- */
2268
2269Oid
2270get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2271{
2272 HeapTuple tup;
2273
2274 if (!list_member_oid(trftypes, typid))
2275 return InvalidOid;
2276
2278 ObjectIdGetDatum(langid));
2279 if (HeapTupleIsValid(tup))
2280 {
2281 Oid funcid;
2282
2283 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2285 return funcid;
2286 }
2287 else
2288 return InvalidOid;
2289}
2290
2291Oid
2292get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2293{
2294 HeapTuple tup;
2295
2296 if (!list_member_oid(trftypes, typid))
2297 return InvalidOid;
2298
2300 ObjectIdGetDatum(langid));
2301 if (HeapTupleIsValid(tup))
2302 {
2303 Oid funcid;
2304
2305 funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2307 return funcid;
2308 }
2309 else
2310 return InvalidOid;
2311}
2312
2313
2314/* ---------- TYPE CACHE ---------- */
2315
2316/*
2317 * get_typisdefined
2318 *
2319 * Given the type OID, determine whether the type is defined
2320 * (if not, it's only a shell).
2321 */
2322bool
2324{
2325 HeapTuple tp;
2326
2328 if (HeapTupleIsValid(tp))
2329 {
2331 bool result;
2332
2333 result = typtup->typisdefined;
2334 ReleaseSysCache(tp);
2335 return result;
2336 }
2337 else
2338 return false;
2339}
2340
2341/*
2342 * get_typlen
2343 *
2344 * Given the type OID, return the length of the type.
2345 */
2346int16
2348{
2349 HeapTuple tp;
2350
2352 if (HeapTupleIsValid(tp))
2353 {
2355 int16 result;
2356
2357 result = typtup->typlen;
2358 ReleaseSysCache(tp);
2359 return result;
2360 }
2361 else
2362 return 0;
2363}
2364
2365/*
2366 * get_typbyval
2367 *
2368 * Given the type OID, determine whether the type is returned by value or
2369 * not. Returns true if by value, false if by reference.
2370 */
2371bool
2373{
2374 HeapTuple tp;
2375
2377 if (HeapTupleIsValid(tp))
2378 {
2380 bool result;
2381
2382 result = typtup->typbyval;
2383 ReleaseSysCache(tp);
2384 return result;
2385 }
2386 else
2387 return false;
2388}
2389
2390/*
2391 * get_typlenbyval
2392 *
2393 * A two-fer: given the type OID, return both typlen and typbyval.
2394 *
2395 * Since both pieces of info are needed to know how to copy a Datum,
2396 * many places need both. Might as well get them with one cache lookup
2397 * instead of two. Also, this routine raises an error instead of
2398 * returning a bogus value when given a bad type OID.
2399 */
2400void
2401get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2402{
2403 HeapTuple tp;
2405
2407 if (!HeapTupleIsValid(tp))
2408 elog(ERROR, "cache lookup failed for type %u", typid);
2410 *typlen = typtup->typlen;
2411 *typbyval = typtup->typbyval;
2412 ReleaseSysCache(tp);
2413}
2414
2415/*
2416 * get_typlenbyvalalign
2417 *
2418 * A three-fer: given the type OID, return typlen, typbyval, typalign.
2419 */
2420void
2421get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2422 char *typalign)
2423{
2424 HeapTuple tp;
2426
2428 if (!HeapTupleIsValid(tp))
2429 elog(ERROR, "cache lookup failed for type %u", typid);
2431 *typlen = typtup->typlen;
2432 *typbyval = typtup->typbyval;
2433 *typalign = typtup->typalign;
2434 ReleaseSysCache(tp);
2435}
2436
2437/*
2438 * getTypeIOParam
2439 * Given a pg_type row, select the type OID to pass to I/O functions
2440 *
2441 * Formerly, all I/O functions were passed pg_type.typelem as their second
2442 * parameter, but we now have a more complex rule about what to pass.
2443 * This knowledge is intended to be centralized here --- direct references
2444 * to typelem elsewhere in the code are wrong, if they are associated with
2445 * I/O calls and not with actual subscripting operations! (But see
2446 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2447 *
2448 * As of PostgreSQL 8.1, output functions receive only the value itself
2449 * and not any auxiliary parameters, so the name of this routine is now
2450 * a bit of a misnomer ... it should be getTypeInputParam.
2451 */
2452Oid
2454{
2456
2457 /*
2458 * Array types get their typelem as parameter; everybody else gets their
2459 * own type OID as parameter.
2460 */
2461 if (OidIsValid(typeStruct->typelem))
2462 return typeStruct->typelem;
2463 else
2464 return typeStruct->oid;
2465}
2466
2467/*
2468 * get_type_io_data
2469 *
2470 * A six-fer: given the type OID, return typlen, typbyval, typalign,
2471 * typdelim, typioparam, and IO function OID. The IO function
2472 * returned is controlled by IOFuncSelector
2473 */
2474void
2477 int16 *typlen,
2478 bool *typbyval,
2479 char *typalign,
2480 char *typdelim,
2481 Oid *typioparam,
2482 Oid *func)
2483{
2486
2487 /*
2488 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2489 * use array_in and array_out during bootstrap.
2490 */
2492 {
2493 Oid typinput;
2494 Oid typoutput;
2495 Oid typcollation;
2496
2498 typlen,
2499 typbyval,
2500 typalign,
2501 typdelim,
2502 typioparam,
2503 &typinput,
2504 &typoutput,
2505 &typcollation);
2506 switch (which_func)
2507 {
2508 case IOFunc_input:
2509 *func = typinput;
2510 break;
2511 case IOFunc_output:
2512 *func = typoutput;
2513 break;
2514 default:
2515 elog(ERROR, "binary I/O not supported during bootstrap");
2516 break;
2517 }
2518 return;
2519 }
2520
2523 elog(ERROR, "cache lookup failed for type %u", typid);
2525
2526 *typlen = typeStruct->typlen;
2527 *typbyval = typeStruct->typbyval;
2528 *typalign = typeStruct->typalign;
2529 *typdelim = typeStruct->typdelim;
2530 *typioparam = getTypeIOParam(typeTuple);
2531 switch (which_func)
2532 {
2533 case IOFunc_input:
2534 *func = typeStruct->typinput;
2535 break;
2536 case IOFunc_output:
2537 *func = typeStruct->typoutput;
2538 break;
2539 case IOFunc_receive:
2540 *func = typeStruct->typreceive;
2541 break;
2542 case IOFunc_send:
2543 *func = typeStruct->typsend;
2544 break;
2545 }
2547}
2548
2549#ifdef NOT_USED
2550char
2551get_typalign(Oid typid)
2552{
2553 HeapTuple tp;
2554
2556 if (HeapTupleIsValid(tp))
2557 {
2559 char result;
2560
2561 result = typtup->typalign;
2562 ReleaseSysCache(tp);
2563 return result;
2564 }
2565 else
2566 return TYPALIGN_INT;
2567}
2568#endif
2569
2570char
2572{
2573 HeapTuple tp;
2574
2576 if (HeapTupleIsValid(tp))
2577 {
2579 char result;
2580
2581 result = typtup->typstorage;
2582 ReleaseSysCache(tp);
2583 return result;
2584 }
2585 else
2586 return TYPSTORAGE_PLAIN;
2587}
2588
2589/*
2590 * get_typdefault
2591 * Given a type OID, return the type's default value, if any.
2592 *
2593 * The result is a palloc'd expression node tree, or NULL if there
2594 * is no defined default for the datatype.
2595 *
2596 * NB: caller should be prepared to coerce result to correct datatype;
2597 * the returned expression tree might produce something of the wrong type.
2598 */
2599Node *
2601{
2604 Datum datum;
2605 bool isNull;
2606 Node *expr;
2607
2610 elog(ERROR, "cache lookup failed for type %u", typid);
2612
2613 /*
2614 * typdefault and typdefaultbin are potentially null, so don't try to
2615 * access 'em as struct fields. Must do it the hard way with
2616 * SysCacheGetAttr.
2617 */
2618 datum = SysCacheGetAttr(TYPEOID,
2619 typeTuple,
2621 &isNull);
2622
2623 if (!isNull)
2624 {
2625 /* We have an expression default */
2626 expr = stringToNode(TextDatumGetCString(datum));
2627 }
2628 else
2629 {
2630 /* Perhaps we have a plain literal default */
2631 datum = SysCacheGetAttr(TYPEOID,
2632 typeTuple,
2634 &isNull);
2635
2636 if (!isNull)
2637 {
2638 char *strDefaultVal;
2639
2640 /* Convert text datum to C string */
2642 /* Convert C string to a value of the given type */
2643 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2645 /* Build a Const node containing the value */
2646 expr = (Node *) makeConst(typid,
2647 -1,
2648 type->typcollation,
2649 type->typlen,
2650 datum,
2651 false,
2652 type->typbyval);
2654 }
2655 else
2656 {
2657 /* No default */
2658 expr = NULL;
2659 }
2660 }
2661
2663
2664 return expr;
2665}
2666
2667/*
2668 * getBaseType
2669 * If the given type is a domain, return its base type;
2670 * otherwise return the type's own OID.
2671 */
2672Oid
2674{
2675 int32 typmod = -1;
2676
2677 return getBaseTypeAndTypmod(typid, &typmod);
2678}
2679
2680/*
2681 * getBaseTypeAndTypmod
2682 * If the given type is a domain, return its base type and typmod;
2683 * otherwise return the type's own OID, and leave *typmod unchanged.
2684 *
2685 * Note that the "applied typmod" should be -1 for every domain level
2686 * above the bottommost; therefore, if the passed-in typid is indeed
2687 * a domain, *typmod should be -1.
2688 */
2689Oid
2691{
2692 /*
2693 * We loop to find the bottom base type in a stack of domains.
2694 */
2695 for (;;)
2696 {
2697 HeapTuple tup;
2699
2701 if (!HeapTupleIsValid(tup))
2702 elog(ERROR, "cache lookup failed for type %u", typid);
2704 if (typTup->typtype != TYPTYPE_DOMAIN)
2705 {
2706 /* Not a domain, so done */
2708 break;
2709 }
2710
2711 Assert(*typmod == -1);
2712 typid = typTup->typbasetype;
2713 *typmod = typTup->typtypmod;
2714
2716 }
2717
2718 return typid;
2719}
2720
2721/*
2722 * get_typavgwidth
2723 *
2724 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2725 * estimate the average width of values of the type. This is used by
2726 * the planner, which doesn't require absolutely correct results;
2727 * it's OK (and expected) to guess if we don't know for sure.
2728 */
2729int32
2731{
2732 int typlen = get_typlen(typid);
2734
2735 /*
2736 * Easy if it's a fixed-width type
2737 */
2738 if (typlen > 0)
2739 return typlen;
2740
2741 /*
2742 * type_maximum_size knows the encoding of typmod for some datatypes;
2743 * don't duplicate that knowledge here.
2744 */
2745 maxwidth = type_maximum_size(typid, typmod);
2746 if (maxwidth > 0)
2747 {
2748 /*
2749 * For BPCHAR, the max width is also the only width. Otherwise we
2750 * need to guess about the typical data width given the max. A sliding
2751 * scale for percentage of max width seems reasonable.
2752 */
2753 if (typid == BPCHAROID)
2754 return maxwidth;
2755 if (maxwidth <= 32)
2756 return maxwidth; /* assume full width */
2757 if (maxwidth < 1000)
2758 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2759
2760 /*
2761 * Beyond 1000, assume we're looking at something like
2762 * "varchar(10000)" where the limit isn't actually reached often, and
2763 * use a fixed estimate.
2764 */
2765 return 32 + (1000 - 32) / 2;
2766 }
2767
2768 /*
2769 * Oops, we have no idea ... wild guess time.
2770 */
2771 return 32;
2772}
2773
2774/*
2775 * get_typtype
2776 *
2777 * Given the type OID, find if it is a basic type, a complex type, etc.
2778 * It returns the null char if the cache lookup fails...
2779 */
2780char
2782{
2783 HeapTuple tp;
2784
2786 if (HeapTupleIsValid(tp))
2787 {
2789 char result;
2790
2791 result = typtup->typtype;
2792 ReleaseSysCache(tp);
2793 return result;
2794 }
2795 else
2796 return '\0';
2797}
2798
2799/*
2800 * type_is_rowtype
2801 *
2802 * Convenience function to determine whether a type OID represents
2803 * a "rowtype" type --- either RECORD or a named composite type
2804 * (including a domain over a named composite type).
2805 */
2806bool
2808{
2809 if (typid == RECORDOID)
2810 return true; /* easy case */
2811 switch (get_typtype(typid))
2812 {
2813 case TYPTYPE_COMPOSITE:
2814 return true;
2815 case TYPTYPE_DOMAIN:
2817 return true;
2818 break;
2819 default:
2820 break;
2821 }
2822 return false;
2823}
2824
2825/*
2826 * type_is_enum
2827 * Returns true if the given type is an enum type.
2828 */
2829bool
2831{
2832 return (get_typtype(typid) == TYPTYPE_ENUM);
2833}
2834
2835/*
2836 * type_is_range
2837 * Returns true if the given type is a range type.
2838 */
2839bool
2841{
2842 return (get_typtype(typid) == TYPTYPE_RANGE);
2843}
2844
2845/*
2846 * type_is_multirange
2847 * Returns true if the given type is a multirange type.
2848 */
2849bool
2851{
2852 return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
2853}
2854
2855/*
2856 * get_type_category_preferred
2857 *
2858 * Given the type OID, fetch its category and preferred-type status.
2859 * Throws error on failure.
2860 */
2861void
2863{
2864 HeapTuple tp;
2866
2868 if (!HeapTupleIsValid(tp))
2869 elog(ERROR, "cache lookup failed for type %u", typid);
2871 *typcategory = typtup->typcategory;
2872 *typispreferred = typtup->typispreferred;
2873 ReleaseSysCache(tp);
2874}
2875
2876/*
2877 * get_typ_typrelid
2878 *
2879 * Given the type OID, get the typrelid (InvalidOid if not a complex
2880 * type).
2881 */
2882Oid
2884{
2885 HeapTuple tp;
2886
2888 if (HeapTupleIsValid(tp))
2889 {
2891 Oid result;
2892
2893 result = typtup->typrelid;
2894 ReleaseSysCache(tp);
2895 return result;
2896 }
2897 else
2898 return InvalidOid;
2899}
2900
2901/*
2902 * get_element_type
2903 *
2904 * Given the type OID, get the typelem (InvalidOid if not an array type).
2905 *
2906 * NB: this only succeeds for "true" arrays having array_subscript_handler
2907 * as typsubscript. For other types, InvalidOid is returned independently
2908 * of whether they have typelem or typsubscript set.
2909 */
2910Oid
2912{
2913 HeapTuple tp;
2914
2916 if (HeapTupleIsValid(tp))
2917 {
2919 Oid result;
2920
2922 result = typtup->typelem;
2923 else
2924 result = InvalidOid;
2925 ReleaseSysCache(tp);
2926 return result;
2927 }
2928 else
2929 return InvalidOid;
2930}
2931
2932/*
2933 * get_array_type
2934 *
2935 * Given the type OID, get the corresponding "true" array type.
2936 * Returns InvalidOid if no array type can be found.
2937 */
2938Oid
2940{
2941 HeapTuple tp;
2942 Oid result = InvalidOid;
2943
2945 if (HeapTupleIsValid(tp))
2946 {
2947 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2948 ReleaseSysCache(tp);
2949 }
2950 return result;
2951}
2952
2953/*
2954 * get_promoted_array_type
2955 *
2956 * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
2957 * construct, that is, either the corresponding "true" array type
2958 * if the input is a scalar type that has such an array type,
2959 * or the same type if the input is already a "true" array type.
2960 * Returns InvalidOid if neither rule is satisfied.
2961 */
2962Oid
2964{
2965 Oid array_type = get_array_type(typid);
2966
2967 if (OidIsValid(array_type))
2968 return array_type;
2969 if (OidIsValid(get_element_type(typid)))
2970 return typid;
2971 return InvalidOid;
2972}
2973
2974/*
2975 * get_base_element_type
2976 * Given the type OID, get the typelem, looking "through" any domain
2977 * to its underlying array type.
2978 *
2979 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2980 * an extra cache lookup. Note that it fails to provide any information
2981 * about the typmod of the array.
2982 */
2983Oid
2985{
2986 /*
2987 * We loop to find the bottom base type in a stack of domains.
2988 */
2989 for (;;)
2990 {
2991 HeapTuple tup;
2993
2995 if (!HeapTupleIsValid(tup))
2996 break;
2998 if (typTup->typtype != TYPTYPE_DOMAIN)
2999 {
3000 /* Not a domain, so stop descending */
3001 Oid result;
3002
3003 /* This test must match get_element_type */
3005 result = typTup->typelem;
3006 else
3007 result = InvalidOid;
3009 return result;
3010 }
3011
3012 typid = typTup->typbasetype;
3014 }
3015
3016 /* Like get_element_type, silently return InvalidOid for bogus input */
3017 return InvalidOid;
3018}
3019
3020/*
3021 * getTypeInputInfo
3022 *
3023 * Get info needed for converting values of a type to internal form
3024 */
3025void
3027{
3030
3033 elog(ERROR, "cache lookup failed for type %u", type);
3035
3036 if (!pt->typisdefined)
3037 ereport(ERROR,
3039 errmsg("type %s is only a shell",
3040 format_type_be(type))));
3041 if (!OidIsValid(pt->typinput))
3042 ereport(ERROR,
3044 errmsg("no input function available for type %s",
3045 format_type_be(type))));
3046
3047 *typInput = pt->typinput;
3049
3051}
3052
3053/*
3054 * getTypeOutputInfo
3055 *
3056 * Get info needed for printing values of a type
3057 */
3058void
3060{
3063
3066 elog(ERROR, "cache lookup failed for type %u", type);
3068
3069 if (!pt->typisdefined)
3070 ereport(ERROR,
3072 errmsg("type %s is only a shell",
3073 format_type_be(type))));
3074 if (!OidIsValid(pt->typoutput))
3075 ereport(ERROR,
3077 errmsg("no output function available for type %s",
3078 format_type_be(type))));
3079
3080 *typOutput = pt->typoutput;
3081 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3082
3084}
3085
3086/*
3087 * getTypeBinaryInputInfo
3088 *
3089 * Get info needed for binary input of values of a type
3090 */
3091void
3093{
3096
3099 elog(ERROR, "cache lookup failed for type %u", type);
3101
3102 if (!pt->typisdefined)
3103 ereport(ERROR,
3105 errmsg("type %s is only a shell",
3106 format_type_be(type))));
3107 if (!OidIsValid(pt->typreceive))
3108 ereport(ERROR,
3110 errmsg("no binary input function available for type %s",
3111 format_type_be(type))));
3112
3113 *typReceive = pt->typreceive;
3115
3117}
3118
3119/*
3120 * getTypeBinaryOutputInfo
3121 *
3122 * Get info needed for binary output of values of a type
3123 */
3124void
3126{
3129
3132 elog(ERROR, "cache lookup failed for type %u", type);
3134
3135 if (!pt->typisdefined)
3136 ereport(ERROR,
3138 errmsg("type %s is only a shell",
3139 format_type_be(type))));
3140 if (!OidIsValid(pt->typsend))
3141 ereport(ERROR,
3143 errmsg("no binary output function available for type %s",
3144 format_type_be(type))));
3145
3146 *typSend = pt->typsend;
3147 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
3148
3150}
3151
3152/*
3153 * get_typmodin
3154 *
3155 * Given the type OID, return the type's typmodin procedure, if any.
3156 */
3157Oid
3159{
3160 HeapTuple tp;
3161
3163 if (HeapTupleIsValid(tp))
3164 {
3166 Oid result;
3167
3168 result = typtup->typmodin;
3169 ReleaseSysCache(tp);
3170 return result;
3171 }
3172 else
3173 return InvalidOid;
3174}
3175
3176#ifdef NOT_USED
3177/*
3178 * get_typmodout
3179 *
3180 * Given the type OID, return the type's typmodout procedure, if any.
3181 */
3182Oid
3183get_typmodout(Oid typid)
3184{
3185 HeapTuple tp;
3186
3188 if (HeapTupleIsValid(tp))
3189 {
3191 Oid result;
3192
3193 result = typtup->typmodout;
3194 ReleaseSysCache(tp);
3195 return result;
3196 }
3197 else
3198 return InvalidOid;
3199}
3200#endif /* NOT_USED */
3201
3202/*
3203 * get_typcollation
3204 *
3205 * Given the type OID, return the type's typcollation attribute.
3206 */
3207Oid
3209{
3210 HeapTuple tp;
3211
3213 if (HeapTupleIsValid(tp))
3214 {
3216 Oid result;
3217
3218 result = typtup->typcollation;
3219 ReleaseSysCache(tp);
3220 return result;
3221 }
3222 else
3223 return InvalidOid;
3224}
3225
3226
3227/*
3228 * type_is_collatable
3229 *
3230 * Return whether the type cares about collations
3231 */
3232bool
3234{
3235 return OidIsValid(get_typcollation(typid));
3236}
3237
3238
3239/*
3240 * get_typsubscript
3241 *
3242 * Given the type OID, return the type's subscripting handler's OID,
3243 * if it has one.
3244 *
3245 * If typelemp isn't NULL, we also store the type's typelem value there.
3246 * This saves some callers an extra catalog lookup.
3247 */
3250{
3251 HeapTuple tp;
3252
3254 if (HeapTupleIsValid(tp))
3255 {
3257 RegProcedure handler = typform->typsubscript;
3258
3259 if (typelemp)
3260 *typelemp = typform->typelem;
3261 ReleaseSysCache(tp);
3262 return handler;
3263 }
3264 else
3265 {
3266 if (typelemp)
3268 return InvalidOid;
3269 }
3270}
3271
3272/*
3273 * getSubscriptingRoutines
3274 *
3275 * Given the type OID, fetch the type's subscripting methods struct.
3276 * Return NULL if type is not subscriptable.
3277 *
3278 * If typelemp isn't NULL, we also store the type's typelem value there.
3279 * This saves some callers an extra catalog lookup.
3280 */
3281const struct SubscriptRoutines *
3283{
3284 RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3285
3286 if (!OidIsValid(typsubscript))
3287 return NULL;
3288
3289 return (const struct SubscriptRoutines *)
3290 DatumGetPointer(OidFunctionCall0(typsubscript));
3291}
3292
3293
3294/* ---------- STATISTICS CACHE ---------- */
3295
3296/*
3297 * get_attavgwidth
3298 *
3299 * Given the table and attribute number of a column, get the average
3300 * width of entries in the column. Return zero if no data available.
3301 *
3302 * Currently this is only consulted for individual tables, not for inheritance
3303 * trees, so we don't need an "inh" parameter.
3304 *
3305 * Calling a hook at this point looks somewhat strange, but is required
3306 * because the optimizer calls this function without any other way for
3307 * plug-ins to control the result.
3308 */
3309int32
3311{
3312 HeapTuple tp;
3313 int32 stawidth;
3314
3316 {
3317 stawidth = (*get_attavgwidth_hook) (relid, attnum);
3318 if (stawidth > 0)
3319 return stawidth;
3320 }
3322 ObjectIdGetDatum(relid),
3324 BoolGetDatum(false));
3325 if (HeapTupleIsValid(tp))
3326 {
3327 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3328 ReleaseSysCache(tp);
3329 if (stawidth > 0)
3330 return stawidth;
3331 }
3332 return 0;
3333}
3334
3335/*
3336 * get_attstatsslot
3337 *
3338 * Extract the contents of a "slot" of a pg_statistic tuple.
3339 * Returns true if requested slot type was found, else false.
3340 *
3341 * Unlike other routines in this file, this takes a pointer to an
3342 * already-looked-up tuple in the pg_statistic cache. We do this since
3343 * most callers will want to extract more than one value from the cache
3344 * entry, and we don't want to repeat the cache lookup unnecessarily.
3345 * Also, this API allows this routine to be used with statistics tuples
3346 * that have been provided by a stats hook and didn't really come from
3347 * pg_statistic.
3348 *
3349 * sslot: pointer to output area (typically, a local variable in the caller).
3350 * statstuple: pg_statistic tuple to be examined.
3351 * reqkind: STAKIND code for desired statistics slot kind.
3352 * reqop: STAOP value wanted, or InvalidOid if don't care.
3353 * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3354 *
3355 * If a matching slot is found, true is returned, and *sslot is filled thus:
3356 * staop: receives the actual STAOP value.
3357 * stacoll: receives the actual STACOLL value.
3358 * valuetype: receives actual datatype of the elements of stavalues.
3359 * values: receives pointer to an array of the slot's stavalues.
3360 * nvalues: receives number of stavalues.
3361 * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3362 * nnumbers: receives number of stanumbers.
3363 *
3364 * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3365 * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3366 * ATTSTATSSLOT_NUMBERS wasn't specified.
3367 *
3368 * If no matching slot is found, false is returned, and *sslot is zeroed.
3369 *
3370 * Note that the current API doesn't allow for searching for a slot with
3371 * a particular collation. If we ever actually support recording more than
3372 * one collation, we'll have to extend the API, but for now simple is good.
3373 *
3374 * The data referred to by the fields of sslot is locally palloc'd and
3375 * is independent of the original pg_statistic tuple. When the caller
3376 * is done with it, call free_attstatsslot to release the palloc'd data.
3377 *
3378 * If it's desirable to call free_attstatsslot when get_attstatsslot might
3379 * not have been called, memset'ing sslot to zeroes will allow that.
3380 *
3381 * Passing flags=0 can be useful to quickly check if the requested slot type
3382 * exists. In this case no arrays are extracted, so free_attstatsslot need
3383 * not be called.
3384 */
3385bool
3387 int reqkind, Oid reqop, int flags)
3388{
3390 int i;
3391 Datum val;
3394 int narrayelem;
3397
3398 /* initialize *sslot properly */
3399 memset(sslot, 0, sizeof(AttStatsSlot));
3400
3401 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3402 {
3403 if ((&stats->stakind1)[i] == reqkind &&
3404 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3405 break;
3406 }
3407 if (i >= STATISTIC_NUM_SLOTS)
3408 return false; /* not there */
3409
3410 sslot->staop = (&stats->staop1)[i];
3411 sslot->stacoll = (&stats->stacoll1)[i];
3412
3413 if (flags & ATTSTATSSLOT_VALUES)
3414 {
3417
3418 /*
3419 * Detoast the array if needed, and in any case make a copy that's
3420 * under control of this AttStatsSlot.
3421 */
3423
3424 /*
3425 * Extract the actual array element type, and pass it back in case the
3426 * caller needs it.
3427 */
3428 sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3429
3430 /* Need info about element type */
3433 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3435
3436 /* Deconstruct array into Datum elements; NULLs not expected */
3439 typeForm->typlen,
3440 typeForm->typbyval,
3441 typeForm->typalign,
3442 &sslot->values, NULL, &sslot->nvalues);
3443
3444 /*
3445 * If the element type is pass-by-reference, we now have a bunch of
3446 * Datums that are pointers into the statarray, so we need to keep
3447 * that until free_attstatsslot. Otherwise, all the useful info is in
3448 * sslot->values[], so we can free the array object immediately.
3449 */
3450 if (!typeForm->typbyval)
3451 sslot->values_arr = statarray;
3452 else
3454
3456 }
3457
3458 if (flags & ATTSTATSSLOT_NUMBERS)
3459 {
3462
3463 /*
3464 * Detoast the array if needed, and in any case make a copy that's
3465 * under control of this AttStatsSlot.
3466 */
3468
3469 /*
3470 * We expect the array to be a 1-D float4 array; verify that. We don't
3471 * need to use deconstruct_array() since the array data is just going
3472 * to look like a C array of float4 values.
3473 */
3475 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3478 elog(ERROR, "stanumbers is not a 1-D float4 array");
3479
3480 /* Give caller a pointer directly into the statarray */
3481 sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3482 sslot->nnumbers = narrayelem;
3483
3484 /* We'll free the statarray in free_attstatsslot */
3485 sslot->numbers_arr = statarray;
3486 }
3487
3488 return true;
3489}
3490
3491/*
3492 * free_attstatsslot
3493 * Free data allocated by get_attstatsslot
3494 */
3495void
3497{
3498 /* The values[] array was separately palloc'd by deconstruct_array */
3499 if (sslot->values)
3500 pfree(sslot->values);
3501 /* The numbers[] array points into numbers_arr, do not pfree it */
3502 /* Free the detoasted array objects, if any */
3503 if (sslot->values_arr)
3504 pfree(sslot->values_arr);
3505 if (sslot->numbers_arr)
3506 pfree(sslot->numbers_arr);
3507}
3508
3509/* ---------- PG_NAMESPACE CACHE ---------- */
3510
3511/*
3512 * get_namespace_name
3513 * Returns the name of a given namespace
3514 *
3515 * Returns a palloc'd copy of the string, or NULL if no such namespace.
3516 */
3517char *
3519{
3520 HeapTuple tp;
3521
3523 if (HeapTupleIsValid(tp))
3524 {
3526 char *result;
3527
3528 result = pstrdup(NameStr(nsptup->nspname));
3529 ReleaseSysCache(tp);
3530 return result;
3531 }
3532 else
3533 return NULL;
3534}
3535
3536/*
3537 * get_namespace_name_or_temp
3538 * As above, but if it is this backend's temporary namespace, return
3539 * "pg_temp" instead.
3540 */
3541char *
3543{
3545 return pstrdup("pg_temp");
3546 else
3547 return get_namespace_name(nspid);
3548}
3549
3550/* ---------- PG_RANGE CACHES ---------- */
3551
3552/*
3553 * get_range_subtype
3554 * Returns the subtype of a given range type
3555 *
3556 * Returns InvalidOid if the type is not a range type.
3557 */
3558Oid
3560{
3561 HeapTuple tp;
3562
3564 if (HeapTupleIsValid(tp))
3565 {
3567 Oid result;
3568
3569 result = rngtup->rngsubtype;
3570 ReleaseSysCache(tp);
3571 return result;
3572 }
3573 else
3574 return InvalidOid;
3575}
3576
3577/*
3578 * get_range_collation
3579 * Returns the collation of a given range type
3580 *
3581 * Returns InvalidOid if the type is not a range type,
3582 * or if its subtype is not collatable.
3583 */
3584Oid
3586{
3587 HeapTuple tp;
3588
3590 if (HeapTupleIsValid(tp))
3591 {
3593 Oid result;
3594
3595 result = rngtup->rngcollation;
3596 ReleaseSysCache(tp);
3597 return result;
3598 }
3599 else
3600 return InvalidOid;
3601}
3602
3603/*
3604 * get_range_multirange
3605 * Returns the multirange type of a given range type
3606 *
3607 * Returns InvalidOid if the type is not a range type.
3608 */
3609Oid
3611{
3612 HeapTuple tp;
3613
3615 if (HeapTupleIsValid(tp))
3616 {
3618 Oid result;
3619
3620 result = rngtup->rngmultitypid;
3621 ReleaseSysCache(tp);
3622 return result;
3623 }
3624 else
3625 return InvalidOid;
3626}
3627
3628/*
3629 * get_multirange_range
3630 * Returns the range type of a given multirange
3631 *
3632 * Returns InvalidOid if the type is not a multirange.
3633 */
3634Oid
3636{
3637 HeapTuple tp;
3638
3640 if (HeapTupleIsValid(tp))
3641 {
3643 Oid result;
3644
3645 result = rngtup->rngtypid;
3646 ReleaseSysCache(tp);
3647 return result;
3648 }
3649 else
3650 return InvalidOid;
3651}
3652
3653/* ---------- PG_INDEX CACHE ---------- */
3654
3655/*
3656 * get_index_column_opclass
3657 *
3658 * Given the index OID and column number,
3659 * return opclass of the index column
3660 * or InvalidOid if the index was not found
3661 * or column is non-key one.
3662 */
3663Oid
3665{
3666 HeapTuple tuple;
3667 Form_pg_index rd_index;
3668 Datum datum;
3670 Oid opclass;
3671
3672 /* First we need to know the column's opclass. */
3673
3675 if (!HeapTupleIsValid(tuple))
3676 return InvalidOid;
3677
3678 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3679
3680 /* caller is supposed to guarantee this */
3681 Assert(attno > 0 && attno <= rd_index->indnatts);
3682
3683 /* Non-key attributes don't have an opclass */
3684 if (attno > rd_index->indnkeyatts)
3685 {
3686 ReleaseSysCache(tuple);
3687 return InvalidOid;
3688 }
3689
3691 indclass = ((oidvector *) DatumGetPointer(datum));
3692
3694 opclass = indclass->values[attno - 1];
3695
3696 ReleaseSysCache(tuple);
3697
3698 return opclass;
3699}
3700
3701/*
3702 * get_index_isreplident
3703 *
3704 * Given the index OID, return pg_index.indisreplident.
3705 */
3706bool
3708{
3709 HeapTuple tuple;
3710 Form_pg_index rd_index;
3711 bool result;
3712
3714 if (!HeapTupleIsValid(tuple))
3715 return false;
3716
3717 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3718 result = rd_index->indisreplident;
3719 ReleaseSysCache(tuple);
3720
3721 return result;
3722}
3723
3724/*
3725 * get_index_isvalid
3726 *
3727 * Given the index OID, return pg_index.indisvalid.
3728 */
3729bool
3731{
3732 bool isvalid;
3733 HeapTuple tuple;
3734 Form_pg_index rd_index;
3735
3737 if (!HeapTupleIsValid(tuple))
3738 elog(ERROR, "cache lookup failed for index %u", index_oid);
3739
3740 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3741 isvalid = rd_index->indisvalid;
3742 ReleaseSysCache(tuple);
3743
3744 return isvalid;
3745}
3746
3747/*
3748 * get_index_isclustered
3749 *
3750 * Given the index OID, return pg_index.indisclustered.
3751 */
3752bool
3754{
3755 bool isclustered;
3756 HeapTuple tuple;
3757 Form_pg_index rd_index;
3758
3760 if (!HeapTupleIsValid(tuple))
3761 elog(ERROR, "cache lookup failed for index %u", index_oid);
3762
3763 rd_index = (Form_pg_index) GETSTRUCT(tuple);
3764 isclustered = rd_index->indisclustered;
3765 ReleaseSysCache(tuple);
3766
3767 return isclustered;
3768}
3769
3770/*
3771 * get_publication_oid - given a publication name, look up the OID
3772 *
3773 * If missing_ok is false, throw an error if name not found. If true, just
3774 * return InvalidOid.
3775 */
3776Oid
3777get_publication_oid(const char *pubname, bool missing_ok)
3778{
3779 Oid oid;
3780
3782 CStringGetDatum(pubname));
3783 if (!OidIsValid(oid) && !missing_ok)
3784 ereport(ERROR,
3786 errmsg("publication \"%s\" does not exist", pubname)));
3787 return oid;
3788}
3789
3790/*
3791 * get_publication_name - given a publication Oid, look up the name
3792 *
3793 * If missing_ok is false, throw an error if name not found. If true, just
3794 * return NULL.
3795 */
3796char *
3797get_publication_name(Oid pubid, bool missing_ok)
3798{
3799 HeapTuple tup;
3800 char *pubname;
3802
3804
3805 if (!HeapTupleIsValid(tup))
3806 {
3807 if (!missing_ok)
3808 elog(ERROR, "cache lookup failed for publication %u", pubid);
3809 return NULL;
3810 }
3811
3813 pubname = pstrdup(NameStr(pubform->pubname));
3814
3816
3817 return pubname;
3818}
3819
3820/*
3821 * get_subscription_oid - given a subscription name, look up the OID
3822 *
3823 * If missing_ok is false, throw an error if name not found. If true, just
3824 * return InvalidOid.
3825 */
3826Oid
3827get_subscription_oid(const char *subname, bool missing_ok)
3828{
3829 Oid oid;
3830
3833 if (!OidIsValid(oid) && !missing_ok)
3834 ereport(ERROR,
3836 errmsg("subscription \"%s\" does not exist", subname)));
3837 return oid;
3838}
3839
3840/*
3841 * get_subscription_name - given a subscription OID, look up the name
3842 *
3843 * If missing_ok is false, throw an error if name not found. If true, just
3844 * return NULL.
3845 */
3846char *
3847get_subscription_name(Oid subid, bool missing_ok)
3848{
3849 HeapTuple tup;
3850 char *subname;
3852
3854
3855 if (!HeapTupleIsValid(tup))
3856 {
3857 if (!missing_ok)
3858 elog(ERROR, "cache lookup failed for subscription %u", subid);
3859 return NULL;
3860 }
3861
3863 subname = pstrdup(NameStr(subform->subname));
3864
3866
3867 return subname;
3868}
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:963
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:777
#define Assert(condition)
Definition c.h:885
int16_t int16
Definition c.h:553
regproc RegProcedure
Definition c.h:676
int32_t int32
Definition c.h:554
float float4
Definition c.h:655
#define OidIsValid(objectId)
Definition c.h:800
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
int errmsg(const char *fmt,...)
Definition elog.c:1093
#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:1754
#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:3559
char * get_rel_name(Oid relid)
Definition lsyscache.c:2078
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:138
Oid get_func_variadictype(Oid funcid)
Definition lsyscache.c:1873
Oid get_opclass_method(Oid opclass)
Definition lsyscache.c:1362
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition lsyscache.c:475
bool get_rel_relispartition(Oid relid)
Definition lsyscache.c:2177
Oid get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
Definition lsyscache.c:110
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2228
char get_func_prokind(Oid funcid)
Definition lsyscache.c:1968
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3730
Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
Definition lsyscache.c:1083
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition lsyscache.c:3125
AttrNumber get_attnum(Oid relid, const char *attname)
Definition lsyscache.c:934
RegProcedure get_oprrest(Oid opno)
Definition lsyscache.c:1707
void free_attstatsslot(AttStatsSlot *sslot)
Definition lsyscache.c:3496
bool comparison_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:823
Oid get_constraint_index(Oid conoid)
Definition lsyscache.c:1189
bool get_func_retset(Oid funcid)
Definition lsyscache.c:1892
bool get_ordering_op_properties(Oid opno, Oid *opfamily, Oid *opcintype, CompareType *cmptype)
Definition lsyscache.c:259
Oid get_element_type(Oid typid)
Definition lsyscache.c:2911
Oid get_opclass_input_type(Oid opclass)
Definition lsyscache.c:1314
bool type_is_rowtype(Oid typid)
Definition lsyscache.c:2807
bool type_is_range(Oid typid)
Definition lsyscache.c:2840
char func_parallel(Oid funcid)
Definition lsyscache.c:1949
Oid get_opclass_family(Oid opclass)
Definition lsyscache.c:1292
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:964
bool type_is_enum(Oid typid)
Definition lsyscache.c:2830
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3635
Oid get_typmodin(Oid typid)
Definition lsyscache.c:3158
Oid get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, CompareType cmptype)
Definition lsyscache.c:197
char get_typstorage(Oid typid)
Definition lsyscache.c:2571
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition lsyscache.c:1337
RegProcedure get_func_support(Oid funcid)
Definition lsyscache.c:2008
char * get_database_name(Oid dbid)
Definition lsyscache.c:1242
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3059
bool get_typisdefined(Oid typid)
Definition lsyscache.c:2323
char * get_opname(Oid opno)
Definition lsyscache.c:1460
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1046
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2421
int32 get_attavgwidth(Oid relid, AttrNumber attnum)
Definition lsyscache.c:3310
bool get_index_isreplident(Oid index_oid)
Definition lsyscache.c:3707
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:872
RegProcedure get_oprjoin(Oid opno)
Definition lsyscache.c:1731
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition lsyscache.c:324
bool op_strict(Oid opno)
Definition lsyscache.c:1627
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1587
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2401
Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
Definition lsyscache.c:1846
Oid get_publication_oid(const char *pubname, bool missing_ok)
Definition lsyscache.c:3777
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2102
static bool get_opmethod_canorder(Oid amoid)
Definition lsyscache.c:221
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1435
Oid get_typcollation(Oid typid)
Definition lsyscache.c:3208
Oid get_op_rettype(Oid opno)
Definition lsyscache.c:1483
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:85
char * get_collation_name(Oid colloid)
Definition lsyscache.c:1111
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2129
char * get_language_name(Oid langoid, bool missing_ok)
Definition lsyscache.c:1263
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3542
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3026
char func_volatile(Oid funcid)
Definition lsyscache.c:1930
bool equality_ops_are_compatible(Oid opno1, Oid opno2)
Definition lsyscache.c:771
get_attavgwidth_hook_type get_attavgwidth_hook
Definition lsyscache.c:55
bool get_index_isclustered(Oid index_oid)
Definition lsyscache.c:3753
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:168
Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
Definition lsyscache.c:362
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition lsyscache.c:2292
bool func_strict(Oid funcid)
Definition lsyscache.c:1911
Oid get_index_column_opclass(Oid index_oid, int attno)
Definition lsyscache.c:3664
char * get_constraint_name(Oid conoid)
Definition lsyscache.c:1157
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:903
bool get_func_leakproof(Oid funcid)
Definition lsyscache.c:1987
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition lsyscache.c:3282
Node * get_typdefault(Oid typid)
Definition lsyscache.c:2600
bool get_collation_isdeterministic(Oid colloid)
Definition lsyscache.c:1130
List * get_op_index_interpretation(Oid opno)
Definition lsyscache.c:666
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition lsyscache.c:3827
char * get_subscription_name(Oid subid, bool missing_ok)
Definition lsyscache.c:3847
Oid get_range_collation(Oid rangeOid)
Definition lsyscache.c:3585
char * get_opfamily_name(Oid opfid, bool missing_ok)
Definition lsyscache.c:1403
char * get_func_name(Oid funcid)
Definition lsyscache.c:1758
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3610
Oid get_rel_relam(Oid relid)
Definition lsyscache.c:2250
char op_volatile(Oid opno)
Definition lsyscache.c:1643
Oid get_func_namespace(Oid funcid)
Definition lsyscache.c:1782
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3233
Oid get_rel_tablespace(Oid relid)
Definition lsyscache.c:2204
int get_func_nargs(Oid funcid)
Definition lsyscache.c:1824
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:2475
int16 get_typlen(Oid typid)
Definition lsyscache.c:2347
Oid get_typ_typrelid(Oid typid)
Definition lsyscache.c:2883
char get_typtype(Oid typid)
Definition lsyscache.c:2781
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:2984
Oid getTypeIOParam(HeapTuple typeTuple)
Definition lsyscache.c:2453
Oid get_opfamily_method(Oid opfid)
Definition lsyscache.c:1386
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition lsyscache.c:2690
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition lsyscache.c:2270
char * get_publication_name(Oid pubid, bool missing_ok)
Definition lsyscache.c:3797
Oid getBaseType(Oid typid)
Definition lsyscache.c:2673
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition lsyscache.c:575
bool get_typbyval(Oid typid)
Definition lsyscache.c:2372
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1536
List * get_mergejoin_opfamilies(Oid opno)
Definition lsyscache.c:428
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3518
Oid get_array_type(Oid typid)
Definition lsyscache.c:2939
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1805
Oid get_promoted_array_type(Oid typid)
Definition lsyscache.c:2963
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition lsyscache.c:989
char get_constraint_type(Oid conoid)
Definition lsyscache.c:1219
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition lsyscache.c:2730
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition lsyscache.c:68
RegProcedure get_typsubscript(Oid typid, Oid *typelemp)
Definition lsyscache.c:3249
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
Definition lsyscache.c:2862
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition lsyscache.c:3386
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2035
Oid get_negator(Oid opno)
Definition lsyscache.c:1683
Oid get_commutator(Oid opno)
Definition lsyscache.c:1659
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:1508
bool type_is_multirange(Oid typid)
Definition lsyscache.c:2850
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition lsyscache.c:3092
void get_atttypetypmodcoll(Oid relid, AttrNumber attnum, Oid *typid, int32 *typmod, Oid *collid)
Definition lsyscache.c:1019
#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
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_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:352
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
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:757
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