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