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