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-2021, 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 number,
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 /*
1098  * get_constraint_index
1099  * Given the OID of a unique, primary-key, or exclusion constraint,
1100  * return the OID of the underlying index.
1101  *
1102  * Return InvalidOid if the index couldn't be found; this suggests the
1103  * given OID is bogus, but we leave it to caller to decide what to do.
1104  */
1105 Oid
1107 {
1108  HeapTuple tp;
1109 
1111  if (HeapTupleIsValid(tp))
1112  {
1114  Oid result;
1115 
1116  result = contup->conindid;
1117  ReleaseSysCache(tp);
1118  return result;
1119  }
1120  else
1121  return InvalidOid;
1122 }
1123 
1124 /* ---------- LANGUAGE CACHE ---------- */
1125 
1126 char *
1127 get_language_name(Oid langoid, bool missing_ok)
1128 {
1129  HeapTuple tp;
1130 
1131  tp = SearchSysCache1(LANGOID, ObjectIdGetDatum(langoid));
1132  if (HeapTupleIsValid(tp))
1133  {
1135  char *result;
1136 
1137  result = pstrdup(NameStr(lantup->lanname));
1138  ReleaseSysCache(tp);
1139  return result;
1140  }
1141 
1142  if (!missing_ok)
1143  elog(ERROR, "cache lookup failed for language %u",
1144  langoid);
1145  return NULL;
1146 }
1147 
1148 /* ---------- OPCLASS CACHE ---------- */
1149 
1150 /*
1151  * get_opclass_family
1152  *
1153  * Returns the OID of the operator family the opclass belongs to.
1154  */
1155 Oid
1157 {
1158  HeapTuple tp;
1159  Form_pg_opclass cla_tup;
1160  Oid result;
1161 
1162  tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1163  if (!HeapTupleIsValid(tp))
1164  elog(ERROR, "cache lookup failed for opclass %u", opclass);
1165  cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1166 
1167  result = cla_tup->opcfamily;
1168  ReleaseSysCache(tp);
1169  return result;
1170 }
1171 
1172 /*
1173  * get_opclass_input_type
1174  *
1175  * Returns the OID of the datatype the opclass indexes.
1176  */
1177 Oid
1179 {
1180  HeapTuple tp;
1181  Form_pg_opclass cla_tup;
1182  Oid result;
1183 
1184  tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1185  if (!HeapTupleIsValid(tp))
1186  elog(ERROR, "cache lookup failed for opclass %u", opclass);
1187  cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1188 
1189  result = cla_tup->opcintype;
1190  ReleaseSysCache(tp);
1191  return result;
1192 }
1193 
1194 /*
1195  * get_opclass_opfamily_and_input_type
1196  *
1197  * Returns the OID of the operator family the opclass belongs to,
1198  * the OID of the datatype the opclass indexes
1199  */
1200 bool
1201 get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
1202 {
1203  HeapTuple tp;
1204  Form_pg_opclass cla_tup;
1205 
1206  tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1207  if (!HeapTupleIsValid(tp))
1208  return false;
1209 
1210  cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1211 
1212  *opfamily = cla_tup->opcfamily;
1213  *opcintype = cla_tup->opcintype;
1214 
1215  ReleaseSysCache(tp);
1216 
1217  return true;
1218 }
1219 
1220 /* ---------- OPERATOR CACHE ---------- */
1221 
1222 /*
1223  * get_opcode
1224  *
1225  * Returns the regproc id of the routine used to implement an
1226  * operator given the operator oid.
1227  */
1230 {
1231  HeapTuple tp;
1232 
1234  if (HeapTupleIsValid(tp))
1235  {
1237  RegProcedure result;
1238 
1239  result = optup->oprcode;
1240  ReleaseSysCache(tp);
1241  return result;
1242  }
1243  else
1244  return (RegProcedure) InvalidOid;
1245 }
1246 
1247 /*
1248  * get_opname
1249  * returns the name of the operator with the given opno
1250  *
1251  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1252  */
1253 char *
1255 {
1256  HeapTuple tp;
1257 
1259  if (HeapTupleIsValid(tp))
1260  {
1262  char *result;
1263 
1264  result = pstrdup(NameStr(optup->oprname));
1265  ReleaseSysCache(tp);
1266  return result;
1267  }
1268  else
1269  return NULL;
1270 }
1271 
1272 /*
1273  * get_op_rettype
1274  * Given operator oid, return the operator's result type.
1275  */
1276 Oid
1278 {
1279  HeapTuple tp;
1280 
1282  if (HeapTupleIsValid(tp))
1283  {
1285  Oid result;
1286 
1287  result = optup->oprresult;
1288  ReleaseSysCache(tp);
1289  return result;
1290  }
1291  else
1292  return InvalidOid;
1293 }
1294 
1295 /*
1296  * op_input_types
1297  *
1298  * Returns the left and right input datatypes for an operator
1299  * (InvalidOid if not relevant).
1300  */
1301 void
1302 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1303 {
1304  HeapTuple tp;
1305  Form_pg_operator optup;
1306 
1308  if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1309  elog(ERROR, "cache lookup failed for operator %u", opno);
1310  optup = (Form_pg_operator) GETSTRUCT(tp);
1311  *lefttype = optup->oprleft;
1312  *righttype = optup->oprright;
1313  ReleaseSysCache(tp);
1314 }
1315 
1316 /*
1317  * op_mergejoinable
1318  *
1319  * Returns true if the operator is potentially mergejoinable. (The planner
1320  * will fail to find any mergejoin plans unless there are suitable btree
1321  * opfamily entries for this operator and associated sortops. The pg_operator
1322  * flag is just a hint to tell the planner whether to bother looking.)
1323  *
1324  * In some cases (currently only array_eq and record_eq), mergejoinability
1325  * depends on the specific input data type the operator is invoked for, so
1326  * that must be passed as well. We currently assume that only one input's type
1327  * is needed to check this --- by convention, pass the left input's data type.
1328  */
1329 bool
1330 op_mergejoinable(Oid opno, Oid inputtype)
1331 {
1332  bool result = false;
1333  HeapTuple tp;
1334  TypeCacheEntry *typentry;
1335 
1336  /*
1337  * For array_eq or record_eq, we can sort if the element or field types
1338  * are all sortable. We could implement all the checks for that here, but
1339  * the typcache already does that and caches the results too, so let's
1340  * rely on the typcache.
1341  */
1342  if (opno == ARRAY_EQ_OP)
1343  {
1344  typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1345  if (typentry->cmp_proc == F_BTARRAYCMP)
1346  result = true;
1347  }
1348  else if (opno == RECORD_EQ_OP)
1349  {
1350  typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1351  if (typentry->cmp_proc == F_BTRECORDCMP)
1352  result = true;
1353  }
1354  else
1355  {
1356  /* For all other operators, rely on pg_operator.oprcanmerge */
1358  if (HeapTupleIsValid(tp))
1359  {
1361 
1362  result = optup->oprcanmerge;
1363  ReleaseSysCache(tp);
1364  }
1365  }
1366  return result;
1367 }
1368 
1369 /*
1370  * op_hashjoinable
1371  *
1372  * Returns true if the operator is hashjoinable. (There must be a suitable
1373  * hash opfamily entry for this operator if it is so marked.)
1374  *
1375  * In some cases (currently only array_eq), hashjoinability depends on the
1376  * specific input data type the operator is invoked for, so that must be
1377  * passed as well. We currently assume that only one input's type is needed
1378  * to check this --- by convention, pass the left input's data type.
1379  */
1380 bool
1381 op_hashjoinable(Oid opno, Oid inputtype)
1382 {
1383  bool result = false;
1384  HeapTuple tp;
1385  TypeCacheEntry *typentry;
1386 
1387  /* As in op_mergejoinable, let the typcache handle the hard cases */
1388  if (opno == ARRAY_EQ_OP)
1389  {
1390  typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1391  if (typentry->hash_proc == F_HASH_ARRAY)
1392  result = true;
1393  }
1394  else if (opno == RECORD_EQ_OP)
1395  {
1396  typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1397  if (typentry->hash_proc == F_HASH_RECORD)
1398  result = true;
1399  }
1400  else
1401  {
1402  /* For all other operators, rely on pg_operator.oprcanhash */
1404  if (HeapTupleIsValid(tp))
1405  {
1407 
1408  result = optup->oprcanhash;
1409  ReleaseSysCache(tp);
1410  }
1411  }
1412  return result;
1413 }
1414 
1415 /*
1416  * op_strict
1417  *
1418  * Get the proisstrict flag for the operator's underlying function.
1419  */
1420 bool
1422 {
1423  RegProcedure funcid = get_opcode(opno);
1424 
1425  if (funcid == (RegProcedure) InvalidOid)
1426  elog(ERROR, "operator %u does not exist", opno);
1427 
1428  return func_strict((Oid) funcid);
1429 }
1430 
1431 /*
1432  * op_volatile
1433  *
1434  * Get the provolatile flag for the operator's underlying function.
1435  */
1436 char
1438 {
1439  RegProcedure funcid = get_opcode(opno);
1440 
1441  if (funcid == (RegProcedure) InvalidOid)
1442  elog(ERROR, "operator %u does not exist", opno);
1443 
1444  return func_volatile((Oid) funcid);
1445 }
1446 
1447 /*
1448  * get_commutator
1449  *
1450  * Returns the corresponding commutator of an operator.
1451  */
1452 Oid
1454 {
1455  HeapTuple tp;
1456 
1458  if (HeapTupleIsValid(tp))
1459  {
1461  Oid result;
1462 
1463  result = optup->oprcom;
1464  ReleaseSysCache(tp);
1465  return result;
1466  }
1467  else
1468  return InvalidOid;
1469 }
1470 
1471 /*
1472  * get_negator
1473  *
1474  * Returns the corresponding negator of an operator.
1475  */
1476 Oid
1478 {
1479  HeapTuple tp;
1480 
1482  if (HeapTupleIsValid(tp))
1483  {
1485  Oid result;
1486 
1487  result = optup->oprnegate;
1488  ReleaseSysCache(tp);
1489  return result;
1490  }
1491  else
1492  return InvalidOid;
1493 }
1494 
1495 /*
1496  * get_oprrest
1497  *
1498  * Returns procedure id for computing selectivity of an operator.
1499  */
1502 {
1503  HeapTuple tp;
1504 
1506  if (HeapTupleIsValid(tp))
1507  {
1509  RegProcedure result;
1510 
1511  result = optup->oprrest;
1512  ReleaseSysCache(tp);
1513  return result;
1514  }
1515  else
1516  return (RegProcedure) InvalidOid;
1517 }
1518 
1519 /*
1520  * get_oprjoin
1521  *
1522  * Returns procedure id for computing selectivity of a join.
1523  */
1526 {
1527  HeapTuple tp;
1528 
1530  if (HeapTupleIsValid(tp))
1531  {
1533  RegProcedure result;
1534 
1535  result = optup->oprjoin;
1536  ReleaseSysCache(tp);
1537  return result;
1538  }
1539  else
1540  return (RegProcedure) InvalidOid;
1541 }
1542 
1543 /* ---------- FUNCTION CACHE ---------- */
1544 
1545 /*
1546  * get_func_name
1547  * returns the name of the function with the given funcid
1548  *
1549  * Note: returns a palloc'd copy of the string, or NULL if no such function.
1550  */
1551 char *
1553 {
1554  HeapTuple tp;
1555 
1556  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1557  if (HeapTupleIsValid(tp))
1558  {
1559  Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1560  char *result;
1561 
1562  result = pstrdup(NameStr(functup->proname));
1563  ReleaseSysCache(tp);
1564  return result;
1565  }
1566  else
1567  return NULL;
1568 }
1569 
1570 /*
1571  * get_func_namespace
1572  *
1573  * Returns the pg_namespace OID associated with a given function.
1574  */
1575 Oid
1577 {
1578  HeapTuple tp;
1579 
1580  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1581  if (HeapTupleIsValid(tp))
1582  {
1583  Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1584  Oid result;
1585 
1586  result = functup->pronamespace;
1587  ReleaseSysCache(tp);
1588  return result;
1589  }
1590  else
1591  return InvalidOid;
1592 }
1593 
1594 /*
1595  * get_func_rettype
1596  * Given procedure id, return the function's result type.
1597  */
1598 Oid
1600 {
1601  HeapTuple tp;
1602  Oid result;
1603 
1604  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1605  if (!HeapTupleIsValid(tp))
1606  elog(ERROR, "cache lookup failed for function %u", funcid);
1607 
1608  result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1609  ReleaseSysCache(tp);
1610  return result;
1611 }
1612 
1613 /*
1614  * get_func_nargs
1615  * Given procedure id, return the number of arguments.
1616  */
1617 int
1619 {
1620  HeapTuple tp;
1621  int result;
1622 
1623  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1624  if (!HeapTupleIsValid(tp))
1625  elog(ERROR, "cache lookup failed for function %u", funcid);
1626 
1627  result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1628  ReleaseSysCache(tp);
1629  return result;
1630 }
1631 
1632 /*
1633  * get_func_signature
1634  * Given procedure id, return the function's argument and result types.
1635  * (The return value is the result type.)
1636  *
1637  * The arguments are returned as a palloc'd array.
1638  */
1639 Oid
1640 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1641 {
1642  HeapTuple tp;
1643  Form_pg_proc procstruct;
1644  Oid result;
1645 
1646  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1647  if (!HeapTupleIsValid(tp))
1648  elog(ERROR, "cache lookup failed for function %u", funcid);
1649 
1650  procstruct = (Form_pg_proc) GETSTRUCT(tp);
1651 
1652  result = procstruct->prorettype;
1653  *nargs = (int) procstruct->pronargs;
1654  Assert(*nargs == procstruct->proargtypes.dim1);
1655  *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1656  memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1657 
1658  ReleaseSysCache(tp);
1659  return result;
1660 }
1661 
1662 /*
1663  * get_func_variadictype
1664  * Given procedure id, return the function's provariadic field.
1665  */
1666 Oid
1668 {
1669  HeapTuple tp;
1670  Oid result;
1671 
1672  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1673  if (!HeapTupleIsValid(tp))
1674  elog(ERROR, "cache lookup failed for function %u", funcid);
1675 
1676  result = ((Form_pg_proc) GETSTRUCT(tp))->provariadic;
1677  ReleaseSysCache(tp);
1678  return result;
1679 }
1680 
1681 /*
1682  * get_func_retset
1683  * Given procedure id, return the function's proretset flag.
1684  */
1685 bool
1687 {
1688  HeapTuple tp;
1689  bool result;
1690 
1691  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1692  if (!HeapTupleIsValid(tp))
1693  elog(ERROR, "cache lookup failed for function %u", funcid);
1694 
1695  result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1696  ReleaseSysCache(tp);
1697  return result;
1698 }
1699 
1700 /*
1701  * func_strict
1702  * Given procedure id, return the function's proisstrict flag.
1703  */
1704 bool
1706 {
1707  HeapTuple tp;
1708  bool result;
1709 
1710  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1711  if (!HeapTupleIsValid(tp))
1712  elog(ERROR, "cache lookup failed for function %u", funcid);
1713 
1714  result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1715  ReleaseSysCache(tp);
1716  return result;
1717 }
1718 
1719 /*
1720  * func_volatile
1721  * Given procedure id, return the function's provolatile flag.
1722  */
1723 char
1725 {
1726  HeapTuple tp;
1727  char result;
1728 
1729  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1730  if (!HeapTupleIsValid(tp))
1731  elog(ERROR, "cache lookup failed for function %u", funcid);
1732 
1733  result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1734  ReleaseSysCache(tp);
1735  return result;
1736 }
1737 
1738 /*
1739  * func_parallel
1740  * Given procedure id, return the function's proparallel flag.
1741  */
1742 char
1744 {
1745  HeapTuple tp;
1746  char result;
1747 
1748  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1749  if (!HeapTupleIsValid(tp))
1750  elog(ERROR, "cache lookup failed for function %u", funcid);
1751 
1752  result = ((Form_pg_proc) GETSTRUCT(tp))->proparallel;
1753  ReleaseSysCache(tp);
1754  return result;
1755 }
1756 
1757 /*
1758  * get_func_prokind
1759  * Given procedure id, return the routine kind.
1760  */
1761 char
1763 {
1764  HeapTuple tp;
1765  char result;
1766 
1767  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1768  if (!HeapTupleIsValid(tp))
1769  elog(ERROR, "cache lookup failed for function %u", funcid);
1770 
1771  result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
1772  ReleaseSysCache(tp);
1773  return result;
1774 }
1775 
1776 /*
1777  * get_func_leakproof
1778  * Given procedure id, return the function's leakproof field.
1779  */
1780 bool
1782 {
1783  HeapTuple tp;
1784  bool result;
1785 
1786  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1787  if (!HeapTupleIsValid(tp))
1788  elog(ERROR, "cache lookup failed for function %u", funcid);
1789 
1790  result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
1791  ReleaseSysCache(tp);
1792  return result;
1793 }
1794 
1795 /*
1796  * get_func_support
1797  *
1798  * Returns the support function OID associated with a given function,
1799  * or InvalidOid if there is none.
1800  */
1803 {
1804  HeapTuple tp;
1805 
1806  tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1807  if (HeapTupleIsValid(tp))
1808  {
1809  Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1810  RegProcedure result;
1811 
1812  result = functup->prosupport;
1813  ReleaseSysCache(tp);
1814  return result;
1815  }
1816  else
1817  return (RegProcedure) InvalidOid;
1818 }
1819 
1820 /* ---------- RELATION CACHE ---------- */
1821 
1822 /*
1823  * get_relname_relid
1824  * Given name and namespace of a relation, look up the OID.
1825  *
1826  * Returns InvalidOid if there is no such relation.
1827  */
1828 Oid
1829 get_relname_relid(const char *relname, Oid relnamespace)
1830 {
1831  return GetSysCacheOid2(RELNAMENSP, Anum_pg_class_oid,
1832  PointerGetDatum(relname),
1833  ObjectIdGetDatum(relnamespace));
1834 }
1835 
1836 #ifdef NOT_USED
1837 /*
1838  * get_relnatts
1839  *
1840  * Returns the number of attributes for a given relation.
1841  */
1842 int
1843 get_relnatts(Oid relid)
1844 {
1845  HeapTuple tp;
1846 
1847  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1848  if (HeapTupleIsValid(tp))
1849  {
1850  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1851  int result;
1852 
1853  result = reltup->relnatts;
1854  ReleaseSysCache(tp);
1855  return result;
1856  }
1857  else
1858  return InvalidAttrNumber;
1859 }
1860 #endif
1861 
1862 /*
1863  * get_rel_name
1864  * Returns the name of a given relation.
1865  *
1866  * Returns a palloc'd copy of the string, or NULL if no such relation.
1867  *
1868  * NOTE: since relation name is not unique, be wary of code that uses this
1869  * for anything except preparing error messages.
1870  */
1871 char *
1873 {
1874  HeapTuple tp;
1875 
1876  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1877  if (HeapTupleIsValid(tp))
1878  {
1879  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1880  char *result;
1881 
1882  result = pstrdup(NameStr(reltup->relname));
1883  ReleaseSysCache(tp);
1884  return result;
1885  }
1886  else
1887  return NULL;
1888 }
1889 
1890 /*
1891  * get_rel_namespace
1892  *
1893  * Returns the pg_namespace OID associated with a given relation.
1894  */
1895 Oid
1897 {
1898  HeapTuple tp;
1899 
1900  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1901  if (HeapTupleIsValid(tp))
1902  {
1903  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1904  Oid result;
1905 
1906  result = reltup->relnamespace;
1907  ReleaseSysCache(tp);
1908  return result;
1909  }
1910  else
1911  return InvalidOid;
1912 }
1913 
1914 /*
1915  * get_rel_type_id
1916  *
1917  * Returns the pg_type OID associated with a given relation.
1918  *
1919  * Note: not all pg_class entries have associated pg_type OIDs; so be
1920  * careful to check for InvalidOid result.
1921  */
1922 Oid
1924 {
1925  HeapTuple tp;
1926 
1927  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1928  if (HeapTupleIsValid(tp))
1929  {
1930  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1931  Oid result;
1932 
1933  result = reltup->reltype;
1934  ReleaseSysCache(tp);
1935  return result;
1936  }
1937  else
1938  return InvalidOid;
1939 }
1940 
1941 /*
1942  * get_rel_relkind
1943  *
1944  * Returns the relkind associated with a given relation.
1945  */
1946 char
1948 {
1949  HeapTuple tp;
1950 
1951  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1952  if (HeapTupleIsValid(tp))
1953  {
1954  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1955  char result;
1956 
1957  result = reltup->relkind;
1958  ReleaseSysCache(tp);
1959  return result;
1960  }
1961  else
1962  return '\0';
1963 }
1964 
1965 /*
1966  * get_rel_relispartition
1967  *
1968  * Returns the relispartition flag associated with a given relation.
1969  */
1970 bool
1972 {
1973  HeapTuple tp;
1974 
1975  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1976  if (HeapTupleIsValid(tp))
1977  {
1978  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1979  bool result;
1980 
1981  result = reltup->relispartition;
1982  ReleaseSysCache(tp);
1983  return result;
1984  }
1985  else
1986  return false;
1987 }
1988 
1989 /*
1990  * get_rel_tablespace
1991  *
1992  * Returns the pg_tablespace OID associated with a given relation.
1993  *
1994  * Note: InvalidOid might mean either that we couldn't find the relation,
1995  * or that it is in the database's default tablespace.
1996  */
1997 Oid
1999 {
2000  HeapTuple tp;
2001 
2002  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2003  if (HeapTupleIsValid(tp))
2004  {
2005  Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
2006  Oid result;
2007 
2008  result = reltup->reltablespace;
2009  ReleaseSysCache(tp);
2010  return result;
2011  }
2012  else
2013  return InvalidOid;
2014 }
2015 
2016 /*
2017  * get_rel_persistence
2018  *
2019  * Returns the relpersistence associated with a given relation.
2020  */
2021 char
2023 {
2024  HeapTuple tp;
2025  Form_pg_class reltup;
2026  char result;
2027 
2028  tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2029  if (!HeapTupleIsValid(tp))
2030  elog(ERROR, "cache lookup failed for relation %u", relid);
2031  reltup = (Form_pg_class) GETSTRUCT(tp);
2032  result = reltup->relpersistence;
2033  ReleaseSysCache(tp);
2034 
2035  return result;
2036 }
2037 
2038 
2039 /* ---------- TRANSFORM CACHE ---------- */
2040 
2041 Oid
2042 get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
2043 {
2044  HeapTuple tup;
2045 
2046  if (!list_member_oid(trftypes, typid))
2047  return InvalidOid;
2048 
2049  tup = SearchSysCache2(TRFTYPELANG, typid, langid);
2050  if (HeapTupleIsValid(tup))
2051  {
2052  Oid funcid;
2053 
2054  funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
2055  ReleaseSysCache(tup);
2056  return funcid;
2057  }
2058  else
2059  return InvalidOid;
2060 }
2061 
2062 Oid
2063 get_transform_tosql(Oid typid, Oid langid, List *trftypes)
2064 {
2065  HeapTuple tup;
2066 
2067  if (!list_member_oid(trftypes, typid))
2068  return InvalidOid;
2069 
2070  tup = SearchSysCache2(TRFTYPELANG, typid, langid);
2071  if (HeapTupleIsValid(tup))
2072  {
2073  Oid funcid;
2074 
2075  funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
2076  ReleaseSysCache(tup);
2077  return funcid;
2078  }
2079  else
2080  return InvalidOid;
2081 }
2082 
2083 
2084 /* ---------- TYPE CACHE ---------- */
2085 
2086 /*
2087  * get_typisdefined
2088  *
2089  * Given the type OID, determine whether the type is defined
2090  * (if not, it's only a shell).
2091  */
2092 bool
2094 {
2095  HeapTuple tp;
2096 
2098  if (HeapTupleIsValid(tp))
2099  {
2100  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2101  bool result;
2102 
2103  result = typtup->typisdefined;
2104  ReleaseSysCache(tp);
2105  return result;
2106  }
2107  else
2108  return false;
2109 }
2110 
2111 /*
2112  * get_typlen
2113  *
2114  * Given the type OID, return the length of the type.
2115  */
2116 int16
2118 {
2119  HeapTuple tp;
2120 
2122  if (HeapTupleIsValid(tp))
2123  {
2124  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2125  int16 result;
2126 
2127  result = typtup->typlen;
2128  ReleaseSysCache(tp);
2129  return result;
2130  }
2131  else
2132  return 0;
2133 }
2134 
2135 /*
2136  * get_typbyval
2137  *
2138  * Given the type OID, determine whether the type is returned by value or
2139  * not. Returns true if by value, false if by reference.
2140  */
2141 bool
2143 {
2144  HeapTuple tp;
2145 
2147  if (HeapTupleIsValid(tp))
2148  {
2149  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2150  bool result;
2151 
2152  result = typtup->typbyval;
2153  ReleaseSysCache(tp);
2154  return result;
2155  }
2156  else
2157  return false;
2158 }
2159 
2160 /*
2161  * get_typlenbyval
2162  *
2163  * A two-fer: given the type OID, return both typlen and typbyval.
2164  *
2165  * Since both pieces of info are needed to know how to copy a Datum,
2166  * many places need both. Might as well get them with one cache lookup
2167  * instead of two. Also, this routine raises an error instead of
2168  * returning a bogus value when given a bad type OID.
2169  */
2170 void
2171 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
2172 {
2173  HeapTuple tp;
2174  Form_pg_type typtup;
2175 
2177  if (!HeapTupleIsValid(tp))
2178  elog(ERROR, "cache lookup failed for type %u", typid);
2179  typtup = (Form_pg_type) GETSTRUCT(tp);
2180  *typlen = typtup->typlen;
2181  *typbyval = typtup->typbyval;
2182  ReleaseSysCache(tp);
2183 }
2184 
2185 /*
2186  * get_typlenbyvalalign
2187  *
2188  * A three-fer: given the type OID, return typlen, typbyval, typalign.
2189  */
2190 void
2191 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
2192  char *typalign)
2193 {
2194  HeapTuple tp;
2195  Form_pg_type typtup;
2196 
2198  if (!HeapTupleIsValid(tp))
2199  elog(ERROR, "cache lookup failed for type %u", typid);
2200  typtup = (Form_pg_type) GETSTRUCT(tp);
2201  *typlen = typtup->typlen;
2202  *typbyval = typtup->typbyval;
2203  *typalign = typtup->typalign;
2204  ReleaseSysCache(tp);
2205 }
2206 
2207 /*
2208  * getTypeIOParam
2209  * Given a pg_type row, select the type OID to pass to I/O functions
2210  *
2211  * Formerly, all I/O functions were passed pg_type.typelem as their second
2212  * parameter, but we now have a more complex rule about what to pass.
2213  * This knowledge is intended to be centralized here --- direct references
2214  * to typelem elsewhere in the code are wrong, if they are associated with
2215  * I/O calls and not with actual subscripting operations! (But see
2216  * bootstrap.c's boot_get_type_io_data() if you need to change this.)
2217  *
2218  * As of PostgreSQL 8.1, output functions receive only the value itself
2219  * and not any auxiliary parameters, so the name of this routine is now
2220  * a bit of a misnomer ... it should be getTypeInputParam.
2221  */
2222 Oid
2224 {
2225  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2226 
2227  /*
2228  * Array types get their typelem as parameter; everybody else gets their
2229  * own type OID as parameter.
2230  */
2231  if (OidIsValid(typeStruct->typelem))
2232  return typeStruct->typelem;
2233  else
2234  return typeStruct->oid;
2235 }
2236 
2237 /*
2238  * get_type_io_data
2239  *
2240  * A six-fer: given the type OID, return typlen, typbyval, typalign,
2241  * typdelim, typioparam, and IO function OID. The IO function
2242  * returned is controlled by IOFuncSelector
2243  */
2244 void
2246  IOFuncSelector which_func,
2247  int16 *typlen,
2248  bool *typbyval,
2249  char *typalign,
2250  char *typdelim,
2251  Oid *typioparam,
2252  Oid *func)
2253 {
2254  HeapTuple typeTuple;
2255  Form_pg_type typeStruct;
2256 
2257  /*
2258  * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
2259  * use array_in and array_out during bootstrap.
2260  */
2262  {
2263  Oid typinput;
2264  Oid typoutput;
2265 
2266  boot_get_type_io_data(typid,
2267  typlen,
2268  typbyval,
2269  typalign,
2270  typdelim,
2271  typioparam,
2272  &typinput,
2273  &typoutput);
2274  switch (which_func)
2275  {
2276  case IOFunc_input:
2277  *func = typinput;
2278  break;
2279  case IOFunc_output:
2280  *func = typoutput;
2281  break;
2282  default:
2283  elog(ERROR, "binary I/O not supported during bootstrap");
2284  break;
2285  }
2286  return;
2287  }
2288 
2289  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2290  if (!HeapTupleIsValid(typeTuple))
2291  elog(ERROR, "cache lookup failed for type %u", typid);
2292  typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2293 
2294  *typlen = typeStruct->typlen;
2295  *typbyval = typeStruct->typbyval;
2296  *typalign = typeStruct->typalign;
2297  *typdelim = typeStruct->typdelim;
2298  *typioparam = getTypeIOParam(typeTuple);
2299  switch (which_func)
2300  {
2301  case IOFunc_input:
2302  *func = typeStruct->typinput;
2303  break;
2304  case IOFunc_output:
2305  *func = typeStruct->typoutput;
2306  break;
2307  case IOFunc_receive:
2308  *func = typeStruct->typreceive;
2309  break;
2310  case IOFunc_send:
2311  *func = typeStruct->typsend;
2312  break;
2313  }
2314  ReleaseSysCache(typeTuple);
2315 }
2316 
2317 #ifdef NOT_USED
2318 char
2319 get_typalign(Oid typid)
2320 {
2321  HeapTuple tp;
2322 
2324  if (HeapTupleIsValid(tp))
2325  {
2326  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2327  char result;
2328 
2329  result = typtup->typalign;
2330  ReleaseSysCache(tp);
2331  return result;
2332  }
2333  else
2334  return TYPALIGN_INT;
2335 }
2336 #endif
2337 
2338 char
2340 {
2341  HeapTuple tp;
2342 
2344  if (HeapTupleIsValid(tp))
2345  {
2346  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2347  char result;
2348 
2349  result = typtup->typstorage;
2350  ReleaseSysCache(tp);
2351  return result;
2352  }
2353  else
2354  return TYPSTORAGE_PLAIN;
2355 }
2356 
2357 /*
2358  * get_typdefault
2359  * Given a type OID, return the type's default value, if any.
2360  *
2361  * The result is a palloc'd expression node tree, or NULL if there
2362  * is no defined default for the datatype.
2363  *
2364  * NB: caller should be prepared to coerce result to correct datatype;
2365  * the returned expression tree might produce something of the wrong type.
2366  */
2367 Node *
2369 {
2370  HeapTuple typeTuple;
2372  Datum datum;
2373  bool isNull;
2374  Node *expr;
2375 
2376  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2377  if (!HeapTupleIsValid(typeTuple))
2378  elog(ERROR, "cache lookup failed for type %u", typid);
2379  type = (Form_pg_type) GETSTRUCT(typeTuple);
2380 
2381  /*
2382  * typdefault and typdefaultbin are potentially null, so don't try to
2383  * access 'em as struct fields. Must do it the hard way with
2384  * SysCacheGetAttr.
2385  */
2386  datum = SysCacheGetAttr(TYPEOID,
2387  typeTuple,
2388  Anum_pg_type_typdefaultbin,
2389  &isNull);
2390 
2391  if (!isNull)
2392  {
2393  /* We have an expression default */
2394  expr = stringToNode(TextDatumGetCString(datum));
2395  }
2396  else
2397  {
2398  /* Perhaps we have a plain literal default */
2399  datum = SysCacheGetAttr(TYPEOID,
2400  typeTuple,
2401  Anum_pg_type_typdefault,
2402  &isNull);
2403 
2404  if (!isNull)
2405  {
2406  char *strDefaultVal;
2407 
2408  /* Convert text datum to C string */
2409  strDefaultVal = TextDatumGetCString(datum);
2410  /* Convert C string to a value of the given type */
2411  datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2412  getTypeIOParam(typeTuple), -1);
2413  /* Build a Const node containing the value */
2414  expr = (Node *) makeConst(typid,
2415  -1,
2416  type->typcollation,
2417  type->typlen,
2418  datum,
2419  false,
2420  type->typbyval);
2421  pfree(strDefaultVal);
2422  }
2423  else
2424  {
2425  /* No default */
2426  expr = NULL;
2427  }
2428  }
2429 
2430  ReleaseSysCache(typeTuple);
2431 
2432  return expr;
2433 }
2434 
2435 /*
2436  * getBaseType
2437  * If the given type is a domain, return its base type;
2438  * otherwise return the type's own OID.
2439  */
2440 Oid
2442 {
2443  int32 typmod = -1;
2444 
2445  return getBaseTypeAndTypmod(typid, &typmod);
2446 }
2447 
2448 /*
2449  * getBaseTypeAndTypmod
2450  * If the given type is a domain, return its base type and typmod;
2451  * otherwise return the type's own OID, and leave *typmod unchanged.
2452  *
2453  * Note that the "applied typmod" should be -1 for every domain level
2454  * above the bottommost; therefore, if the passed-in typid is indeed
2455  * a domain, *typmod should be -1.
2456  */
2457 Oid
2459 {
2460  /*
2461  * We loop to find the bottom base type in a stack of domains.
2462  */
2463  for (;;)
2464  {
2465  HeapTuple tup;
2466  Form_pg_type typTup;
2467 
2468  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2469  if (!HeapTupleIsValid(tup))
2470  elog(ERROR, "cache lookup failed for type %u", typid);
2471  typTup = (Form_pg_type) GETSTRUCT(tup);
2472  if (typTup->typtype != TYPTYPE_DOMAIN)
2473  {
2474  /* Not a domain, so done */
2475  ReleaseSysCache(tup);
2476  break;
2477  }
2478 
2479  Assert(*typmod == -1);
2480  typid = typTup->typbasetype;
2481  *typmod = typTup->typtypmod;
2482 
2483  ReleaseSysCache(tup);
2484  }
2485 
2486  return typid;
2487 }
2488 
2489 /*
2490  * get_typavgwidth
2491  *
2492  * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2493  * estimate the average width of values of the type. This is used by
2494  * the planner, which doesn't require absolutely correct results;
2495  * it's OK (and expected) to guess if we don't know for sure.
2496  */
2497 int32
2498 get_typavgwidth(Oid typid, int32 typmod)
2499 {
2500  int typlen = get_typlen(typid);
2501  int32 maxwidth;
2502 
2503  /*
2504  * Easy if it's a fixed-width type
2505  */
2506  if (typlen > 0)
2507  return typlen;
2508 
2509  /*
2510  * type_maximum_size knows the encoding of typmod for some datatypes;
2511  * don't duplicate that knowledge here.
2512  */
2513  maxwidth = type_maximum_size(typid, typmod);
2514  if (maxwidth > 0)
2515  {
2516  /*
2517  * For BPCHAR, the max width is also the only width. Otherwise we
2518  * need to guess about the typical data width given the max. A sliding
2519  * scale for percentage of max width seems reasonable.
2520  */
2521  if (typid == BPCHAROID)
2522  return maxwidth;
2523  if (maxwidth <= 32)
2524  return maxwidth; /* assume full width */
2525  if (maxwidth < 1000)
2526  return 32 + (maxwidth - 32) / 2; /* assume 50% */
2527 
2528  /*
2529  * Beyond 1000, assume we're looking at something like
2530  * "varchar(10000)" where the limit isn't actually reached often, and
2531  * use a fixed estimate.
2532  */
2533  return 32 + (1000 - 32) / 2;
2534  }
2535 
2536  /*
2537  * Oops, we have no idea ... wild guess time.
2538  */
2539  return 32;
2540 }
2541 
2542 /*
2543  * get_typtype
2544  *
2545  * Given the type OID, find if it is a basic type, a complex type, etc.
2546  * It returns the null char if the cache lookup fails...
2547  */
2548 char
2550 {
2551  HeapTuple tp;
2552 
2554  if (HeapTupleIsValid(tp))
2555  {
2556  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2557  char result;
2558 
2559  result = typtup->typtype;
2560  ReleaseSysCache(tp);
2561  return result;
2562  }
2563  else
2564  return '\0';
2565 }
2566 
2567 /*
2568  * type_is_rowtype
2569  *
2570  * Convenience function to determine whether a type OID represents
2571  * a "rowtype" type --- either RECORD or a named composite type
2572  * (including a domain over a named composite type).
2573  */
2574 bool
2576 {
2577  if (typid == RECORDOID)
2578  return true; /* easy case */
2579  switch (get_typtype(typid))
2580  {
2581  case TYPTYPE_COMPOSITE:
2582  return true;
2583  case TYPTYPE_DOMAIN:
2584  if (get_typtype(getBaseType(typid)) == TYPTYPE_COMPOSITE)
2585  return true;
2586  break;
2587  default:
2588  break;
2589  }
2590  return false;
2591 }
2592 
2593 /*
2594  * type_is_enum
2595  * Returns true if the given type is an enum type.
2596  */
2597 bool
2599 {
2600  return (get_typtype(typid) == TYPTYPE_ENUM);
2601 }
2602 
2603 /*
2604  * type_is_range
2605  * Returns true if the given type is a range type.
2606  */
2607 bool
2609 {
2610  return (get_typtype(typid) == TYPTYPE_RANGE);
2611 }
2612 
2613 /*
2614  * type_is_multirange
2615  * Returns true if the given type is a multirange type.
2616  */
2617 bool
2619 {
2620  return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
2621 }
2622 
2623 /*
2624  * get_type_category_preferred
2625  *
2626  * Given the type OID, fetch its category and preferred-type status.
2627  * Throws error on failure.
2628  */
2629 void
2630 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2631 {
2632  HeapTuple tp;
2633  Form_pg_type typtup;
2634 
2636  if (!HeapTupleIsValid(tp))
2637  elog(ERROR, "cache lookup failed for type %u", typid);
2638  typtup = (Form_pg_type) GETSTRUCT(tp);
2639  *typcategory = typtup->typcategory;
2640  *typispreferred = typtup->typispreferred;
2641  ReleaseSysCache(tp);
2642 }
2643 
2644 /*
2645  * get_typ_typrelid
2646  *
2647  * Given the type OID, get the typrelid (InvalidOid if not a complex
2648  * type).
2649  */
2650 Oid
2652 {
2653  HeapTuple tp;
2654 
2656  if (HeapTupleIsValid(tp))
2657  {
2658  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2659  Oid result;
2660 
2661  result = typtup->typrelid;
2662  ReleaseSysCache(tp);
2663  return result;
2664  }
2665  else
2666  return InvalidOid;
2667 }
2668 
2669 /*
2670  * get_element_type
2671  *
2672  * Given the type OID, get the typelem (InvalidOid if not an array type).
2673  *
2674  * NB: this only succeeds for "true" arrays having array_subscript_handler
2675  * as typsubscript. For other types, InvalidOid is returned independently
2676  * of whether they have typelem or typsubscript set.
2677  */
2678 Oid
2680 {
2681  HeapTuple tp;
2682 
2684  if (HeapTupleIsValid(tp))
2685  {
2686  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2687  Oid result;
2688 
2689  if (IsTrueArrayType(typtup))
2690  result = typtup->typelem;
2691  else
2692  result = InvalidOid;
2693  ReleaseSysCache(tp);
2694  return result;
2695  }
2696  else
2697  return InvalidOid;
2698 }
2699 
2700 /*
2701  * get_array_type
2702  *
2703  * Given the type OID, get the corresponding "true" array type.
2704  * Returns InvalidOid if no array type can be found.
2705  */
2706 Oid
2708 {
2709  HeapTuple tp;
2710  Oid result = InvalidOid;
2711 
2713  if (HeapTupleIsValid(tp))
2714  {
2715  result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2716  ReleaseSysCache(tp);
2717  }
2718  return result;
2719 }
2720 
2721 /*
2722  * get_promoted_array_type
2723  *
2724  * The "promoted" type is what you'd get from an ARRAY(SELECT ...)
2725  * construct, that is, either the corresponding "true" array type
2726  * if the input is a scalar type that has such an array type,
2727  * or the same type if the input is already a "true" array type.
2728  * Returns InvalidOid if neither rule is satisfied.
2729  */
2730 Oid
2732 {
2733  Oid array_type = get_array_type(typid);
2734 
2735  if (OidIsValid(array_type))
2736  return array_type;
2737  if (OidIsValid(get_element_type(typid)))
2738  return typid;
2739  return InvalidOid;
2740 }
2741 
2742 /*
2743  * get_base_element_type
2744  * Given the type OID, get the typelem, looking "through" any domain
2745  * to its underlying array type.
2746  *
2747  * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2748  * an extra cache lookup. Note that it fails to provide any information
2749  * about the typmod of the array.
2750  */
2751 Oid
2753 {
2754  /*
2755  * We loop to find the bottom base type in a stack of domains.
2756  */
2757  for (;;)
2758  {
2759  HeapTuple tup;
2760  Form_pg_type typTup;
2761 
2762  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2763  if (!HeapTupleIsValid(tup))
2764  break;
2765  typTup = (Form_pg_type) GETSTRUCT(tup);
2766  if (typTup->typtype != TYPTYPE_DOMAIN)
2767  {
2768  /* Not a domain, so stop descending */
2769  Oid result;
2770 
2771  /* This test must match get_element_type */
2772  if (IsTrueArrayType(typTup))
2773  result = typTup->typelem;
2774  else
2775  result = InvalidOid;
2776  ReleaseSysCache(tup);
2777  return result;
2778  }
2779 
2780  typid = typTup->typbasetype;
2781  ReleaseSysCache(tup);
2782  }
2783 
2784  /* Like get_element_type, silently return InvalidOid for bogus input */
2785  return InvalidOid;
2786 }
2787 
2788 /*
2789  * getTypeInputInfo
2790  *
2791  * Get info needed for converting values of a type to internal form
2792  */
2793 void
2794 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2795 {
2796  HeapTuple typeTuple;
2797  Form_pg_type pt;
2798 
2799  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2800  if (!HeapTupleIsValid(typeTuple))
2801  elog(ERROR, "cache lookup failed for type %u", type);
2802  pt = (Form_pg_type) GETSTRUCT(typeTuple);
2803 
2804  if (!pt->typisdefined)
2805  ereport(ERROR,
2806  (errcode(ERRCODE_UNDEFINED_OBJECT),
2807  errmsg("type %s is only a shell",
2808  format_type_be(type))));
2809  if (!OidIsValid(pt->typinput))
2810  ereport(ERROR,
2811  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2812  errmsg("no input function available for type %s",
2813  format_type_be(type))));
2814 
2815  *typInput = pt->typinput;
2816  *typIOParam = getTypeIOParam(typeTuple);
2817 
2818  ReleaseSysCache(typeTuple);
2819 }
2820 
2821 /*
2822  * getTypeOutputInfo
2823  *
2824  * Get info needed for printing values of a type
2825  */
2826 void
2827 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2828 {
2829  HeapTuple typeTuple;
2830  Form_pg_type pt;
2831 
2832  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2833  if (!HeapTupleIsValid(typeTuple))
2834  elog(ERROR, "cache lookup failed for type %u", type);
2835  pt = (Form_pg_type) GETSTRUCT(typeTuple);
2836 
2837  if (!pt->typisdefined)
2838  ereport(ERROR,
2839  (errcode(ERRCODE_UNDEFINED_OBJECT),
2840  errmsg("type %s is only a shell",
2841  format_type_be(type))));
2842  if (!OidIsValid(pt->typoutput))
2843  ereport(ERROR,
2844  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2845  errmsg("no output function available for type %s",
2846  format_type_be(type))));
2847 
2848  *typOutput = pt->typoutput;
2849  *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2850 
2851  ReleaseSysCache(typeTuple);
2852 }
2853 
2854 /*
2855  * getTypeBinaryInputInfo
2856  *
2857  * Get info needed for binary input of values of a type
2858  */
2859 void
2860 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2861 {
2862  HeapTuple typeTuple;
2863  Form_pg_type pt;
2864 
2865  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2866  if (!HeapTupleIsValid(typeTuple))
2867  elog(ERROR, "cache lookup failed for type %u", type);
2868  pt = (Form_pg_type) GETSTRUCT(typeTuple);
2869 
2870  if (!pt->typisdefined)
2871  ereport(ERROR,
2872  (errcode(ERRCODE_UNDEFINED_OBJECT),
2873  errmsg("type %s is only a shell",
2874  format_type_be(type))));
2875  if (!OidIsValid(pt->typreceive))
2876  ereport(ERROR,
2877  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2878  errmsg("no binary input function available for type %s",
2879  format_type_be(type))));
2880 
2881  *typReceive = pt->typreceive;
2882  *typIOParam = getTypeIOParam(typeTuple);
2883 
2884  ReleaseSysCache(typeTuple);
2885 }
2886 
2887 /*
2888  * getTypeBinaryOutputInfo
2889  *
2890  * Get info needed for binary output of values of a type
2891  */
2892 void
2893 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2894 {
2895  HeapTuple typeTuple;
2896  Form_pg_type pt;
2897 
2898  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2899  if (!HeapTupleIsValid(typeTuple))
2900  elog(ERROR, "cache lookup failed for type %u", type);
2901  pt = (Form_pg_type) GETSTRUCT(typeTuple);
2902 
2903  if (!pt->typisdefined)
2904  ereport(ERROR,
2905  (errcode(ERRCODE_UNDEFINED_OBJECT),
2906  errmsg("type %s is only a shell",
2907  format_type_be(type))));
2908  if (!OidIsValid(pt->typsend))
2909  ereport(ERROR,
2910  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2911  errmsg("no binary output function available for type %s",
2912  format_type_be(type))));
2913 
2914  *typSend = pt->typsend;
2915  *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2916 
2917  ReleaseSysCache(typeTuple);
2918 }
2919 
2920 /*
2921  * get_typmodin
2922  *
2923  * Given the type OID, return the type's typmodin procedure, if any.
2924  */
2925 Oid
2927 {
2928  HeapTuple tp;
2929 
2931  if (HeapTupleIsValid(tp))
2932  {
2933  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2934  Oid result;
2935 
2936  result = typtup->typmodin;
2937  ReleaseSysCache(tp);
2938  return result;
2939  }
2940  else
2941  return InvalidOid;
2942 }
2943 
2944 #ifdef NOT_USED
2945 /*
2946  * get_typmodout
2947  *
2948  * Given the type OID, return the type's typmodout procedure, if any.
2949  */
2950 Oid
2951 get_typmodout(Oid typid)
2952 {
2953  HeapTuple tp;
2954 
2956  if (HeapTupleIsValid(tp))
2957  {
2958  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2959  Oid result;
2960 
2961  result = typtup->typmodout;
2962  ReleaseSysCache(tp);
2963  return result;
2964  }
2965  else
2966  return InvalidOid;
2967 }
2968 #endif /* NOT_USED */
2969 
2970 /*
2971  * get_typcollation
2972  *
2973  * Given the type OID, return the type's typcollation attribute.
2974  */
2975 Oid
2977 {
2978  HeapTuple tp;
2979 
2981  if (HeapTupleIsValid(tp))
2982  {
2983  Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2984  Oid result;
2985 
2986  result = typtup->typcollation;
2987  ReleaseSysCache(tp);
2988  return result;
2989  }
2990  else
2991  return InvalidOid;
2992 }
2993 
2994 
2995 /*
2996  * type_is_collatable
2997  *
2998  * Return whether the type cares about collations
2999  */
3000 bool
3002 {
3003  return OidIsValid(get_typcollation(typid));
3004 }
3005 
3006 
3007 /*
3008  * get_typsubscript
3009  *
3010  * Given the type OID, return the type's subscripting handler's OID,
3011  * if it has one.
3012  *
3013  * If typelemp isn't NULL, we also store the type's typelem value there.
3014  * This saves some callers an extra catalog lookup.
3015  */
3017 get_typsubscript(Oid typid, Oid *typelemp)
3018 {
3019  HeapTuple tp;
3020 
3022  if (HeapTupleIsValid(tp))
3023  {
3024  Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
3025  RegProcedure handler = typform->typsubscript;
3026 
3027  if (typelemp)
3028  *typelemp = typform->typelem;
3029  ReleaseSysCache(tp);
3030  return handler;
3031  }
3032  else
3033  {
3034  if (typelemp)
3035  *typelemp = InvalidOid;
3036  return InvalidOid;
3037  }
3038 }
3039 
3040 /*
3041  * getSubscriptingRoutines
3042  *
3043  * Given the type OID, fetch the type's subscripting methods struct.
3044  * Return NULL if type is not subscriptable.
3045  *
3046  * If typelemp isn't NULL, we also store the type's typelem value there.
3047  * This saves some callers an extra catalog lookup.
3048  */
3049 const struct SubscriptRoutines *
3051 {
3052  RegProcedure typsubscript = get_typsubscript(typid, typelemp);
3053 
3054  if (!OidIsValid(typsubscript))
3055  return NULL;
3056 
3057  return (const struct SubscriptRoutines *)
3058  DatumGetPointer(OidFunctionCall0(typsubscript));
3059 }
3060 
3061 
3062 /* ---------- STATISTICS CACHE ---------- */
3063 
3064 /*
3065  * get_attavgwidth
3066  *
3067  * Given the table and attribute number of a column, get the average
3068  * width of entries in the column. Return zero if no data available.
3069  *
3070  * Currently this is only consulted for individual tables, not for inheritance
3071  * trees, so we don't need an "inh" parameter.
3072  *
3073  * Calling a hook at this point looks somewhat strange, but is required
3074  * because the optimizer calls this function without any other way for
3075  * plug-ins to control the result.
3076  */
3077 int32
3079 {
3080  HeapTuple tp;
3081  int32 stawidth;
3082 
3084  {
3085  stawidth = (*get_attavgwidth_hook) (relid, attnum);
3086  if (stawidth > 0)
3087  return stawidth;
3088  }
3090  ObjectIdGetDatum(relid),
3091  Int16GetDatum(attnum),
3092  BoolGetDatum(false));
3093  if (HeapTupleIsValid(tp))
3094  {
3095  stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
3096  ReleaseSysCache(tp);
3097  if (stawidth > 0)
3098  return stawidth;
3099  }
3100  return 0;
3101 }
3102 
3103 /*
3104  * get_attstatsslot
3105  *
3106  * Extract the contents of a "slot" of a pg_statistic tuple.
3107  * Returns true if requested slot type was found, else false.
3108  *
3109  * Unlike other routines in this file, this takes a pointer to an
3110  * already-looked-up tuple in the pg_statistic cache. We do this since
3111  * most callers will want to extract more than one value from the cache
3112  * entry, and we don't want to repeat the cache lookup unnecessarily.
3113  * Also, this API allows this routine to be used with statistics tuples
3114  * that have been provided by a stats hook and didn't really come from
3115  * pg_statistic.
3116  *
3117  * sslot: pointer to output area (typically, a local variable in the caller).
3118  * statstuple: pg_statistic tuple to be examined.
3119  * reqkind: STAKIND code for desired statistics slot kind.
3120  * reqop: STAOP value wanted, or InvalidOid if don't care.
3121  * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
3122  *
3123  * If a matching slot is found, true is returned, and *sslot is filled thus:
3124  * staop: receives the actual STAOP value.
3125  * stacoll: receives the actual STACOLL value.
3126  * valuetype: receives actual datatype of the elements of stavalues.
3127  * values: receives pointer to an array of the slot's stavalues.
3128  * nvalues: receives number of stavalues.
3129  * numbers: receives pointer to an array of the slot's stanumbers (as float4).
3130  * nnumbers: receives number of stanumbers.
3131  *
3132  * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
3133  * wasn't specified. Likewise, numbers/nnumbers are NULL/0 if
3134  * ATTSTATSSLOT_NUMBERS wasn't specified.
3135  *
3136  * If no matching slot is found, false is returned, and *sslot is zeroed.
3137  *
3138  * Note that the current API doesn't allow for searching for a slot with
3139  * a particular collation. If we ever actually support recording more than
3140  * one collation, we'll have to extend the API, but for now simple is good.
3141  *
3142  * The data referred to by the fields of sslot is locally palloc'd and
3143  * is independent of the original pg_statistic tuple. When the caller
3144  * is done with it, call free_attstatsslot to release the palloc'd data.
3145  *
3146  * If it's desirable to call free_attstatsslot when get_attstatsslot might
3147  * not have been called, memset'ing sslot to zeroes will allow that.
3148  */
3149 bool
3151  int reqkind, Oid reqop, int flags)
3152 {
3153  Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
3154  int i;
3155  Datum val;
3156  bool isnull;
3157  ArrayType *statarray;
3158  Oid arrayelemtype;
3159  int narrayelem;
3160  HeapTuple typeTuple;
3161  Form_pg_type typeForm;
3162 
3163  /* initialize *sslot properly */
3164  memset(sslot, 0, sizeof(AttStatsSlot));
3165 
3166  for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
3167  {
3168  if ((&stats->stakind1)[i] == reqkind &&
3169  (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
3170  break;
3171  }
3172  if (i >= STATISTIC_NUM_SLOTS)
3173  return false; /* not there */
3174 
3175  sslot->staop = (&stats->staop1)[i];
3176  sslot->stacoll = (&stats->stacoll1)[i];
3177 
3178  if (flags & ATTSTATSSLOT_VALUES)
3179  {
3180  val = SysCacheGetAttr(STATRELATTINH, statstuple,
3181  Anum_pg_statistic_stavalues1 + i,
3182  &isnull);
3183  if (isnull)
3184  elog(ERROR, "stavalues is null");
3185 
3186  /*
3187  * Detoast the array if needed, and in any case make a copy that's
3188  * under control of this AttStatsSlot.
3189  */
3190  statarray = DatumGetArrayTypePCopy(val);
3191 
3192  /*
3193  * Extract the actual array element type, and pass it back in case the
3194  * caller needs it.
3195  */
3196  sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
3197 
3198  /* Need info about element type */
3199  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
3200  if (!HeapTupleIsValid(typeTuple))
3201  elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
3202  typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
3203 
3204  /* Deconstruct array into Datum elements; NULLs not expected */
3205  deconstruct_array(statarray,
3206  arrayelemtype,
3207  typeForm->typlen,
3208  typeForm->typbyval,
3209  typeForm->typalign,
3210  &sslot->values, NULL, &sslot->nvalues);
3211 
3212  /*
3213  * If the element type is pass-by-reference, we now have a bunch of
3214  * Datums that are pointers into the statarray, so we need to keep
3215  * that until free_attstatsslot. Otherwise, all the useful info is in
3216  * sslot->values[], so we can free the array object immediately.
3217  */
3218  if (!typeForm->typbyval)
3219  sslot->values_arr = statarray;
3220  else
3221  pfree(statarray);
3222 
3223  ReleaseSysCache(typeTuple);
3224  }
3225 
3226  if (flags & ATTSTATSSLOT_NUMBERS)
3227  {
3228  val = SysCacheGetAttr(STATRELATTINH, statstuple,
3229  Anum_pg_statistic_stanumbers1 + i,
3230  &isnull);
3231  if (isnull)
3232  elog(ERROR, "stanumbers is null");
3233 
3234  /*
3235  * Detoast the array if needed, and in any case make a copy that's
3236  * under control of this AttStatsSlot.
3237  */
3238  statarray = DatumGetArrayTypePCopy(val);
3239 
3240  /*
3241  * We expect the array to be a 1-D float4 array; verify that. We don't
3242  * need to use deconstruct_array() since the array data is just going
3243  * to look like a C array of float4 values.
3244  */
3245  narrayelem = ARR_DIMS(statarray)[0];
3246  if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
3247  ARR_HASNULL(statarray) ||
3248  ARR_ELEMTYPE(statarray) != FLOAT4OID)
3249  elog(ERROR, "stanumbers is not a 1-D float4 array");
3250 
3251  /* Give caller a pointer directly into the statarray */
3252  sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
3253  sslot->nnumbers = narrayelem;
3254 
3255  /* We'll free the statarray in free_attstatsslot */
3256  sslot->numbers_arr = statarray;
3257  }
3258 
3259  return true;
3260 }
3261 
3262 /*
3263  * free_attstatsslot
3264  * Free data allocated by get_attstatsslot
3265  */
3266 void
3268 {
3269  /* The values[] array was separately palloc'd by deconstruct_array */
3270  if (sslot->values)
3271  pfree(sslot->values);
3272  /* The numbers[] array points into numbers_arr, do not pfree it */
3273  /* Free the detoasted array objects, if any */
3274  if (sslot->values_arr)
3275  pfree(sslot->values_arr);
3276  if (sslot->numbers_arr)
3277  pfree(sslot->numbers_arr);
3278 }
3279 
3280 /* ---------- PG_NAMESPACE CACHE ---------- */
3281 
3282 /*
3283  * get_namespace_name
3284  * Returns the name of a given namespace
3285  *
3286  * Returns a palloc'd copy of the string, or NULL if no such namespace.
3287  */
3288 char *
3290 {
3291  HeapTuple tp;
3292 
3294  if (HeapTupleIsValid(tp))
3295  {
3297  char *result;
3298 
3299  result = pstrdup(NameStr(nsptup->nspname));
3300  ReleaseSysCache(tp);
3301  return result;
3302  }
3303  else
3304  return NULL;
3305 }
3306 
3307 /*
3308  * get_namespace_name_or_temp
3309  * As above, but if it is this backend's temporary namespace, return
3310  * "pg_temp" instead.
3311  */
3312 char *
3314 {
3315  if (isTempNamespace(nspid))
3316  return "pg_temp";
3317  else
3318  return get_namespace_name(nspid);
3319 }
3320 
3321 /* ---------- PG_RANGE CACHES ---------- */
3322 
3323 /*
3324  * get_range_subtype
3325  * Returns the subtype of a given range type
3326  *
3327  * Returns InvalidOid if the type is not a range type.
3328  */
3329 Oid
3331 {
3332  HeapTuple tp;
3333 
3334  tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3335  if (HeapTupleIsValid(tp))
3336  {
3337  Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3338  Oid result;
3339 
3340  result = rngtup->rngsubtype;
3341  ReleaseSysCache(tp);
3342  return result;
3343  }
3344  else
3345  return InvalidOid;
3346 }
3347 
3348 /*
3349  * get_range_collation
3350  * Returns the collation of a given range type
3351  *
3352  * Returns InvalidOid if the type is not a range type,
3353  * or if its subtype is not collatable.
3354  */
3355 Oid
3357 {
3358  HeapTuple tp;
3359 
3360  tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3361  if (HeapTupleIsValid(tp))
3362  {
3363  Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3364  Oid result;
3365 
3366  result = rngtup->rngcollation;
3367  ReleaseSysCache(tp);
3368  return result;
3369  }
3370  else
3371  return InvalidOid;
3372 }
3373 
3374 /*
3375  * get_range_multirange
3376  * Returns the multirange type of a given range type
3377  *
3378  * Returns InvalidOid if the type is not a range type.
3379  */
3380 Oid
3382 {
3383  HeapTuple tp;
3384 
3385  tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
3386  if (HeapTupleIsValid(tp))
3387  {
3388  Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3389  Oid result;
3390 
3391  result = rngtup->rngmultitypid;
3392  ReleaseSysCache(tp);
3393  return result;
3394  }
3395  else
3396  return InvalidOid;
3397 }
3398 
3399 /*
3400  * get_multirange_range
3401  * Returns the range type of a given multirange
3402  *
3403  * Returns InvalidOid if the type is not a multirange.
3404  */
3405 Oid
3407 {
3408  HeapTuple tp;
3409 
3410  tp = SearchSysCache1(RANGEMULTIRANGE, ObjectIdGetDatum(multirangeOid));
3411  if (HeapTupleIsValid(tp))
3412  {
3413  Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
3414  Oid result;
3415 
3416  result = rngtup->rngtypid;
3417  ReleaseSysCache(tp);
3418  return result;
3419  }
3420  else
3421  return InvalidOid;
3422 }
3423 
3424 /* ---------- PG_INDEX CACHE ---------- */
3425 
3426 /*
3427  * get_index_column_opclass
3428  *
3429  * Given the index OID and column number,
3430  * return opclass of the index column
3431  * or InvalidOid if the index was not found
3432  * or column is non-key one.
3433  */
3434 Oid
3435 get_index_column_opclass(Oid index_oid, int attno)
3436 {
3437  HeapTuple tuple;
3439  Datum datum;
3440  bool isnull;
3441  oidvector *indclass;
3442  Oid opclass;
3443 
3444  /* First we need to know the column's opclass. */
3445 
3446  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3447  if (!HeapTupleIsValid(tuple))
3448  return InvalidOid;
3449 
3450  rd_index = (Form_pg_index) GETSTRUCT(tuple);
3451 
3452  /* caller is supposed to guarantee this */
3453  Assert(attno > 0 && attno <= rd_index->indnatts);
3454 
3455  /* Non-key attributes don't have an opclass */
3456  if (attno > rd_index->indnkeyatts)
3457  {
3458  ReleaseSysCache(tuple);
3459  return InvalidOid;
3460  }
3461 
3462  datum = SysCacheGetAttr(INDEXRELID, tuple,
3463  Anum_pg_index_indclass, &isnull);
3464  Assert(!isnull);
3465 
3466  indclass = ((oidvector *) DatumGetPointer(datum));
3467 
3468  Assert(attno <= indclass->dim1);
3469  opclass = indclass->values[attno - 1];
3470 
3471  ReleaseSysCache(tuple);
3472 
3473  return opclass;
3474 }
3475 
3476 /*
3477  * get_index_isreplident
3478  *
3479  * Given the index OID, return pg_index.indisreplident.
3480  */
3481 bool
3483 {
3484  HeapTuple tuple;
3485  Form_pg_index rd_index;
3486  bool result;
3487 
3488  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3489  if (!HeapTupleIsValid(tuple))
3490  return false;
3491 
3492  rd_index = (Form_pg_index) GETSTRUCT(tuple);
3493  result = rd_index->indisreplident;
3494  ReleaseSysCache(tuple);
3495 
3496  return result;
3497 }
3498 
3499 /*
3500  * get_index_isvalid
3501  *
3502  * Given the index OID, return pg_index.indisvalid.
3503  */
3504 bool
3506 {
3507  bool isvalid;
3508  HeapTuple tuple;
3509  Form_pg_index rd_index;
3510 
3511  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3512  if (!HeapTupleIsValid(tuple))
3513  elog(ERROR, "cache lookup failed for index %u", index_oid);
3514 
3515  rd_index = (Form_pg_index) GETSTRUCT(tuple);
3516  isvalid = rd_index->indisvalid;
3517  ReleaseSysCache(tuple);
3518 
3519  return isvalid;
3520 }
3521 
3522 /*
3523  * get_index_isclustered
3524  *
3525  * Given the index OID, return pg_index.indisclustered.
3526  */
3527 bool
3529 {
3530  bool isclustered;
3531  HeapTuple tuple;
3532  Form_pg_index rd_index;
3533 
3534  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
3535  if (!HeapTupleIsValid(tuple))
3536  elog(ERROR, "cache lookup failed for index %u", index_oid);
3537 
3538  rd_index = (Form_pg_index) GETSTRUCT(tuple);
3539  isclustered = rd_index->indisclustered;
3540  ReleaseSysCache(tuple);
3541 
3542  return isclustered;
3543 }
signed short int16
Definition: c.h:416
#define NIL
Definition: pg_list.h:65
Definition: c.h:648
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:2042
char get_typstorage(Oid typid)
Definition: lsyscache.c:2339
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1781
RegProcedure get_oprjoin(Oid opno)
Definition: lsyscache.c:1525
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2458
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:1421
FormData_pg_range * Form_pg_range
Definition: pg_range.h:58
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:1453
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2827
#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:1127
#define ATTSTATSSLOT_VALUES
Definition: lsyscache.h:42
Oid get_func_namespace(Oid funcid)
Definition: lsyscache.c:1576
char * get_constraint_name(Oid conoid)
Definition: lsyscache.c:1079
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2679
int nnumbers
Definition: lsyscache.h:57
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2191
#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:2707
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1947
char * get_collation_name(Oid colloid)
Definition: lsyscache.c:1033
char * pstrdup(const char *in)
Definition: mcxt.c:1187
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:573
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1896
#define Int16GetDatum(X)
Definition: postgres.h:451
Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
Definition: lsyscache.c:1640
Definition: nodes.h:528
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2093
bool get_collation_isdeterministic(Oid colloid)
Definition: lsyscache.c:1052
uint16 StrategyNumber
Definition: stratnum.h:22
int errcode(int sqlerrcode)
Definition: elog.c:704
void * stringToNode(const char *str)
Definition: read.c:89
char get_typtype(Oid typid)
Definition: lsyscache.c:2549
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
bool type_is_range(Oid typid)
Definition: lsyscache.c:2608
Oid get_range_multirange(Oid rangeOid)
Definition: lsyscache.c:3381
IOFuncSelector
Definition: lsyscache.h:33
int16 pronargs
Definition: pg_proc.h:81
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition: lsyscache.c:1330
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:299
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:698
Oid get_op_rettype(Oid opno)
Definition: lsyscache.c:1277
const struct SubscriptRoutines * getSubscriptingRoutines(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3050
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1599
signed int int32
Definition: c.h:417
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3406
Oid get_rel_tablespace(Oid relid)
Definition: lsyscache.c:1998
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
bool get_typbyval(Oid typid)
Definition: lsyscache.c:2142
char * get_opname(Oid opno)
Definition: lsyscache.c:1254
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition: lsyscache.c:1201
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:968
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2651
void pfree(void *pointer)
Definition: mcxt.c:1057
char typalign
Definition: pg_type.h:176
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition: lsyscache.c:1381
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
#define ATTSTATSSLOT_NUMBERS
Definition: lsyscache.h:43
void * values_arr
Definition: lsyscache.h:60
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
NameData attname
Definition: pg_attribute.h:40
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:188
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1552
#define ARR_DIMS(a)
Definition: array.h:287
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1149
#define HTEqualStrategyNumber
Definition: stratnum.h:41
int32 type_maximum_size(Oid type_oid, int32 typemod)
Definition: format_type.c:408
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1829
#define ARR_DATA_PTR(a)
Definition: array.h:315
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
Oid get_func_variadictype(Oid funcid)
Definition: lsyscache.c:1667
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:856
float4 * numbers
Definition: lsyscache.h:56
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:656
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:3156
#define ARR_HASNULL(a)
Definition: array.h:284
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:211
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1302
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:2575
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1160
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:911
Oid get_typmodin(Oid typid)
Definition: lsyscache.c:2926
#define HASHSTANDARD_PROC
Definition: hash.h:353
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2860
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2794
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
bool get_rel_relispartition(Oid relid)
Definition: lsyscache.c:1971
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:3356
FormData_pg_index * Form_pg_index
Definition: pg_index.h:68
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
float float4
Definition: c.h:552
bool get_func_retset(Oid funcid)
Definition: lsyscache.c:1686
Oid get_promoted_array_type(Oid typid)
Definition: lsyscache.c:2731
#define ReleaseSysCacheList(x)
Definition: syscache.h:218
RegProcedure get_oprrest(Oid opno)
Definition: lsyscache.c:1501
#define TextDatumGetCString(d)
Definition: builtins.h:83
char get_func_prokind(Oid funcid)
Definition: lsyscache.c:1762
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
Definition: lsyscache.c:2893
char op_volatile(Oid opno)
Definition: lsyscache.c:1437
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:1175
int32(* get_attavgwidth_hook_type)(Oid relid, AttrNumber attnum)
Definition: lsyscache.h:65
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define DatumGetArrayTypePCopy(X)
Definition: array.h:255
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1923
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:2498
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1229
int16 attnum
Definition: pg_attribute.h:79
#define STATISTIC_NUM_SLOTS
Definition: pg_statistic.h:126
#define ereport(elevel,...)
Definition: elog.h:155
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2976
#define TYPECACHE_CMP_PROC
Definition: typcache.h:139
#define OidFunctionCall0(functionId)
Definition: fmgr.h:662
RegProcedure get_func_support(Oid funcid)
Definition: lsyscache.c:1802
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:3150
#define Assert(condition)
Definition: c.h:792
Datum * values
Definition: lsyscache.h:53
Node * get_typdefault(Oid typid)
Definition: lsyscache.c:2368
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:195
char func_parallel(Oid funcid)
Definition: lsyscache.c:1743
bool get_ordering_op_properties(Oid opno, Oid *opfamily, Oid *opcintype, int16 *strategy)
Definition: lsyscache.c:205
bool type_is_multirange(Oid typid)
Definition: lsyscache.c:2618
bool type_is_enum(Oid typid)
Definition: lsyscache.c:2598
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:3505
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
bool get_index_isreplident(Oid index_oid)
Definition: lsyscache.c:3482
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2171
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1268
#define ARR_NDIM(a)
Definition: array.h:283
bool get_index_isclustered(Oid index_oid)
Definition: lsyscache.c:3528
Oid get_opclass_family(Oid opclass)
Definition: lsyscache.c:1156
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
bool func_strict(Oid funcid)
Definition: lsyscache.c:1705
#define InvalidAttrNumber
Definition: attnum.h:23
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
#define CharGetDatum(X)
Definition: postgres.h:416
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:2063
#define DatumGetPointer(X)
Definition: postgres.h:549
char get_rel_persistence(Oid relid)
Definition: lsyscache.c:2022
RegProcedure get_typsubscript(Oid typid, Oid *typelemp)
Definition: lsyscache.c:3017
int get_func_nargs(Oid funcid)
Definition: lsyscache.c:1618
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3488
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
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:2752
char func_volatile(Oid funcid)
Definition: lsyscache.c:1724
Oid get_index_column_opclass(Oid index_oid, int attno)
Definition: lsyscache.c:3435
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:2117
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3313
FormData_pg_amop * Form_pg_amop
Definition: pg_amop.h:88
#define elog(elevel,...)
Definition: elog.h:228
int i
Oid getTypeIOParam(HeapTuple typeTuple)
Definition: lsyscache.c:2223
#define NameStr(name)
Definition: c.h:669
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:61
Oid get_constraint_index(Oid conoid)
Definition: lsyscache.c:1106
Oid get_negator(Oid opno)
Definition: lsyscache.c:1477
int32 get_attavgwidth(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:3078
#define BTLessStrategyNumber
Definition: stratnum.h:29
Oid valuetype
Definition: lsyscache.h:52
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2441
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3001
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
Definition: lsyscache.c:2630
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:1872
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1647
#define ARR_ELEMTYPE(a)
Definition: array.h:285
int16 AttrNumber
Definition: attnum.h:21
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3330
long val
Definition: informix.c:664
#define TYPECACHE_HASH_PROC
Definition: typcache.h:140
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:143
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:971
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1178
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:2245
void free_attstatsslot(AttStatsSlot *sslot)
Definition: lsyscache.c:3267