]> granicus.if.org Git - postgresql/blob - src/backend/utils/cache/lsyscache.c
Replace pg_shadow and pg_group by new role-capable catalogs pg_authid
[postgresql] / src / backend / utils / cache / lsyscache.c
1 /*-------------------------------------------------------------------------
2  *
3  * lsyscache.c
4  *        Convenience routines for common queries in the system catalog cache.
5  *
6  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.126 2005/06/28 05:09:01 tgl Exp $
11  *
12  * NOTES
13  *        Eventually, the index information should go through here, too.
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 #include "miscadmin.h"
18
19 #include "access/hash.h"
20 #include "access/tupmacs.h"
21 #include "catalog/pg_amop.h"
22 #include "catalog/pg_amproc.h"
23 #include "catalog/pg_namespace.h"
24 #include "catalog/pg_opclass.h"
25 #include "catalog/pg_operator.h"
26 #include "catalog/pg_proc.h"
27 #include "catalog/pg_statistic.h"
28 #include "catalog/pg_type.h"
29 #include "nodes/makefuncs.h"
30 #include "utils/array.h"
31 #include "utils/builtins.h"
32 #include "utils/catcache.h"
33 #include "utils/datum.h"
34 #include "utils/lsyscache.h"
35 #include "utils/syscache.h"
36
37
38 /*                              ---------- AMOP CACHES ----------                                                */
39
40 /*
41  * op_in_opclass
42  *
43  *              Return t iff operator 'opno' is in operator class 'opclass'.
44  */
45 bool
46 op_in_opclass(Oid opno, Oid opclass)
47 {
48         return SearchSysCacheExists(AMOPOPID,
49                                                                 ObjectIdGetDatum(opno),
50                                                                 ObjectIdGetDatum(opclass),
51                                                                 0, 0);
52 }
53
54 /*
55  * get_op_opclass_strategy
56  *
57  *              Get the operator's strategy number within the specified opclass,
58  *              or 0 if it's not a member of the opclass.
59  */
60 int
61 get_op_opclass_strategy(Oid opno, Oid opclass)
62 {
63         HeapTuple       tp;
64         Form_pg_amop amop_tup;
65         int                     result;
66
67         tp = SearchSysCache(AMOPOPID,
68                                                 ObjectIdGetDatum(opno),
69                                                 ObjectIdGetDatum(opclass),
70                                                 0, 0);
71         if (!HeapTupleIsValid(tp))
72                 return 0;
73         amop_tup = (Form_pg_amop) GETSTRUCT(tp);
74         result = amop_tup->amopstrategy;
75         ReleaseSysCache(tp);
76         return result;
77 }
78
79 /*
80  * get_op_opclass_properties
81  *
82  *              Get the operator's strategy number, subtype, and recheck (lossy) flag
83  *              within the specified opclass.
84  *
85  * Caller should already have verified that opno is a member of opclass,
86  * therefore we raise an error if the tuple is not found.
87  */
88 void
89 get_op_opclass_properties(Oid opno, Oid opclass,
90                                                   int *strategy, Oid *subtype, bool *recheck)
91 {
92         HeapTuple       tp;
93         Form_pg_amop amop_tup;
94
95         tp = SearchSysCache(AMOPOPID,
96                                                 ObjectIdGetDatum(opno),
97                                                 ObjectIdGetDatum(opclass),
98                                                 0, 0);
99         if (!HeapTupleIsValid(tp))
100                 elog(ERROR, "operator %u is not a member of opclass %u",
101                          opno, opclass);
102         amop_tup = (Form_pg_amop) GETSTRUCT(tp);
103         *strategy = amop_tup->amopstrategy;
104         *subtype = amop_tup->amopsubtype;
105         *recheck = amop_tup->amopreqcheck;
106         ReleaseSysCache(tp);
107 }
108
109 /*
110  * get_opclass_member
111  *              Get the OID of the operator that implements the specified strategy
112  *              with the specified subtype for the specified opclass.
113  *
114  * Returns InvalidOid if there is no pg_amop entry for the given keys.
115  */
116 Oid
117 get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
118 {
119         HeapTuple       tp;
120         Form_pg_amop amop_tup;
121         Oid                     result;
122
123         tp = SearchSysCache(AMOPSTRATEGY,
124                                                 ObjectIdGetDatum(opclass),
125                                                 ObjectIdGetDatum(subtype),
126                                                 Int16GetDatum(strategy),
127                                                 0);
128         if (!HeapTupleIsValid(tp))
129                 return InvalidOid;
130         amop_tup = (Form_pg_amop) GETSTRUCT(tp);
131         result = amop_tup->amopopr;
132         ReleaseSysCache(tp);
133         return result;
134 }
135
136 /*
137  * get_op_hash_function
138  *              Get the OID of the datatype-specific hash function associated with
139  *              a hashable equality operator.
140  *
141  * Returns InvalidOid if no hash function can be found.  (This indicates
142  * that the operator should not have been marked oprcanhash.)
143  */
144 Oid
145 get_op_hash_function(Oid opno)
146 {
147         CatCList   *catlist;
148         int                     i;
149         Oid                     opclass = InvalidOid;
150
151         /*
152          * Search pg_amop to see if the target operator is registered as the
153          * "=" operator of any hash opclass.  If the operator is registered in
154          * multiple opclasses, assume we can use the associated hash function
155          * from any one.
156          */
157         catlist = SearchSysCacheList(AMOPOPID, 1,
158                                                                  ObjectIdGetDatum(opno),
159                                                                  0, 0, 0);
160
161         for (i = 0; i < catlist->n_members; i++)
162         {
163                 HeapTuple       tuple = &catlist->members[i]->tuple;
164                 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
165
166                 if (aform->amopstrategy == HTEqualStrategyNumber &&
167                         opclass_is_hash(aform->amopclaid))
168                 {
169                         opclass = aform->amopclaid;
170                         break;
171                 }
172         }
173
174         ReleaseSysCacheList(catlist);
175
176         if (OidIsValid(opclass))
177         {
178                 /* Found a suitable opclass, get its default hash support function */
179                 return get_opclass_proc(opclass, InvalidOid, HASHPROC);
180         }
181
182         /* Didn't find a match... */
183         return InvalidOid;
184 }
185
186
187 /*                              ---------- AMPROC CACHES ----------                                              */
188
189 /*
190  * get_opclass_proc
191  *              Get the OID of the specified support function
192  *              for the specified opclass and subtype.
193  *
194  * Returns InvalidOid if there is no pg_amproc entry for the given keys.
195  */
196 Oid
197 get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
198 {
199         HeapTuple       tp;
200         Form_pg_amproc amproc_tup;
201         RegProcedure result;
202
203         tp = SearchSysCache(AMPROCNUM,
204                                                 ObjectIdGetDatum(opclass),
205                                                 ObjectIdGetDatum(subtype),
206                                                 Int16GetDatum(procnum),
207                                                 0);
208         if (!HeapTupleIsValid(tp))
209                 return InvalidOid;
210         amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
211         result = amproc_tup->amproc;
212         ReleaseSysCache(tp);
213         return result;
214 }
215
216
217 /*                              ---------- ATTRIBUTE CACHES ----------                                   */
218
219 /*
220  * get_attname
221  *              Given the relation id and the attribute number,
222  *              return the "attname" field from the attribute relation.
223  *
224  * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
225  */
226 char *
227 get_attname(Oid relid, AttrNumber attnum)
228 {
229         HeapTuple       tp;
230
231         tp = SearchSysCache(ATTNUM,
232                                                 ObjectIdGetDatum(relid),
233                                                 Int16GetDatum(attnum),
234                                                 0, 0);
235         if (HeapTupleIsValid(tp))
236         {
237                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
238                 char       *result;
239
240                 result = pstrdup(NameStr(att_tup->attname));
241                 ReleaseSysCache(tp);
242                 return result;
243         }
244         else
245                 return NULL;
246 }
247
248 /*
249  * get_relid_attribute_name
250  *
251  * Same as above routine get_attname(), except that error
252  * is handled by elog() instead of returning NULL.
253  */
254 char *
255 get_relid_attribute_name(Oid relid, AttrNumber attnum)
256 {
257         char       *attname;
258
259         attname = get_attname(relid, attnum);
260         if (attname == NULL)
261                 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
262                          attnum, relid);
263         return attname;
264 }
265
266 /*
267  * get_attnum
268  *
269  *              Given the relation id and the attribute name,
270  *              return the "attnum" field from the attribute relation.
271  *
272  *              Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
273  */
274 AttrNumber
275 get_attnum(Oid relid, const char *attname)
276 {
277         HeapTuple       tp;
278
279         tp = SearchSysCacheAttName(relid, attname);
280         if (HeapTupleIsValid(tp))
281         {
282                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
283                 AttrNumber      result;
284
285                 result = att_tup->attnum;
286                 ReleaseSysCache(tp);
287                 return result;
288         }
289         else
290                 return InvalidAttrNumber;
291 }
292
293 /*
294  * get_atttype
295  *
296  *              Given the relation OID and the attribute number with the relation,
297  *              return the attribute type OID.
298  */
299 Oid
300 get_atttype(Oid relid, AttrNumber attnum)
301 {
302         HeapTuple       tp;
303
304         tp = SearchSysCache(ATTNUM,
305                                                 ObjectIdGetDatum(relid),
306                                                 Int16GetDatum(attnum),
307                                                 0, 0);
308         if (HeapTupleIsValid(tp))
309         {
310                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
311                 Oid                     result;
312
313                 result = att_tup->atttypid;
314                 ReleaseSysCache(tp);
315                 return result;
316         }
317         else
318                 return InvalidOid;
319 }
320
321 /*
322  * get_atttypmod
323  *
324  *              Given the relation id and the attribute number,
325  *              return the "atttypmod" field from the attribute relation.
326  */
327 int32
328 get_atttypmod(Oid relid, AttrNumber attnum)
329 {
330         HeapTuple       tp;
331
332         tp = SearchSysCache(ATTNUM,
333                                                 ObjectIdGetDatum(relid),
334                                                 Int16GetDatum(attnum),
335                                                 0, 0);
336         if (HeapTupleIsValid(tp))
337         {
338                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
339                 int32           result;
340
341                 result = att_tup->atttypmod;
342                 ReleaseSysCache(tp);
343                 return result;
344         }
345         else
346                 return -1;
347 }
348
349 /*
350  * get_atttypetypmod
351  *
352  *              A two-fer: given the relation id and the attribute number,
353  *              fetch both type OID and atttypmod in a single cache lookup.
354  *
355  * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
356  * raises an error if it can't obtain the information.
357  */
358 void
359 get_atttypetypmod(Oid relid, AttrNumber attnum,
360                                   Oid *typid, int32 *typmod)
361 {
362         HeapTuple       tp;
363         Form_pg_attribute att_tup;
364
365         tp = SearchSysCache(ATTNUM,
366                                                 ObjectIdGetDatum(relid),
367                                                 Int16GetDatum(attnum),
368                                                 0, 0);
369         if (!HeapTupleIsValid(tp))
370                 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
371                          attnum, relid);
372         att_tup = (Form_pg_attribute) GETSTRUCT(tp);
373
374         *typid = att_tup->atttypid;
375         *typmod = att_tup->atttypmod;
376         ReleaseSysCache(tp);
377 }
378
379 /*                              ---------- INDEX CACHE ----------                                                */
380
381 /*              watch this space...
382  */
383
384 /*                              ---------- OPCLASS CACHE ----------                                              */
385
386 /*
387  * opclass_is_btree
388  *
389  *              Returns TRUE iff the specified opclass is associated with the
390  *              btree index access method.
391  */
392 bool
393 opclass_is_btree(Oid opclass)
394 {
395         HeapTuple       tp;
396         Form_pg_opclass cla_tup;
397         bool            result;
398
399         tp = SearchSysCache(CLAOID,
400                                                 ObjectIdGetDatum(opclass),
401                                                 0, 0, 0);
402         if (!HeapTupleIsValid(tp))
403                 elog(ERROR, "cache lookup failed for opclass %u", opclass);
404         cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
405
406         result = (cla_tup->opcamid == BTREE_AM_OID);
407         ReleaseSysCache(tp);
408         return result;
409 }
410
411 /*
412  * opclass_is_hash
413  *
414  *              Returns TRUE iff the specified opclass is associated with the
415  *              hash index access method.
416  */
417 bool
418 opclass_is_hash(Oid opclass)
419 {
420         HeapTuple       tp;
421         Form_pg_opclass cla_tup;
422         bool            result;
423
424         tp = SearchSysCache(CLAOID,
425                                                 ObjectIdGetDatum(opclass),
426                                                 0, 0, 0);
427         if (!HeapTupleIsValid(tp))
428                 elog(ERROR, "cache lookup failed for opclass %u", opclass);
429         cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
430
431         result = (cla_tup->opcamid == HASH_AM_OID);
432         ReleaseSysCache(tp);
433         return result;
434 }
435
436 /*                              ---------- OPERATOR CACHE ----------                                     */
437
438 /*
439  * get_opcode
440  *
441  *              Returns the regproc id of the routine used to implement an
442  *              operator given the operator oid.
443  */
444 RegProcedure
445 get_opcode(Oid opno)
446 {
447         HeapTuple       tp;
448
449         tp = SearchSysCache(OPEROID,
450                                                 ObjectIdGetDatum(opno),
451                                                 0, 0, 0);
452         if (HeapTupleIsValid(tp))
453         {
454                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
455                 RegProcedure result;
456
457                 result = optup->oprcode;
458                 ReleaseSysCache(tp);
459                 return result;
460         }
461         else
462                 return (RegProcedure) InvalidOid;
463 }
464
465 /*
466  * get_opname
467  *        returns the name of the operator with the given opno
468  *
469  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
470  */
471 char *
472 get_opname(Oid opno)
473 {
474         HeapTuple       tp;
475
476         tp = SearchSysCache(OPEROID,
477                                                 ObjectIdGetDatum(opno),
478                                                 0, 0, 0);
479         if (HeapTupleIsValid(tp))
480         {
481                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
482                 char       *result;
483
484                 result = pstrdup(NameStr(optup->oprname));
485                 ReleaseSysCache(tp);
486                 return result;
487         }
488         else
489                 return NULL;
490 }
491
492 /*
493  * op_input_types
494  *
495  *              Returns the left and right input datatypes for an operator
496  *              (InvalidOid if not relevant).
497  */
498 void
499 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
500 {
501         HeapTuple       tp;
502         Form_pg_operator optup;
503
504         tp = SearchSysCache(OPEROID,
505                                                 ObjectIdGetDatum(opno),
506                                                 0, 0, 0);
507         if (!HeapTupleIsValid(tp))      /* shouldn't happen */
508                 elog(ERROR, "cache lookup failed for operator %u", opno);
509         optup = (Form_pg_operator) GETSTRUCT(tp);
510         *lefttype = optup->oprleft;
511         *righttype = optup->oprright;
512         ReleaseSysCache(tp);
513 }
514
515 /*
516  * op_mergejoinable
517  *
518  *              Returns the left and right sort operators corresponding to a
519  *              mergejoinable operator, or false if the operator is not mergejoinable.
520  */
521 bool
522 op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
523 {
524         HeapTuple       tp;
525         bool            result = false;
526
527         tp = SearchSysCache(OPEROID,
528                                                 ObjectIdGetDatum(opno),
529                                                 0, 0, 0);
530         if (HeapTupleIsValid(tp))
531         {
532                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
533
534                 if (optup->oprlsortop &&
535                         optup->oprrsortop)
536                 {
537                         *leftOp = optup->oprlsortop;
538                         *rightOp = optup->oprrsortop;
539                         result = true;
540                 }
541                 ReleaseSysCache(tp);
542         }
543         return result;
544 }
545
546 /*
547  * op_mergejoin_crossops
548  *
549  *              Returns the cross-type comparison operators (ltype "<" rtype and
550  *              ltype ">" rtype) for an operator previously determined to be
551  *              mergejoinable.  Optionally, fetches the regproc ids of these
552  *              operators, as well as their operator OIDs.
553  */
554 void
555 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
556                                           RegProcedure *ltproc, RegProcedure *gtproc)
557 {
558         HeapTuple       tp;
559         Form_pg_operator optup;
560
561         /*
562          * Get the declared comparison operators of the operator.
563          */
564         tp = SearchSysCache(OPEROID,
565                                                 ObjectIdGetDatum(opno),
566                                                 0, 0, 0);
567         if (!HeapTupleIsValid(tp))      /* shouldn't happen */
568                 elog(ERROR, "cache lookup failed for operator %u", opno);
569         optup = (Form_pg_operator) GETSTRUCT(tp);
570         *ltop = optup->oprltcmpop;
571         *gtop = optup->oprgtcmpop;
572         ReleaseSysCache(tp);
573
574         /* Check < op provided */
575         if (!OidIsValid(*ltop))
576                 elog(ERROR, "mergejoin operator %u has no matching < operator",
577                          opno);
578         if (ltproc)
579                 *ltproc = get_opcode(*ltop);
580
581         /* Check > op provided */
582         if (!OidIsValid(*gtop))
583                 elog(ERROR, "mergejoin operator %u has no matching > operator",
584                          opno);
585         if (gtproc)
586                 *gtproc = get_opcode(*gtop);
587 }
588
589 /*
590  * op_hashjoinable
591  *
592  * Returns true if the operator is hashjoinable.
593  */
594 bool
595 op_hashjoinable(Oid opno)
596 {
597         HeapTuple       tp;
598         bool            result = false;
599
600         tp = SearchSysCache(OPEROID,
601                                                 ObjectIdGetDatum(opno),
602                                                 0, 0, 0);
603         if (HeapTupleIsValid(tp))
604         {
605                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
606
607                 result = optup->oprcanhash;
608                 ReleaseSysCache(tp);
609         }
610         return result;
611 }
612
613 /*
614  * op_strict
615  *
616  * Get the proisstrict flag for the operator's underlying function.
617  */
618 bool
619 op_strict(Oid opno)
620 {
621         RegProcedure funcid = get_opcode(opno);
622
623         if (funcid == (RegProcedure) InvalidOid)
624                 elog(ERROR, "operator %u does not exist", opno);
625
626         return func_strict((Oid) funcid);
627 }
628
629 /*
630  * op_volatile
631  *
632  * Get the provolatile flag for the operator's underlying function.
633  */
634 char
635 op_volatile(Oid opno)
636 {
637         RegProcedure funcid = get_opcode(opno);
638
639         if (funcid == (RegProcedure) InvalidOid)
640                 elog(ERROR, "operator %u does not exist", opno);
641
642         return func_volatile((Oid) funcid);
643 }
644
645 /*
646  * get_commutator
647  *
648  *              Returns the corresponding commutator of an operator.
649  */
650 Oid
651 get_commutator(Oid opno)
652 {
653         HeapTuple       tp;
654
655         tp = SearchSysCache(OPEROID,
656                                                 ObjectIdGetDatum(opno),
657                                                 0, 0, 0);
658         if (HeapTupleIsValid(tp))
659         {
660                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
661                 Oid                     result;
662
663                 result = optup->oprcom;
664                 ReleaseSysCache(tp);
665                 return result;
666         }
667         else
668                 return InvalidOid;
669 }
670
671 /*
672  * get_negator
673  *
674  *              Returns the corresponding negator of an operator.
675  */
676 Oid
677 get_negator(Oid opno)
678 {
679         HeapTuple       tp;
680
681         tp = SearchSysCache(OPEROID,
682                                                 ObjectIdGetDatum(opno),
683                                                 0, 0, 0);
684         if (HeapTupleIsValid(tp))
685         {
686                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
687                 Oid                     result;
688
689                 result = optup->oprnegate;
690                 ReleaseSysCache(tp);
691                 return result;
692         }
693         else
694                 return InvalidOid;
695 }
696
697 /*
698  * get_oprrest
699  *
700  *              Returns procedure id for computing selectivity of an operator.
701  */
702 RegProcedure
703 get_oprrest(Oid opno)
704 {
705         HeapTuple       tp;
706
707         tp = SearchSysCache(OPEROID,
708                                                 ObjectIdGetDatum(opno),
709                                                 0, 0, 0);
710         if (HeapTupleIsValid(tp))
711         {
712                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
713                 RegProcedure result;
714
715                 result = optup->oprrest;
716                 ReleaseSysCache(tp);
717                 return result;
718         }
719         else
720                 return (RegProcedure) InvalidOid;
721 }
722
723 /*
724  * get_oprjoin
725  *
726  *              Returns procedure id for computing selectivity of a join.
727  */
728 RegProcedure
729 get_oprjoin(Oid opno)
730 {
731         HeapTuple       tp;
732
733         tp = SearchSysCache(OPEROID,
734                                                 ObjectIdGetDatum(opno),
735                                                 0, 0, 0);
736         if (HeapTupleIsValid(tp))
737         {
738                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
739                 RegProcedure result;
740
741                 result = optup->oprjoin;
742                 ReleaseSysCache(tp);
743                 return result;
744         }
745         else
746                 return (RegProcedure) InvalidOid;
747 }
748
749 /*                              ---------- FUNCTION CACHE ----------                                     */
750
751 /*
752  * get_func_name
753  *        returns the name of the function with the given funcid
754  *
755  * Note: returns a palloc'd copy of the string, or NULL if no such function.
756  */
757 char *
758 get_func_name(Oid funcid)
759 {
760         HeapTuple       tp;
761
762         tp = SearchSysCache(PROCOID,
763                                                 ObjectIdGetDatum(funcid),
764                                                 0, 0, 0);
765         if (HeapTupleIsValid(tp))
766         {
767                 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
768                 char       *result;
769
770                 result = pstrdup(NameStr(functup->proname));
771                 ReleaseSysCache(tp);
772                 return result;
773         }
774         else
775                 return NULL;
776 }
777
778 /*
779  * get_func_rettype
780  *              Given procedure id, return the function's result type.
781  */
782 Oid
783 get_func_rettype(Oid funcid)
784 {
785         HeapTuple       tp;
786         Oid                     result;
787
788         tp = SearchSysCache(PROCOID,
789                                                 ObjectIdGetDatum(funcid),
790                                                 0, 0, 0);
791         if (!HeapTupleIsValid(tp))
792                 elog(ERROR, "cache lookup failed for function %u", funcid);
793
794         result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
795         ReleaseSysCache(tp);
796         return result;
797 }
798
799 /*
800  * get_func_nargs
801  *              Given procedure id, return the number of arguments.
802  */
803 int
804 get_func_nargs(Oid funcid)
805 {
806         HeapTuple       tp;
807         int                     result;
808
809         tp = SearchSysCache(PROCOID,
810                                                 ObjectIdGetDatum(funcid),
811                                                 0, 0, 0);
812         if (!HeapTupleIsValid(tp))
813                 elog(ERROR, "cache lookup failed for function %u", funcid);
814
815         result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
816         ReleaseSysCache(tp);
817         return result;
818 }
819
820 /*
821  * get_func_signature
822  *              Given procedure id, return the function's argument and result types.
823  *              (The return value is the result type.)
824  *
825  * The arguments are returned as a palloc'd array.
826  */
827 Oid
828 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
829 {
830         HeapTuple       tp;
831         Form_pg_proc procstruct;
832         Oid                     result;
833
834         tp = SearchSysCache(PROCOID,
835                                                 ObjectIdGetDatum(funcid),
836                                                 0, 0, 0);
837         if (!HeapTupleIsValid(tp))
838                 elog(ERROR, "cache lookup failed for function %u", funcid);
839
840         procstruct = (Form_pg_proc) GETSTRUCT(tp);
841
842         result = procstruct->prorettype;
843         *nargs = (int) procstruct->pronargs;
844         Assert(*nargs == procstruct->proargtypes.dim1);
845         *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
846         memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
847
848         ReleaseSysCache(tp);
849         return result;
850 }
851
852 /*
853  * get_func_retset
854  *              Given procedure id, return the function's proretset flag.
855  */
856 bool
857 get_func_retset(Oid funcid)
858 {
859         HeapTuple       tp;
860         bool            result;
861
862         tp = SearchSysCache(PROCOID,
863                                                 ObjectIdGetDatum(funcid),
864                                                 0, 0, 0);
865         if (!HeapTupleIsValid(tp))
866                 elog(ERROR, "cache lookup failed for function %u", funcid);
867
868         result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
869         ReleaseSysCache(tp);
870         return result;
871 }
872
873 /*
874  * func_strict
875  *              Given procedure id, return the function's proisstrict flag.
876  */
877 bool
878 func_strict(Oid funcid)
879 {
880         HeapTuple       tp;
881         bool            result;
882
883         tp = SearchSysCache(PROCOID,
884                                                 ObjectIdGetDatum(funcid),
885                                                 0, 0, 0);
886         if (!HeapTupleIsValid(tp))
887                 elog(ERROR, "cache lookup failed for function %u", funcid);
888
889         result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
890         ReleaseSysCache(tp);
891         return result;
892 }
893
894 /*
895  * func_volatile
896  *              Given procedure id, return the function's provolatile flag.
897  */
898 char
899 func_volatile(Oid funcid)
900 {
901         HeapTuple       tp;
902         char            result;
903
904         tp = SearchSysCache(PROCOID,
905                                                 ObjectIdGetDatum(funcid),
906                                                 0, 0, 0);
907         if (!HeapTupleIsValid(tp))
908                 elog(ERROR, "cache lookup failed for function %u", funcid);
909
910         result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
911         ReleaseSysCache(tp);
912         return result;
913 }
914
915 /*                              ---------- RELATION CACHE ----------                                     */
916
917 /*
918  * get_relname_relid
919  *              Given name and namespace of a relation, look up the OID.
920  *
921  * Returns InvalidOid if there is no such relation.
922  */
923 Oid
924 get_relname_relid(const char *relname, Oid relnamespace)
925 {
926         return GetSysCacheOid(RELNAMENSP,
927                                                   PointerGetDatum(relname),
928                                                   ObjectIdGetDatum(relnamespace),
929                                                   0, 0);
930 }
931
932 #ifdef NOT_USED
933 /*
934  * get_relnatts
935  *
936  *              Returns the number of attributes for a given relation.
937  */
938 int
939 get_relnatts(Oid relid)
940 {
941         HeapTuple       tp;
942
943         tp = SearchSysCache(RELOID,
944                                                 ObjectIdGetDatum(relid),
945                                                 0, 0, 0);
946         if (HeapTupleIsValid(tp))
947         {
948                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
949                 int                     result;
950
951                 result = reltup->relnatts;
952                 ReleaseSysCache(tp);
953                 return result;
954         }
955         else
956                 return InvalidAttrNumber;
957 }
958 #endif
959
960 /*
961  * get_rel_name
962  *              Returns the name of a given relation.
963  *
964  * Returns a palloc'd copy of the string, or NULL if no such relation.
965  *
966  * NOTE: since relation name is not unique, be wary of code that uses this
967  * for anything except preparing error messages.
968  */
969 char *
970 get_rel_name(Oid relid)
971 {
972         HeapTuple       tp;
973
974         tp = SearchSysCache(RELOID,
975                                                 ObjectIdGetDatum(relid),
976                                                 0, 0, 0);
977         if (HeapTupleIsValid(tp))
978         {
979                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
980                 char       *result;
981
982                 result = pstrdup(NameStr(reltup->relname));
983                 ReleaseSysCache(tp);
984                 return result;
985         }
986         else
987                 return NULL;
988 }
989
990 /*
991  * get_rel_namespace
992  *
993  *              Returns the pg_namespace OID associated with a given relation.
994  */
995 Oid
996 get_rel_namespace(Oid relid)
997 {
998         HeapTuple       tp;
999
1000         tp = SearchSysCache(RELOID,
1001                                                 ObjectIdGetDatum(relid),
1002                                                 0, 0, 0);
1003         if (HeapTupleIsValid(tp))
1004         {
1005                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1006                 Oid                     result;
1007
1008                 result = reltup->relnamespace;
1009                 ReleaseSysCache(tp);
1010                 return result;
1011         }
1012         else
1013                 return InvalidOid;
1014 }
1015
1016 /*
1017  * get_rel_type_id
1018  *
1019  *              Returns the pg_type OID associated with a given relation.
1020  *
1021  * Note: not all pg_class entries have associated pg_type OIDs; so be
1022  * careful to check for InvalidOid result.
1023  */
1024 Oid
1025 get_rel_type_id(Oid relid)
1026 {
1027         HeapTuple       tp;
1028
1029         tp = SearchSysCache(RELOID,
1030                                                 ObjectIdGetDatum(relid),
1031                                                 0, 0, 0);
1032         if (HeapTupleIsValid(tp))
1033         {
1034                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1035                 Oid                     result;
1036
1037                 result = reltup->reltype;
1038                 ReleaseSysCache(tp);
1039                 return result;
1040         }
1041         else
1042                 return InvalidOid;
1043 }
1044
1045 /*
1046  * get_rel_relkind
1047  *
1048  *              Returns the relkind associated with a given relation.
1049  */
1050 char
1051 get_rel_relkind(Oid relid)
1052 {
1053         HeapTuple       tp;
1054
1055         tp = SearchSysCache(RELOID,
1056                                                 ObjectIdGetDatum(relid),
1057                                                 0, 0, 0);
1058         if (HeapTupleIsValid(tp))
1059         {
1060                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1061                 char            result;
1062
1063                 result = reltup->relkind;
1064                 ReleaseSysCache(tp);
1065                 return result;
1066         }
1067         else
1068                 return '\0';
1069 }
1070
1071
1072 /*                              ---------- TYPE CACHE ----------                                                 */
1073
1074 /*
1075  * get_typisdefined
1076  *
1077  *              Given the type OID, determine whether the type is defined
1078  *              (if not, it's only a shell).
1079  */
1080 bool
1081 get_typisdefined(Oid typid)
1082 {
1083         HeapTuple       tp;
1084
1085         tp = SearchSysCache(TYPEOID,
1086                                                 ObjectIdGetDatum(typid),
1087                                                 0, 0, 0);
1088         if (HeapTupleIsValid(tp))
1089         {
1090                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1091                 bool            result;
1092
1093                 result = typtup->typisdefined;
1094                 ReleaseSysCache(tp);
1095                 return result;
1096         }
1097         else
1098                 return false;
1099 }
1100
1101 /*
1102  * get_typlen
1103  *
1104  *              Given the type OID, return the length of the type.
1105  */
1106 int16
1107 get_typlen(Oid typid)
1108 {
1109         HeapTuple       tp;
1110
1111         tp = SearchSysCache(TYPEOID,
1112                                                 ObjectIdGetDatum(typid),
1113                                                 0, 0, 0);
1114         if (HeapTupleIsValid(tp))
1115         {
1116                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1117                 int16           result;
1118
1119                 result = typtup->typlen;
1120                 ReleaseSysCache(tp);
1121                 return result;
1122         }
1123         else
1124                 return 0;
1125 }
1126
1127 /*
1128  * get_typbyval
1129  *
1130  *              Given the type OID, determine whether the type is returned by value or
1131  *              not.  Returns true if by value, false if by reference.
1132  */
1133 bool
1134 get_typbyval(Oid typid)
1135 {
1136         HeapTuple       tp;
1137
1138         tp = SearchSysCache(TYPEOID,
1139                                                 ObjectIdGetDatum(typid),
1140                                                 0, 0, 0);
1141         if (HeapTupleIsValid(tp))
1142         {
1143                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1144                 bool            result;
1145
1146                 result = typtup->typbyval;
1147                 ReleaseSysCache(tp);
1148                 return result;
1149         }
1150         else
1151                 return false;
1152 }
1153
1154 /*
1155  * get_typlenbyval
1156  *
1157  *              A two-fer: given the type OID, return both typlen and typbyval.
1158  *
1159  *              Since both pieces of info are needed to know how to copy a Datum,
1160  *              many places need both.  Might as well get them with one cache lookup
1161  *              instead of two.  Also, this routine raises an error instead of
1162  *              returning a bogus value when given a bad type OID.
1163  */
1164 void
1165 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1166 {
1167         HeapTuple       tp;
1168         Form_pg_type typtup;
1169
1170         tp = SearchSysCache(TYPEOID,
1171                                                 ObjectIdGetDatum(typid),
1172                                                 0, 0, 0);
1173         if (!HeapTupleIsValid(tp))
1174                 elog(ERROR, "cache lookup failed for type %u", typid);
1175         typtup = (Form_pg_type) GETSTRUCT(tp);
1176         *typlen = typtup->typlen;
1177         *typbyval = typtup->typbyval;
1178         ReleaseSysCache(tp);
1179 }
1180
1181 /*
1182  * get_typlenbyvalalign
1183  *
1184  *              A three-fer: given the type OID, return typlen, typbyval, typalign.
1185  */
1186 void
1187 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1188                                          char *typalign)
1189 {
1190         HeapTuple       tp;
1191         Form_pg_type typtup;
1192
1193         tp = SearchSysCache(TYPEOID,
1194                                                 ObjectIdGetDatum(typid),
1195                                                 0, 0, 0);
1196         if (!HeapTupleIsValid(tp))
1197                 elog(ERROR, "cache lookup failed for type %u", typid);
1198         typtup = (Form_pg_type) GETSTRUCT(tp);
1199         *typlen = typtup->typlen;
1200         *typbyval = typtup->typbyval;
1201         *typalign = typtup->typalign;
1202         ReleaseSysCache(tp);
1203 }
1204
1205 /*
1206  * getTypeIOParam
1207  *              Given a pg_type row, select the type OID to pass to I/O functions
1208  *
1209  * Formerly, all I/O functions were passed pg_type.typelem as their second
1210  * parameter, but we now have a more complex rule about what to pass.
1211  * This knowledge is intended to be centralized here --- direct references
1212  * to typelem elsewhere in the code are wrong, if they are associated with
1213  * I/O calls and not with actual subscripting operations!  (But see
1214  * bootstrap.c, which can't conveniently use this routine.)
1215  *
1216  * As of PostgreSQL 8.1, output functions receive only the value itself
1217  * and not any auxiliary parameters, so the name of this routine is now
1218  * a bit of a misnomer ... it should be getTypeInputParam.
1219  */
1220 Oid
1221 getTypeIOParam(HeapTuple typeTuple)
1222 {
1223         Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1224
1225         /*
1226          * Composite types get their own OID as parameter; array types get
1227          * their typelem as parameter; everybody else gets zero.
1228          */
1229         if (typeStruct->typtype == 'c')
1230                 return HeapTupleGetOid(typeTuple);
1231         else
1232                 return typeStruct->typelem;
1233 }
1234
1235 /*
1236  * get_type_io_data
1237  *
1238  *              A six-fer:      given the type OID, return typlen, typbyval, typalign,
1239  *                                      typdelim, typioparam, and IO function OID. The IO function
1240  *                                      returned is controlled by IOFuncSelector
1241  */
1242 void
1243 get_type_io_data(Oid typid,
1244                                  IOFuncSelector which_func,
1245                                  int16 *typlen,
1246                                  bool *typbyval,
1247                                  char *typalign,
1248                                  char *typdelim,
1249                                  Oid *typioparam,
1250                                  Oid *func)
1251 {
1252         HeapTuple       typeTuple;
1253         Form_pg_type typeStruct;
1254
1255         typeTuple = SearchSysCache(TYPEOID,
1256                                                            ObjectIdGetDatum(typid),
1257                                                            0, 0, 0);
1258         if (!HeapTupleIsValid(typeTuple))
1259                 elog(ERROR, "cache lookup failed for type %u", typid);
1260         typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1261
1262         *typlen = typeStruct->typlen;
1263         *typbyval = typeStruct->typbyval;
1264         *typalign = typeStruct->typalign;
1265         *typdelim = typeStruct->typdelim;
1266         *typioparam = getTypeIOParam(typeTuple);
1267         switch (which_func)
1268         {
1269                 case IOFunc_input:
1270                         *func = typeStruct->typinput;
1271                         break;
1272                 case IOFunc_output:
1273                         *func = typeStruct->typoutput;
1274                         break;
1275                 case IOFunc_receive:
1276                         *func = typeStruct->typreceive;
1277                         break;
1278                 case IOFunc_send:
1279                         *func = typeStruct->typsend;
1280                         break;
1281         }
1282         ReleaseSysCache(typeTuple);
1283 }
1284
1285 #ifdef NOT_USED
1286 char
1287 get_typalign(Oid typid)
1288 {
1289         HeapTuple       tp;
1290
1291         tp = SearchSysCache(TYPEOID,
1292                                                 ObjectIdGetDatum(typid),
1293                                                 0, 0, 0);
1294         if (HeapTupleIsValid(tp))
1295         {
1296                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1297                 char            result;
1298
1299                 result = typtup->typalign;
1300                 ReleaseSysCache(tp);
1301                 return result;
1302         }
1303         else
1304                 return 'i';
1305 }
1306 #endif
1307
1308 char
1309 get_typstorage(Oid typid)
1310 {
1311         HeapTuple       tp;
1312
1313         tp = SearchSysCache(TYPEOID,
1314                                                 ObjectIdGetDatum(typid),
1315                                                 0, 0, 0);
1316         if (HeapTupleIsValid(tp))
1317         {
1318                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1319                 char            result;
1320
1321                 result = typtup->typstorage;
1322                 ReleaseSysCache(tp);
1323                 return result;
1324         }
1325         else
1326                 return 'p';
1327 }
1328
1329 /*
1330  * get_typtypmod
1331  *
1332  *              Given the type OID, return the typtypmod field (domain's typmod
1333  *              for base type)
1334  */
1335 int32
1336 get_typtypmod(Oid typid)
1337 {
1338         HeapTuple       tp;
1339
1340         tp = SearchSysCache(TYPEOID,
1341                                                 ObjectIdGetDatum(typid),
1342                                                 0, 0, 0);
1343         if (HeapTupleIsValid(tp))
1344         {
1345                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1346                 int32           result;
1347
1348                 result = typtup->typtypmod;
1349                 ReleaseSysCache(tp);
1350                 return result;
1351         }
1352         else
1353                 return -1;
1354 }
1355
1356 /*
1357  * get_typdefault
1358  *        Given a type OID, return the type's default value, if any.
1359  *
1360  *        The result is a palloc'd expression node tree, or NULL if there
1361  *        is no defined default for the datatype.
1362  *
1363  * NB: caller should be prepared to coerce result to correct datatype;
1364  * the returned expression tree might produce something of the wrong type.
1365  */
1366 Node *
1367 get_typdefault(Oid typid)
1368 {
1369         HeapTuple       typeTuple;
1370         Form_pg_type type;
1371         Datum           datum;
1372         bool            isNull;
1373         Node       *expr;
1374
1375         typeTuple = SearchSysCache(TYPEOID,
1376                                                            ObjectIdGetDatum(typid),
1377                                                            0, 0, 0);
1378         if (!HeapTupleIsValid(typeTuple))
1379                 elog(ERROR, "cache lookup failed for type %u", typid);
1380         type = (Form_pg_type) GETSTRUCT(typeTuple);
1381
1382         /*
1383          * typdefault and typdefaultbin are potentially null, so don't try to
1384          * access 'em as struct fields. Must do it the hard way with
1385          * SysCacheGetAttr.
1386          */
1387         datum = SysCacheGetAttr(TYPEOID,
1388                                                         typeTuple,
1389                                                         Anum_pg_type_typdefaultbin,
1390                                                         &isNull);
1391
1392         if (!isNull)
1393         {
1394                 /* We have an expression default */
1395                 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
1396                                                                                                                                 datum)));
1397         }
1398         else
1399         {
1400                 /* Perhaps we have a plain literal default */
1401                 datum = SysCacheGetAttr(TYPEOID,
1402                                                                 typeTuple,
1403                                                                 Anum_pg_type_typdefault,
1404                                                                 &isNull);
1405
1406                 if (!isNull)
1407                 {
1408                         char       *strDefaultVal;
1409
1410                         /* Convert text datum to C string */
1411                         strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
1412                                                                                                                                 datum));
1413                         /* Convert C string to a value of the given type */
1414                         datum = OidFunctionCall3(type->typinput,
1415                                                                          CStringGetDatum(strDefaultVal),
1416                                                          ObjectIdGetDatum(getTypeIOParam(typeTuple)),
1417                                                                          Int32GetDatum(-1));
1418                         /* Build a Const node containing the value */
1419                         expr = (Node *) makeConst(typid,
1420                                                                           type->typlen,
1421                                                                           datum,
1422                                                                           false,
1423                                                                           type->typbyval);
1424                         pfree(strDefaultVal);
1425                 }
1426                 else
1427                 {
1428                         /* No default */
1429                         expr = NULL;
1430                 }
1431         }
1432
1433         ReleaseSysCache(typeTuple);
1434
1435         return expr;
1436 }
1437
1438 /*
1439  * getBaseType
1440  *              If the given type is a domain, return its base type;
1441  *              otherwise return the type's own OID.
1442  */
1443 Oid
1444 getBaseType(Oid typid)
1445 {
1446         /*
1447          * We loop to find the bottom base type in a stack of domains.
1448          */
1449         for (;;)
1450         {
1451                 HeapTuple       tup;
1452                 Form_pg_type typTup;
1453
1454                 tup = SearchSysCache(TYPEOID,
1455                                                          ObjectIdGetDatum(typid),
1456                                                          0, 0, 0);
1457                 if (!HeapTupleIsValid(tup))
1458                         elog(ERROR, "cache lookup failed for type %u", typid);
1459                 typTup = (Form_pg_type) GETSTRUCT(tup);
1460                 if (typTup->typtype != 'd')
1461                 {
1462                         /* Not a domain, so done */
1463                         ReleaseSysCache(tup);
1464                         break;
1465                 }
1466
1467                 typid = typTup->typbasetype;
1468                 ReleaseSysCache(tup);
1469         }
1470
1471         return typid;
1472 }
1473
1474 /*
1475  * get_typavgwidth
1476  *
1477  *        Given a type OID and a typmod value (pass -1 if typmod is unknown),
1478  *        estimate the average width of values of the type.  This is used by
1479  *        the planner, which doesn't require absolutely correct results;
1480  *        it's OK (and expected) to guess if we don't know for sure.
1481  */
1482 int32
1483 get_typavgwidth(Oid typid, int32 typmod)
1484 {
1485         int                     typlen = get_typlen(typid);
1486         int32           maxwidth;
1487
1488         /*
1489          * Easy if it's a fixed-width type
1490          */
1491         if (typlen > 0)
1492                 return typlen;
1493
1494         /*
1495          * type_maximum_size knows the encoding of typmod for some datatypes;
1496          * don't duplicate that knowledge here.
1497          */
1498         maxwidth = type_maximum_size(typid, typmod);
1499         if (maxwidth > 0)
1500         {
1501                 /*
1502                  * For BPCHAR, the max width is also the only width.  Otherwise we
1503                  * need to guess about the typical data width given the max. A
1504                  * sliding scale for percentage of max width seems reasonable.
1505                  */
1506                 if (typid == BPCHAROID)
1507                         return maxwidth;
1508                 if (maxwidth <= 32)
1509                         return maxwidth;        /* assume full width */
1510                 if (maxwidth < 1000)
1511                         return 32 + (maxwidth - 32) / 2;        /* assume 50% */
1512
1513                 /*
1514                  * Beyond 1000, assume we're looking at something like
1515                  * "varchar(10000)" where the limit isn't actually reached often,
1516                  * and use a fixed estimate.
1517                  */
1518                 return 32 + (1000 - 32) / 2;
1519         }
1520
1521         /*
1522          * Ooops, we have no idea ... wild guess time.
1523          */
1524         return 32;
1525 }
1526
1527 /*
1528  * get_typtype
1529  *
1530  *              Given the type OID, find if it is a basic type, a complex type, etc.
1531  *              It returns the null char if the cache lookup fails...
1532  */
1533 char
1534 get_typtype(Oid typid)
1535 {
1536         HeapTuple       tp;
1537
1538         tp = SearchSysCache(TYPEOID,
1539                                                 ObjectIdGetDatum(typid),
1540                                                 0, 0, 0);
1541         if (HeapTupleIsValid(tp))
1542         {
1543                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1544                 char            result;
1545
1546                 result = typtup->typtype;
1547                 ReleaseSysCache(tp);
1548                 return result;
1549         }
1550         else
1551                 return '\0';
1552 }
1553
1554 /*
1555  * get_typ_typrelid
1556  *
1557  *              Given the type OID, get the typrelid (InvalidOid if not a complex
1558  *              type).
1559  */
1560 Oid
1561 get_typ_typrelid(Oid typid)
1562 {
1563         HeapTuple       tp;
1564
1565         tp = SearchSysCache(TYPEOID,
1566                                                 ObjectIdGetDatum(typid),
1567                                                 0, 0, 0);
1568         if (HeapTupleIsValid(tp))
1569         {
1570                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1571                 Oid                     result;
1572
1573                 result = typtup->typrelid;
1574                 ReleaseSysCache(tp);
1575                 return result;
1576         }
1577         else
1578                 return InvalidOid;
1579 }
1580
1581 /*
1582  * get_element_type
1583  *
1584  *              Given the type OID, get the typelem (InvalidOid if not an array type).
1585  *
1586  * NB: this only considers varlena arrays to be true arrays; InvalidOid is
1587  * returned if the input is a fixed-length array type.
1588  */
1589 Oid
1590 get_element_type(Oid typid)
1591 {
1592         HeapTuple       tp;
1593
1594         tp = SearchSysCache(TYPEOID,
1595                                                 ObjectIdGetDatum(typid),
1596                                                 0, 0, 0);
1597         if (HeapTupleIsValid(tp))
1598         {
1599                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1600                 Oid                     result;
1601
1602                 if (typtup->typlen == -1)
1603                         result = typtup->typelem;
1604                 else
1605                         result = InvalidOid;
1606                 ReleaseSysCache(tp);
1607                 return result;
1608         }
1609         else
1610                 return InvalidOid;
1611 }
1612
1613 /*
1614  * get_array_type
1615  *
1616  *              Given the type OID, get the corresponding array type.
1617  *              Returns InvalidOid if no array type can be found.
1618  *
1619  * NB: this only considers varlena arrays to be true arrays.
1620  */
1621 Oid
1622 get_array_type(Oid typid)
1623 {
1624         HeapTuple       tp;
1625
1626         tp = SearchSysCache(TYPEOID,
1627                                                 ObjectIdGetDatum(typid),
1628                                                 0, 0, 0);
1629         if (HeapTupleIsValid(tp))
1630         {
1631                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1632                 char       *array_typename;
1633                 Oid                     namespaceId;
1634
1635                 array_typename = makeArrayTypeName(NameStr(typtup->typname));
1636                 namespaceId = typtup->typnamespace;
1637                 ReleaseSysCache(tp);
1638
1639                 tp = SearchSysCache(TYPENAMENSP,
1640                                                         PointerGetDatum(array_typename),
1641                                                         ObjectIdGetDatum(namespaceId),
1642                                                         0, 0);
1643
1644                 pfree(array_typename);
1645
1646                 if (HeapTupleIsValid(tp))
1647                 {
1648                         Oid                     result;
1649
1650                         typtup = (Form_pg_type) GETSTRUCT(tp);
1651                         if (typtup->typlen == -1 && typtup->typelem == typid)
1652                                 result = HeapTupleGetOid(tp);
1653                         else
1654                                 result = InvalidOid;
1655                         ReleaseSysCache(tp);
1656                         return result;
1657                 }
1658         }
1659         return InvalidOid;
1660 }
1661
1662 /*
1663  * getTypeInputInfo
1664  *
1665  *              Get info needed for converting values of a type to internal form
1666  */
1667 void
1668 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
1669 {
1670         HeapTuple       typeTuple;
1671         Form_pg_type pt;
1672
1673         typeTuple = SearchSysCache(TYPEOID,
1674                                                            ObjectIdGetDatum(type),
1675                                                            0, 0, 0);
1676         if (!HeapTupleIsValid(typeTuple))
1677                 elog(ERROR, "cache lookup failed for type %u", type);
1678         pt = (Form_pg_type) GETSTRUCT(typeTuple);
1679
1680         if (!pt->typisdefined)
1681                 ereport(ERROR,
1682                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1683                                  errmsg("type %s is only a shell",
1684                                                 format_type_be(type))));
1685         if (!OidIsValid(pt->typinput))
1686                 ereport(ERROR,
1687                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1688                                  errmsg("no input function available for type %s",
1689                                                 format_type_be(type))));
1690
1691         *typInput = pt->typinput;
1692         *typIOParam = getTypeIOParam(typeTuple);
1693
1694         ReleaseSysCache(typeTuple);
1695 }
1696
1697 /*
1698  * getTypeOutputInfo
1699  *
1700  *              Get info needed for printing values of a type
1701  */
1702 void
1703 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
1704 {
1705         HeapTuple       typeTuple;
1706         Form_pg_type pt;
1707
1708         typeTuple = SearchSysCache(TYPEOID,
1709                                                            ObjectIdGetDatum(type),
1710                                                            0, 0, 0);
1711         if (!HeapTupleIsValid(typeTuple))
1712                 elog(ERROR, "cache lookup failed for type %u", type);
1713         pt = (Form_pg_type) GETSTRUCT(typeTuple);
1714
1715         if (!pt->typisdefined)
1716                 ereport(ERROR,
1717                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1718                                  errmsg("type %s is only a shell",
1719                                                 format_type_be(type))));
1720         if (!OidIsValid(pt->typoutput))
1721                 ereport(ERROR,
1722                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1723                                  errmsg("no output function available for type %s",
1724                                                 format_type_be(type))));
1725
1726         *typOutput = pt->typoutput;
1727         *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1728
1729         ReleaseSysCache(typeTuple);
1730 }
1731
1732 /*
1733  * getTypeBinaryInputInfo
1734  *
1735  *              Get info needed for binary input of values of a type
1736  */
1737 void
1738 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
1739 {
1740         HeapTuple       typeTuple;
1741         Form_pg_type pt;
1742
1743         typeTuple = SearchSysCache(TYPEOID,
1744                                                            ObjectIdGetDatum(type),
1745                                                            0, 0, 0);
1746         if (!HeapTupleIsValid(typeTuple))
1747                 elog(ERROR, "cache lookup failed for type %u", type);
1748         pt = (Form_pg_type) GETSTRUCT(typeTuple);
1749
1750         if (!pt->typisdefined)
1751                 ereport(ERROR,
1752                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1753                                  errmsg("type %s is only a shell",
1754                                                 format_type_be(type))));
1755         if (!OidIsValid(pt->typreceive))
1756                 ereport(ERROR,
1757                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1758                                  errmsg("no binary input function available for type %s",
1759                                                 format_type_be(type))));
1760
1761         *typReceive = pt->typreceive;
1762         *typIOParam = getTypeIOParam(typeTuple);
1763
1764         ReleaseSysCache(typeTuple);
1765 }
1766
1767 /*
1768  * getTypeBinaryOutputInfo
1769  *
1770  *              Get info needed for binary output of values of a type
1771  */
1772 void
1773 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
1774 {
1775         HeapTuple       typeTuple;
1776         Form_pg_type pt;
1777
1778         typeTuple = SearchSysCache(TYPEOID,
1779                                                            ObjectIdGetDatum(type),
1780                                                            0, 0, 0);
1781         if (!HeapTupleIsValid(typeTuple))
1782                 elog(ERROR, "cache lookup failed for type %u", type);
1783         pt = (Form_pg_type) GETSTRUCT(typeTuple);
1784
1785         if (!pt->typisdefined)
1786                 ereport(ERROR,
1787                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1788                                  errmsg("type %s is only a shell",
1789                                                 format_type_be(type))));
1790         if (!OidIsValid(pt->typsend))
1791                 ereport(ERROR,
1792                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1793                                  errmsg("no binary output function available for type %s",
1794                                                 format_type_be(type))));
1795
1796         *typSend = pt->typsend;
1797         *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
1798
1799         ReleaseSysCache(typeTuple);
1800 }
1801
1802
1803 /*                              ---------- STATISTICS CACHE ----------                                   */
1804
1805 /*
1806  * get_attavgwidth
1807  *
1808  *        Given the table and attribute number of a column, get the average
1809  *        width of entries in the column.  Return zero if no data available.
1810  */
1811 int32
1812 get_attavgwidth(Oid relid, AttrNumber attnum)
1813 {
1814         HeapTuple       tp;
1815
1816         tp = SearchSysCache(STATRELATT,
1817                                                 ObjectIdGetDatum(relid),
1818                                                 Int16GetDatum(attnum),
1819                                                 0, 0);
1820         if (HeapTupleIsValid(tp))
1821         {
1822                 int32           stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1823
1824                 ReleaseSysCache(tp);
1825                 if (stawidth > 0)
1826                         return stawidth;
1827         }
1828         return 0;
1829 }
1830
1831 /*
1832  * get_attstatsslot
1833  *
1834  *              Extract the contents of a "slot" of a pg_statistic tuple.
1835  *              Returns TRUE if requested slot type was found, else FALSE.
1836  *
1837  * Unlike other routines in this file, this takes a pointer to an
1838  * already-looked-up tuple in the pg_statistic cache.  We do this since
1839  * most callers will want to extract more than one value from the cache
1840  * entry, and we don't want to repeat the cache lookup unnecessarily.
1841  *
1842  * statstuple: pg_statistics tuple to be examined.
1843  * atttype: type OID of attribute.
1844  * atttypmod: typmod of attribute.
1845  * reqkind: STAKIND code for desired statistics slot kind.
1846  * reqop: STAOP value wanted, or InvalidOid if don't care.
1847  * values, nvalues: if not NULL, the slot's stavalues are extracted.
1848  * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1849  *
1850  * If assigned, values and numbers are set to point to palloc'd arrays.
1851  * If the attribute type is pass-by-reference, the values referenced by
1852  * the values array are themselves palloc'd.  The palloc'd stuff can be
1853  * freed by calling free_attstatsslot.
1854  */
1855 bool
1856 get_attstatsslot(HeapTuple statstuple,
1857                                  Oid atttype, int32 atttypmod,
1858                                  int reqkind, Oid reqop,
1859                                  Datum **values, int *nvalues,
1860                                  float4 **numbers, int *nnumbers)
1861 {
1862         Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1863         int                     i,
1864                                 j;
1865         Datum           val;
1866         bool            isnull;
1867         ArrayType  *statarray;
1868         int                     narrayelem;
1869         HeapTuple       typeTuple;
1870         Form_pg_type typeForm;
1871
1872         for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1873         {
1874                 if ((&stats->stakind1)[i] == reqkind &&
1875                         (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1876                         break;
1877         }
1878         if (i >= STATISTIC_NUM_SLOTS)
1879                 return false;                   /* not there */
1880
1881         if (values)
1882         {
1883                 val = SysCacheGetAttr(STATRELATT, statstuple,
1884                                                           Anum_pg_statistic_stavalues1 + i,
1885                                                           &isnull);
1886                 if (isnull)
1887                         elog(ERROR, "stavalues is null");
1888                 statarray = DatumGetArrayTypeP(val);
1889
1890                 /* Need to get info about the array element type */
1891                 typeTuple = SearchSysCache(TYPEOID,
1892                                                                    ObjectIdGetDatum(atttype),
1893                                                                    0, 0, 0);
1894                 if (!HeapTupleIsValid(typeTuple))
1895                         elog(ERROR, "cache lookup failed for type %u", atttype);
1896                 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
1897
1898                 /* Deconstruct array into Datum elements */
1899                 deconstruct_array(statarray,
1900                                                   atttype,
1901                                                   typeForm->typlen,
1902                                                   typeForm->typbyval,
1903                                                   typeForm->typalign,
1904                                                   values, nvalues);
1905
1906                 /*
1907                  * If the element type is pass-by-reference, we now have a bunch
1908                  * of Datums that are pointers into the syscache value.  Copy them
1909                  * to avoid problems if syscache decides to drop the entry.
1910                  */
1911                 if (!typeForm->typbyval)
1912                 {
1913                         for (j = 0; j < *nvalues; j++)
1914                         {
1915                                 (*values)[j] = datumCopy((*values)[j],
1916                                                                                  typeForm->typbyval,
1917                                                                                  typeForm->typlen);
1918                         }
1919                 }
1920
1921                 ReleaseSysCache(typeTuple);
1922
1923                 /*
1924                  * Free statarray if it's a detoasted copy.
1925                  */
1926                 if ((Pointer) statarray != DatumGetPointer(val))
1927                         pfree(statarray);
1928         }
1929
1930         if (numbers)
1931         {
1932                 val = SysCacheGetAttr(STATRELATT, statstuple,
1933                                                           Anum_pg_statistic_stanumbers1 + i,
1934                                                           &isnull);
1935                 if (isnull)
1936                         elog(ERROR, "stanumbers is null");
1937                 statarray = DatumGetArrayTypeP(val);
1938
1939                 /*
1940                  * We expect the array to be a 1-D float4 array; verify that. We
1941                  * don't need to use deconstruct_array() since the array data is
1942                  * just going to look like a C array of float4 values.
1943                  */
1944                 narrayelem = ARR_DIMS(statarray)[0];
1945                 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1946                         ARR_ELEMTYPE(statarray) != FLOAT4OID)
1947                         elog(ERROR, "stanumbers is not a 1-D float4 array");
1948                 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1949                 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1950                 *nnumbers = narrayelem;
1951
1952                 /*
1953                  * Free statarray if it's a detoasted copy.
1954                  */
1955                 if ((Pointer) statarray != DatumGetPointer(val))
1956                         pfree(statarray);
1957         }
1958
1959         return true;
1960 }
1961
1962 void
1963 free_attstatsslot(Oid atttype,
1964                                   Datum *values, int nvalues,
1965                                   float4 *numbers, int nnumbers)
1966 {
1967         if (values)
1968         {
1969                 if (!get_typbyval(atttype))
1970                 {
1971                         int                     i;
1972
1973                         for (i = 0; i < nvalues; i++)
1974                                 pfree(DatumGetPointer(values[i]));
1975                 }
1976                 pfree(values);
1977         }
1978         if (numbers)
1979                 pfree(numbers);
1980 }
1981
1982 /*                              ---------- PG_NAMESPACE CACHE ----------                                 */
1983
1984 /*
1985  * get_namespace_name
1986  *              Returns the name of a given namespace
1987  *
1988  * Returns a palloc'd copy of the string, or NULL if no such namespace.
1989  */
1990 char *
1991 get_namespace_name(Oid nspid)
1992 {
1993         HeapTuple       tp;
1994
1995         tp = SearchSysCache(NAMESPACEOID,
1996                                                 ObjectIdGetDatum(nspid),
1997                                                 0, 0, 0);
1998         if (HeapTupleIsValid(tp))
1999         {
2000                 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2001                 char       *result;
2002
2003                 result = pstrdup(NameStr(nsptup->nspname));
2004                 ReleaseSysCache(tp);
2005                 return result;
2006         }
2007         else
2008                 return NULL;
2009 }
2010
2011 /*                              ---------- PG_AUTHID CACHE ----------                                    */
2012
2013 /*
2014  * get_roleid
2015  *        Given a role name, look up the role's OID.
2016  *        Returns InvalidOid if no such role.
2017  */
2018 Oid
2019 get_roleid(const char *rolname)
2020 {
2021         return GetSysCacheOid(AUTHNAME,
2022                                                   PointerGetDatum(rolname),
2023                                                   0, 0, 0);
2024 }
2025
2026 /*
2027  * get_roleid_checked
2028  *        Given a role name, look up the role's OID.
2029  *        ereports if no such role.
2030  */
2031 Oid
2032 get_roleid_checked(const char *rolname)
2033 {
2034         Oid             roleid;
2035
2036         roleid = get_roleid(rolname);
2037         if (!OidIsValid(roleid))
2038                 ereport(ERROR,
2039                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
2040                                  errmsg("role \"%s\" does not exist", rolname)));
2041         return roleid;
2042 }