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