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