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