Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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