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