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