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