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