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