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