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