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