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