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