]> granicus.if.org Git - postgresql/blob - src/backend/utils/cache/lsyscache.c
Update copyright to 2002.
[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-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.74 2002/06/20 20:29:39 momjian Exp $
11  *
12  * NOTES
13  *        Eventually, the index information should go through here, too.
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17
18 #include "access/tupmacs.h"
19 #include "catalog/pg_amop.h"
20 #include "catalog/pg_namespace.h"
21 #include "catalog/pg_opclass.h"
22 #include "catalog/pg_operator.h"
23 #include "catalog/pg_proc.h"
24 #include "catalog/pg_shadow.h"
25 #include "catalog/pg_statistic.h"
26 #include "catalog/pg_type.h"
27 #include "nodes/makefuncs.h"
28 #include "utils/array.h"
29 #include "utils/builtins.h"
30 #include "utils/lsyscache.h"
31 #include "utils/syscache.h"
32
33
34 /*                              ---------- AMOP CACHES ----------                                                */
35
36 /*
37  * op_in_opclass
38  *
39  *              Return t iff operator 'opno' is in operator class 'opclass'.
40  */
41 bool
42 op_in_opclass(Oid opno, Oid opclass)
43 {
44         return SearchSysCacheExists(AMOPOPID,
45                                                                 ObjectIdGetDatum(opclass),
46                                                                 ObjectIdGetDatum(opno),
47                                                                 0, 0);
48 }
49
50 /*
51  * op_requires_recheck
52  *
53  *              Return t if operator 'opno' requires a recheck when used as a
54  *              member of opclass 'opclass' (ie, this opclass is lossy for this
55  *              operator).
56  *
57  * Caller should already have verified that opno is a member of opclass,
58  * therefore we raise an error if the tuple is not found.
59  */
60 bool
61 op_requires_recheck(Oid opno, Oid opclass)
62 {
63         HeapTuple       tp;
64         Form_pg_amop amop_tup;
65         bool            result;
66
67         tp = SearchSysCache(AMOPOPID,
68                                                 ObjectIdGetDatum(opclass),
69                                                 ObjectIdGetDatum(opno),
70                                                 0, 0);
71         if (!HeapTupleIsValid(tp))
72                 elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u",
73                          opno, opclass);
74         amop_tup = (Form_pg_amop) GETSTRUCT(tp);
75
76         result = amop_tup->amopreqcheck;
77         ReleaseSysCache(tp);
78         return result;
79 }
80
81 /*                              ---------- ATTRIBUTE CACHES ----------                                   */
82
83 /*
84  * get_attname
85  *
86  *              Given the relation id and the attribute number,
87  *              return the "attname" field from the attribute relation.
88  *
89  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
90  */
91 char *
92 get_attname(Oid relid, AttrNumber attnum)
93 {
94         HeapTuple       tp;
95
96         tp = SearchSysCache(ATTNUM,
97                                                 ObjectIdGetDatum(relid),
98                                                 Int16GetDatum(attnum),
99                                                 0, 0);
100         if (HeapTupleIsValid(tp))
101         {
102                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
103                 char       *result;
104
105                 result = pstrdup(NameStr(att_tup->attname));
106                 ReleaseSysCache(tp);
107                 return result;
108         }
109         else
110                 return NULL;
111 }
112
113 /*
114  * get_attnum
115  *
116  *              Given the relation id and the attribute name,
117  *              return the "attnum" field from the attribute relation.
118  */
119 AttrNumber
120 get_attnum(Oid relid, char *attname)
121 {
122         HeapTuple       tp;
123
124         tp = SearchSysCache(ATTNAME,
125                                                 ObjectIdGetDatum(relid),
126                                                 PointerGetDatum(attname),
127                                                 0, 0);
128         if (HeapTupleIsValid(tp))
129         {
130                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
131                 AttrNumber      result;
132
133                 result = att_tup->attnum;
134                 ReleaseSysCache(tp);
135                 return result;
136         }
137         else
138                 return InvalidAttrNumber;
139 }
140
141 /*
142  * get_atttype
143  *
144  *              Given the relation OID and the attribute number with the relation,
145  *              return the attribute type OID.
146  */
147 Oid
148 get_atttype(Oid relid, AttrNumber attnum)
149 {
150         HeapTuple       tp;
151
152         tp = SearchSysCache(ATTNUM,
153                                                 ObjectIdGetDatum(relid),
154                                                 Int16GetDatum(attnum),
155                                                 0, 0);
156         if (HeapTupleIsValid(tp))
157         {
158                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
159                 Oid                     result;
160
161                 result = att_tup->atttypid;
162                 ReleaseSysCache(tp);
163                 return result;
164         }
165         else
166                 return InvalidOid;
167 }
168
169 /* This routine uses the attname instead of the attnum because it
170  * replaces the routine find_atttype, which is called sometimes when
171  * only the attname, not the attno, is available.
172  */
173 bool
174 get_attisset(Oid relid, char *attname)
175 {
176         HeapTuple       tp;
177
178         tp = SearchSysCache(ATTNAME,
179                                                 ObjectIdGetDatum(relid),
180                                                 PointerGetDatum(attname),
181                                                 0, 0);
182         if (HeapTupleIsValid(tp))
183         {
184                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
185                 bool            result;
186
187                 result = att_tup->attisset;
188                 ReleaseSysCache(tp);
189                 return result;
190         }
191         else
192                 return false;
193 }
194
195 /*
196  * get_atttypmod
197  *
198  *              Given the relation id and the attribute number,
199  *              return the "atttypmod" field from the attribute relation.
200  */
201 int32
202 get_atttypmod(Oid relid, AttrNumber attnum)
203 {
204         HeapTuple       tp;
205
206         tp = SearchSysCache(ATTNUM,
207                                                 ObjectIdGetDatum(relid),
208                                                 Int16GetDatum(attnum),
209                                                 0, 0);
210         if (HeapTupleIsValid(tp))
211         {
212                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
213                 int32           result;
214
215                 result = att_tup->atttypmod;
216                 ReleaseSysCache(tp);
217                 return result;
218         }
219         else
220                 return -1;
221 }
222
223 /*
224  * get_atttypetypmod
225  *
226  *              A two-fer: given the relation id and the attribute number,
227  *              fetch both type OID and atttypmod in a single cache lookup.
228  *
229  * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
230  * raises an error if it can't obtain the information.
231  */
232 void
233 get_atttypetypmod(Oid relid, AttrNumber attnum,
234                                   Oid *typid, int32 *typmod)
235 {
236         HeapTuple       tp;
237         Form_pg_attribute att_tup;
238
239         tp = SearchSysCache(ATTNUM,
240                                                 ObjectIdGetDatum(relid),
241                                                 Int16GetDatum(attnum),
242                                                 0, 0);
243         if (!HeapTupleIsValid(tp))
244                 elog(ERROR, "cache lookup failed for relation %u attribute %d",
245                          relid, attnum);
246         att_tup = (Form_pg_attribute) GETSTRUCT(tp);
247
248         *typid = att_tup->atttypid;
249         *typmod = att_tup->atttypmod;
250         ReleaseSysCache(tp);
251 }
252
253 /*                              ---------- INDEX CACHE ----------                                                */
254
255 /*              watch this space...
256  */
257
258 /*                              ---------- OPCLASS CACHE ----------                                              */
259
260 /*
261  * opclass_is_btree
262  *
263  *              Returns TRUE iff the specified opclass is associated with the
264  *              btree index access method.
265  */
266 bool
267 opclass_is_btree(Oid opclass)
268 {
269         HeapTuple       tp;
270         Form_pg_opclass cla_tup;
271         bool            result;
272
273         tp = SearchSysCache(CLAOID,
274                                                 ObjectIdGetDatum(opclass),
275                                                 0, 0, 0);
276         if (!HeapTupleIsValid(tp))
277                 elog(ERROR, "cache lookup failed for opclass %u", opclass);
278         cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
279
280         result = (cla_tup->opcamid == BTREE_AM_OID);
281         ReleaseSysCache(tp);
282         return result;
283 }
284
285 /*                              ---------- OPERATOR CACHE ----------                                     */
286
287 /*
288  * get_opcode
289  *
290  *              Returns the regproc id of the routine used to implement an
291  *              operator given the operator oid.
292  */
293 RegProcedure
294 get_opcode(Oid opno)
295 {
296         HeapTuple       tp;
297
298         tp = SearchSysCache(OPEROID,
299                                                 ObjectIdGetDatum(opno),
300                                                 0, 0, 0);
301         if (HeapTupleIsValid(tp))
302         {
303                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
304                 RegProcedure result;
305
306                 result = optup->oprcode;
307                 ReleaseSysCache(tp);
308                 return result;
309         }
310         else
311                 return (RegProcedure) InvalidOid;
312 }
313
314 /*
315  * get_opname
316  *        returns the name of the operator with the given opno
317  *
318  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
319  */
320 char *
321 get_opname(Oid opno)
322 {
323         HeapTuple       tp;
324
325         tp = SearchSysCache(OPEROID,
326                                                 ObjectIdGetDatum(opno),
327                                                 0, 0, 0);
328         if (HeapTupleIsValid(tp))
329         {
330                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
331                 char       *result;
332
333                 result = pstrdup(NameStr(optup->oprname));
334                 ReleaseSysCache(tp);
335                 return result;
336         }
337         else
338                 return NULL;
339 }
340
341 /*
342  * op_mergejoinable
343  *
344  *              Returns the left and right sort operators and types corresponding to a
345  *              mergejoinable operator, or nil if the operator is not mergejoinable.
346  */
347 bool
348 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
349 {
350         HeapTuple       tp;
351         bool            result = false;
352
353         tp = SearchSysCache(OPEROID,
354                                                 ObjectIdGetDatum(opno),
355                                                 0, 0, 0);
356         if (HeapTupleIsValid(tp))
357         {
358                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
359
360                 if (optup->oprlsortop &&
361                         optup->oprrsortop &&
362                         optup->oprleft == ltype &&
363                         optup->oprright == rtype)
364                 {
365                         *leftOp = optup->oprlsortop;
366                         *rightOp = optup->oprrsortop;
367                         result = true;
368                 }
369                 ReleaseSysCache(tp);
370         }
371         return result;
372 }
373
374 /*
375  * op_mergejoin_crossops
376  *
377  *              Returns the cross-type comparison operators (ltype "<" rtype and
378  *              ltype ">" rtype) for an operator previously determined to be
379  *              mergejoinable.  Optionally, fetches the regproc ids of these
380  *              operators, as well as their operator OIDs.
381  */
382 void
383 op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
384                                           RegProcedure *ltproc, RegProcedure *gtproc)
385 {
386         HeapTuple       tp;
387         Form_pg_operator optup;
388
389         /*
390          * Get the declared comparison operators of the operator.
391          */
392         tp = SearchSysCache(OPEROID,
393                                                 ObjectIdGetDatum(opno),
394                                                 0, 0, 0);
395         if (!HeapTupleIsValid(tp))      /* shouldn't happen */
396                 elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
397         optup = (Form_pg_operator) GETSTRUCT(tp);
398         *ltop = optup->oprltcmpop;
399         *gtop = optup->oprgtcmpop;
400         ReleaseSysCache(tp);
401
402         /* Check < op provided */
403         if (!OidIsValid(*ltop))
404                 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
405                          opno);
406         if (ltproc)
407                 *ltproc = get_opcode(*ltop);
408
409         /* Check > op provided */
410         if (!OidIsValid(*gtop))
411                 elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
412                          opno);
413         if (gtproc)
414                 *gtproc = get_opcode(*gtop);
415 }
416
417 /*
418  * op_hashjoinable
419  *
420  * Returns the hash operator corresponding to a hashjoinable operator,
421  * or InvalidOid if the operator is not hashjoinable.
422  */
423 Oid
424 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
425 {
426         HeapTuple       tp;
427         Oid                     result = InvalidOid;
428
429         tp = SearchSysCache(OPEROID,
430                                                 ObjectIdGetDatum(opno),
431                                                 0, 0, 0);
432         if (HeapTupleIsValid(tp))
433         {
434                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
435
436                 if (optup->oprcanhash &&
437                         optup->oprleft == ltype &&
438                         optup->oprright == rtype)
439                         result = opno;
440                 ReleaseSysCache(tp);
441         }
442         return result;
443 }
444
445 /*
446  * op_volatile
447  *
448  * Get the provolatile flag for the operator's underlying function.
449  */
450 char
451 op_volatile(Oid opno)
452 {
453         RegProcedure funcid = get_opcode(opno);
454
455         if (funcid == (RegProcedure) InvalidOid)
456                 elog(ERROR, "Operator OID %u does not exist", opno);
457
458         return func_volatile((Oid) funcid);
459 }
460
461 /*
462  * get_commutator
463  *
464  *              Returns the corresponding commutator of an operator.
465  */
466 Oid
467 get_commutator(Oid opno)
468 {
469         HeapTuple       tp;
470
471         tp = SearchSysCache(OPEROID,
472                                                 ObjectIdGetDatum(opno),
473                                                 0, 0, 0);
474         if (HeapTupleIsValid(tp))
475         {
476                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
477                 Oid                     result;
478
479                 result = optup->oprcom;
480                 ReleaseSysCache(tp);
481                 return result;
482         }
483         else
484                 return InvalidOid;
485 }
486
487 /*
488  * get_negator
489  *
490  *              Returns the corresponding negator of an operator.
491  */
492 Oid
493 get_negator(Oid opno)
494 {
495         HeapTuple       tp;
496
497         tp = SearchSysCache(OPEROID,
498                                                 ObjectIdGetDatum(opno),
499                                                 0, 0, 0);
500         if (HeapTupleIsValid(tp))
501         {
502                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
503                 Oid                     result;
504
505                 result = optup->oprnegate;
506                 ReleaseSysCache(tp);
507                 return result;
508         }
509         else
510                 return InvalidOid;
511 }
512
513 /*
514  * get_oprrest
515  *
516  *              Returns procedure id for computing selectivity of an operator.
517  */
518 RegProcedure
519 get_oprrest(Oid opno)
520 {
521         HeapTuple       tp;
522
523         tp = SearchSysCache(OPEROID,
524                                                 ObjectIdGetDatum(opno),
525                                                 0, 0, 0);
526         if (HeapTupleIsValid(tp))
527         {
528                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
529                 RegProcedure result;
530
531                 result = optup->oprrest;
532                 ReleaseSysCache(tp);
533                 return result;
534         }
535         else
536                 return (RegProcedure) InvalidOid;
537 }
538
539 /*
540  * get_oprjoin
541  *
542  *              Returns procedure id for computing selectivity of a join.
543  */
544 RegProcedure
545 get_oprjoin(Oid opno)
546 {
547         HeapTuple       tp;
548
549         tp = SearchSysCache(OPEROID,
550                                                 ObjectIdGetDatum(opno),
551                                                 0, 0, 0);
552         if (HeapTupleIsValid(tp))
553         {
554                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
555                 RegProcedure result;
556
557                 result = optup->oprjoin;
558                 ReleaseSysCache(tp);
559                 return result;
560         }
561         else
562                 return (RegProcedure) InvalidOid;
563 }
564
565 /*                              ---------- FUNCTION CACHE ----------                                     */
566
567 /*
568  * get_func_name
569  *        returns the name of the function with the given funcid
570  *
571  * Note: returns a palloc'd copy of the string, or NULL if no such function.
572  */
573 char *
574 get_func_name(Oid funcid)
575 {
576         HeapTuple       tp;
577
578         tp = SearchSysCache(PROCOID,
579                                                 ObjectIdGetDatum(funcid),
580                                                 0, 0, 0);
581         if (HeapTupleIsValid(tp))
582         {
583                 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
584                 char       *result;
585
586                 result = pstrdup(NameStr(functup->proname));
587                 ReleaseSysCache(tp);
588                 return result;
589         }
590         else
591                 return NULL;
592 }
593
594 /*
595  * get_func_rettype
596  *              Given procedure id, return the function's result type.
597  */
598 Oid
599 get_func_rettype(Oid funcid)
600 {
601         HeapTuple       tp;
602         Oid                     result;
603
604         tp = SearchSysCache(PROCOID,
605                                                 ObjectIdGetDatum(funcid),
606                                                 0, 0, 0);
607         if (!HeapTupleIsValid(tp))
608                 elog(ERROR, "Function OID %u does not exist", funcid);
609
610         result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
611         ReleaseSysCache(tp);
612         return result;
613 }
614
615 /*
616  * get_func_retset
617  *              Given procedure id, return the function's proretset flag.
618  */
619 bool
620 get_func_retset(Oid funcid)
621 {
622         HeapTuple       tp;
623         bool            result;
624
625         tp = SearchSysCache(PROCOID,
626                                                 ObjectIdGetDatum(funcid),
627                                                 0, 0, 0);
628         if (!HeapTupleIsValid(tp))
629                 elog(ERROR, "Function OID %u does not exist", funcid);
630
631         result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
632         ReleaseSysCache(tp);
633         return result;
634 }
635
636 /*
637  * func_volatile
638  *              Given procedure id, return the function's provolatile flag.
639  */
640 char
641 func_volatile(Oid funcid)
642 {
643         HeapTuple       tp;
644         char            result;
645
646         tp = SearchSysCache(PROCOID,
647                                                 ObjectIdGetDatum(funcid),
648                                                 0, 0, 0);
649         if (!HeapTupleIsValid(tp))
650                 elog(ERROR, "Function OID %u does not exist", funcid);
651
652         result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
653         ReleaseSysCache(tp);
654         return result;
655 }
656
657 /*                              ---------- RELATION CACHE ----------                                     */
658
659 /*
660  * get_relname_relid
661  *              Given name and namespace of a relation, look up the OID.
662  *
663  * Returns InvalidOid if there is no such relation.
664  */
665 Oid
666 get_relname_relid(const char *relname, Oid relnamespace)
667 {
668         return GetSysCacheOid(RELNAMENSP,
669                                                   PointerGetDatum(relname),
670                                                   ObjectIdGetDatum(relnamespace),
671                                                   0, 0);
672 }
673
674 #ifdef NOT_USED
675 /*
676  * get_relnatts
677  *
678  *              Returns the number of attributes for a given relation.
679  */
680 int
681 get_relnatts(Oid relid)
682 {
683         HeapTuple       tp;
684
685         tp = SearchSysCache(RELOID,
686                                                 ObjectIdGetDatum(relid),
687                                                 0, 0, 0);
688         if (HeapTupleIsValid(tp))
689         {
690                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
691                 int                     result;
692
693                 result = reltup->relnatts;
694                 ReleaseSysCache(tp);
695                 return result;
696         }
697         else
698                 return InvalidAttrNumber;
699 }
700 #endif
701
702 /*
703  * get_rel_name
704  *              Returns the name of a given relation.
705  *
706  * Returns a palloc'd copy of the string, or NULL if no such relation.
707  *
708  * NOTE: since relation name is not unique, be wary of code that uses this
709  * for anything except preparing error messages.
710  */
711 char *
712 get_rel_name(Oid relid)
713 {
714         HeapTuple       tp;
715
716         tp = SearchSysCache(RELOID,
717                                                 ObjectIdGetDatum(relid),
718                                                 0, 0, 0);
719         if (HeapTupleIsValid(tp))
720         {
721                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
722                 char       *result;
723
724                 result = pstrdup(NameStr(reltup->relname));
725                 ReleaseSysCache(tp);
726                 return result;
727         }
728         else
729                 return NULL;
730 }
731
732 /*
733  * get_rel_namespace
734  *
735  *              Returns the pg_namespace OID associated with a given relation.
736  */
737 Oid
738 get_rel_namespace(Oid relid)
739 {
740         HeapTuple       tp;
741
742         tp = SearchSysCache(RELOID,
743                                                 ObjectIdGetDatum(relid),
744                                                 0, 0, 0);
745         if (HeapTupleIsValid(tp))
746         {
747                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
748                 Oid             result;
749
750                 result = reltup->relnamespace;
751                 ReleaseSysCache(tp);
752                 return result;
753         }
754         else
755                 return InvalidOid;
756 }
757
758 /*
759  * get_rel_type_id
760  *
761  *              Returns the pg_type OID associated with a given relation.
762  *
763  * Note: not all pg_class entries have associated pg_type OIDs; so be
764  * careful to check for InvalidOid result.
765  */
766 Oid
767 get_rel_type_id(Oid relid)
768 {
769         HeapTuple       tp;
770
771         tp = SearchSysCache(RELOID,
772                                                 ObjectIdGetDatum(relid),
773                                                 0, 0, 0);
774         if (HeapTupleIsValid(tp))
775         {
776                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
777                 Oid             result;
778
779                 result = reltup->reltype;
780                 ReleaseSysCache(tp);
781                 return result;
782         }
783         else
784                 return InvalidOid;
785 }
786
787 /*                              ---------- TYPE CACHE ----------                                                 */
788
789 /*
790  * get_typisdefined
791  *
792  *              Given the type OID, determine whether the type is defined
793  *              (if not, it's only a shell).
794  */
795 bool
796 get_typisdefined(Oid typid)
797 {
798         HeapTuple       tp;
799
800         tp = SearchSysCache(TYPEOID,
801                                                 ObjectIdGetDatum(typid),
802                                                 0, 0, 0);
803         if (HeapTupleIsValid(tp))
804         {
805                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
806                 bool            result;
807
808                 result = typtup->typisdefined;
809                 ReleaseSysCache(tp);
810                 return result;
811         }
812         else
813                 return false;
814 }
815
816 /*
817  * get_typlen
818  *
819  *              Given the type OID, return the length of the type.
820  */
821 int16
822 get_typlen(Oid typid)
823 {
824         HeapTuple       tp;
825
826         tp = SearchSysCache(TYPEOID,
827                                                 ObjectIdGetDatum(typid),
828                                                 0, 0, 0);
829         if (HeapTupleIsValid(tp))
830         {
831                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
832                 int16           result;
833
834                 result = typtup->typlen;
835                 ReleaseSysCache(tp);
836                 return result;
837         }
838         else
839                 return 0;
840 }
841
842 /*
843  * get_typbyval
844  *
845  *              Given the type OID, determine whether the type is returned by value or
846  *              not.  Returns true if by value, false if by reference.
847  */
848 bool
849 get_typbyval(Oid typid)
850 {
851         HeapTuple       tp;
852
853         tp = SearchSysCache(TYPEOID,
854                                                 ObjectIdGetDatum(typid),
855                                                 0, 0, 0);
856         if (HeapTupleIsValid(tp))
857         {
858                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
859                 bool            result;
860
861                 result = typtup->typbyval;
862                 ReleaseSysCache(tp);
863                 return result;
864         }
865         else
866                 return false;
867 }
868
869 /*
870  * get_typlenbyval
871  *
872  *              A two-fer: given the type OID, return both typlen and typbyval.
873  *
874  *              Since both pieces of info are needed to know how to copy a Datum,
875  *              many places need both.  Might as well get them with one cache lookup
876  *              instead of two.  Also, this routine raises an error instead of
877  *              returning a bogus value when given a bad type OID.
878  */
879 void
880 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
881 {
882         HeapTuple       tp;
883         Form_pg_type typtup;
884
885         tp = SearchSysCache(TYPEOID,
886                                                 ObjectIdGetDatum(typid),
887                                                 0, 0, 0);
888         if (!HeapTupleIsValid(tp))
889                 elog(ERROR, "cache lookup failed for type %u", typid);
890         typtup = (Form_pg_type) GETSTRUCT(tp);
891         *typlen = typtup->typlen;
892         *typbyval = typtup->typbyval;
893         ReleaseSysCache(tp);
894 }
895
896 #ifdef NOT_USED
897 char
898 get_typalign(Oid typid)
899 {
900         HeapTuple       tp;
901
902         tp = SearchSysCache(TYPEOID,
903                                                 ObjectIdGetDatum(typid),
904                                                 0, 0, 0);
905         if (HeapTupleIsValid(tp))
906         {
907                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
908                 char            result;
909
910                 result = typtup->typalign;
911                 ReleaseSysCache(tp);
912                 return result;
913         }
914         else
915                 return 'i';
916 }
917 #endif
918
919 char
920 get_typstorage(Oid typid)
921 {
922         HeapTuple       tp;
923
924         tp = SearchSysCache(TYPEOID,
925                                                 ObjectIdGetDatum(typid),
926                                                 0, 0, 0);
927         if (HeapTupleIsValid(tp))
928         {
929                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
930                 char            result;
931
932                 result = typtup->typstorage;
933                 ReleaseSysCache(tp);
934                 return result;
935         }
936         else
937                 return 'p';
938 }
939
940 /*
941  * get_typdefault
942  *        Given a type OID, return the type's default value, if any.
943  *
944  *        The result is a palloc'd expression node tree, or NULL if there
945  *        is no defined default for the datatype.
946  *
947  * NB: caller should be prepared to coerce result to correct datatype;
948  * the returned expression tree might produce something of the wrong type.
949  */
950 Node *
951 get_typdefault(Oid typid)
952 {
953         HeapTuple       typeTuple;
954         Form_pg_type type;
955         Datum           datum;
956         bool            isNull;
957         Node       *expr;
958
959         typeTuple = SearchSysCache(TYPEOID,
960                                                            ObjectIdGetDatum(typid),
961                                                            0, 0, 0);
962         if (!HeapTupleIsValid(typeTuple))
963                 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
964         type = (Form_pg_type) GETSTRUCT(typeTuple);
965
966         /*
967          * typdefault and typdefaultbin are potentially null, so don't try to
968          * access 'em as struct fields. Must do it the hard way with
969          * SysCacheGetAttr.
970          */
971         datum = SysCacheGetAttr(TYPEOID,
972                                                         typeTuple,
973                                                         Anum_pg_type_typdefaultbin,
974                                                         &isNull);
975
976         if (!isNull)
977         {
978                 /* We have an expression default */
979                 expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
980                                                                                                                                 datum)));
981         }
982         else
983         {
984                 /* Perhaps we have a plain literal default */
985                 datum = SysCacheGetAttr(TYPEOID,
986                                                                 typeTuple,
987                                                                 Anum_pg_type_typdefault,
988                                                                 &isNull);
989
990                 if (!isNull)
991                 {
992                         char       *strDefaultVal;
993
994                         /* Convert text datum to C string */
995                         strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
996                                                                                                                                 datum));
997                         /* Convert C string to a value of the given type */
998                         datum = OidFunctionCall3(type->typinput,
999                                                                          CStringGetDatum(strDefaultVal),
1000                                                                          ObjectIdGetDatum(type->typelem),
1001                                                                          Int32GetDatum(-1));
1002                         /* Build a Const node containing the value */
1003                         expr = (Node *) makeConst(typid,
1004                                                                           type->typlen,
1005                                                                           datum,
1006                                                                           false,
1007                                                                           type->typbyval,
1008                                                                           false,        /* not a set */
1009                                                                           false);
1010                         pfree(strDefaultVal);
1011                 }
1012                 else
1013                 {
1014                         /* No default */
1015                         expr = NULL;
1016                 }
1017         }
1018
1019         ReleaseSysCache(typeTuple);
1020
1021         return expr;
1022 }
1023
1024 /*
1025  * getBaseType
1026  *              If the given type is a domain, return its base type;
1027  *              otherwise return the type's own OID.
1028  */
1029 Oid
1030 getBaseType(Oid typid)
1031 {
1032         /*
1033          * We loop to find the bottom base type in a stack of domains.
1034          */
1035         for (;;)
1036         {
1037                 HeapTuple       tup;
1038                 Form_pg_type typTup;
1039
1040                 tup = SearchSysCache(TYPEOID,
1041                                                          ObjectIdGetDatum(typid),
1042                                                          0, 0, 0);
1043                 if (!HeapTupleIsValid(tup))
1044                         elog(ERROR, "getBaseType: failed to lookup type %u", typid);
1045                 typTup = (Form_pg_type) GETSTRUCT(tup);
1046                 if (typTup->typtype != 'd')
1047                 {
1048                         /* Not a domain, so done */
1049                         ReleaseSysCache(tup);
1050                         break;
1051                 }
1052
1053                 typid = typTup->typbasetype;
1054                 ReleaseSysCache(tup);
1055         }
1056
1057         return typid;
1058 }
1059
1060 /*
1061  * get_typavgwidth
1062  *
1063  *        Given a type OID and a typmod value (pass -1 if typmod is unknown),
1064  *        estimate the average width of values of the type.  This is used by
1065  *        the planner, which doesn't require absolutely correct results;
1066  *        it's OK (and expected) to guess if we don't know for sure.
1067  */
1068 int32
1069 get_typavgwidth(Oid typid, int32 typmod)
1070 {
1071         int                     typlen = get_typlen(typid);
1072         int32           maxwidth;
1073
1074         /*
1075          * Easy if it's a fixed-width type
1076          */
1077         if (typlen > 0)
1078                 return typlen;
1079
1080         /*
1081          * type_maximum_size knows the encoding of typmod for some datatypes;
1082          * don't duplicate that knowledge here.
1083          */
1084         maxwidth = type_maximum_size(typid, typmod);
1085         if (maxwidth > 0)
1086         {
1087                 /*
1088                  * For BPCHAR, the max width is also the only width.  Otherwise we
1089                  * need to guess about the typical data width given the max. A
1090                  * sliding scale for percentage of max width seems reasonable.
1091                  */
1092                 if (typid == BPCHAROID)
1093                         return maxwidth;
1094                 if (maxwidth <= 32)
1095                         return maxwidth;        /* assume full width */
1096                 if (maxwidth < 1000)
1097                         return 32 + (maxwidth - 32) / 2;        /* assume 50% */
1098
1099                 /*
1100                  * Beyond 1000, assume we're looking at something like
1101                  * "varchar(10000)" where the limit isn't actually reached often,
1102                  * and use a fixed estimate.
1103                  */
1104                 return 32 + (1000 - 32) / 2;
1105         }
1106
1107         /*
1108          * Ooops, we have no idea ... wild guess time.
1109          */
1110         return 32;
1111 }
1112
1113 /*
1114  * get_typtype
1115  *
1116  *              Given the type OID, find if it is a basic type, a named relation
1117  *              or the generic type 'relation'.
1118  *              It returns the null char if the cache lookup fails...
1119  */
1120 #ifdef NOT_USED
1121 char
1122 get_typtype(Oid typid)
1123 {
1124         HeapTuple       tp;
1125
1126         tp = SearchSysCache(TYPEOID,
1127                                                 ObjectIdGetDatum(typid),
1128                                                 0, 0, 0);
1129         if (HeapTupleIsValid(tp))
1130         {
1131                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1132                 char            result;
1133
1134                 result = typtup->typtype;
1135                 ReleaseSysCache(tp);
1136                 return result;
1137         }
1138         else
1139                 return '\0';
1140 }
1141 #endif
1142
1143 /*                              ---------- STATISTICS CACHE ----------                                   */
1144
1145 /*
1146  * get_attavgwidth
1147  *
1148  *        Given the table and attribute number of a column, get the average
1149  *        width of entries in the column.  Return zero if no data available.
1150  */
1151 int32
1152 get_attavgwidth(Oid relid, AttrNumber attnum)
1153 {
1154         HeapTuple       tp;
1155
1156         tp = SearchSysCache(STATRELATT,
1157                                                 ObjectIdGetDatum(relid),
1158                                                 Int16GetDatum(attnum),
1159                                                 0, 0);
1160         if (HeapTupleIsValid(tp))
1161         {
1162                 int32           stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
1163
1164                 ReleaseSysCache(tp);
1165                 if (stawidth > 0)
1166                         return stawidth;
1167         }
1168         return 0;
1169 }
1170
1171 /*
1172  * get_attstatsslot
1173  *
1174  *              Extract the contents of a "slot" of a pg_statistic tuple.
1175  *              Returns TRUE if requested slot type was found, else FALSE.
1176  *
1177  * Unlike other routines in this file, this takes a pointer to an
1178  * already-looked-up tuple in the pg_statistic cache.  We do this since
1179  * most callers will want to extract more than one value from the cache
1180  * entry, and we don't want to repeat the cache lookup unnecessarily.
1181  *
1182  * statstuple: pg_statistics tuple to be examined.
1183  * atttype: type OID of attribute.
1184  * atttypmod: typmod of attribute.
1185  * reqkind: STAKIND code for desired statistics slot kind.
1186  * reqop: STAOP value wanted, or InvalidOid if don't care.
1187  * values, nvalues: if not NULL, the slot's stavalues are extracted.
1188  * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
1189  *
1190  * If assigned, values and numbers are set to point to palloc'd arrays.
1191  * If the attribute type is pass-by-reference, the values referenced by
1192  * the values array are themselves palloc'd.  The palloc'd stuff can be
1193  * freed by calling free_attstatsslot.
1194  */
1195 bool
1196 get_attstatsslot(HeapTuple statstuple,
1197                                  Oid atttype, int32 atttypmod,
1198                                  int reqkind, Oid reqop,
1199                                  Datum **values, int *nvalues,
1200                                  float4 **numbers, int *nnumbers)
1201 {
1202         Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
1203         int                     i,
1204                                 j;
1205         Datum           val;
1206         bool            isnull;
1207         ArrayType  *statarray;
1208         int                     narrayelem;
1209         HeapTuple       typeTuple;
1210         FmgrInfo        inputproc;
1211         Oid                     typelem;
1212
1213         for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1214         {
1215                 if ((&stats->stakind1)[i] == reqkind &&
1216                         (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
1217                         break;
1218         }
1219         if (i >= STATISTIC_NUM_SLOTS)
1220                 return false;                   /* not there */
1221
1222         if (values)
1223         {
1224                 val = SysCacheGetAttr(STATRELATT, statstuple,
1225                                                           Anum_pg_statistic_stavalues1 + i,
1226                                                           &isnull);
1227                 if (isnull)
1228                         elog(ERROR, "get_attstatsslot: stavalues is null");
1229                 statarray = DatumGetArrayTypeP(val);
1230
1231                 /*
1232                  * Do initial examination of the array.  This produces a list of
1233                  * text Datums --- ie, pointers into the text array value.
1234                  */
1235                 deconstruct_array(statarray, false, -1, 'i', values, nvalues);
1236                 narrayelem = *nvalues;
1237
1238                 /*
1239                  * We now need to replace each text Datum by its internal
1240                  * equivalent.
1241                  *
1242                  * Get the type input proc and typelem for the column datatype.
1243                  */
1244                 typeTuple = SearchSysCache(TYPEOID,
1245                                                                    ObjectIdGetDatum(atttype),
1246                                                                    0, 0, 0);
1247                 if (!HeapTupleIsValid(typeTuple))
1248                         elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u",
1249                                  atttype);
1250                 fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc);
1251                 typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
1252                 ReleaseSysCache(typeTuple);
1253
1254                 /*
1255                  * Do the conversions.  The palloc'd array of Datums is reused in
1256                  * place.
1257                  */
1258                 for (j = 0; j < narrayelem; j++)
1259                 {
1260                         char       *strval;
1261
1262                         strval = DatumGetCString(DirectFunctionCall1(textout,
1263                                                                                                                  (*values)[j]));
1264                         (*values)[j] = FunctionCall3(&inputproc,
1265                                                                                  CStringGetDatum(strval),
1266                                                                                  ObjectIdGetDatum(typelem),
1267                                                                                  Int32GetDatum(atttypmod));
1268                         pfree(strval);
1269                 }
1270
1271                 /*
1272                  * Free statarray if it's a detoasted copy.
1273                  */
1274                 if ((Pointer) statarray != DatumGetPointer(val))
1275                         pfree(statarray);
1276         }
1277
1278         if (numbers)
1279         {
1280                 val = SysCacheGetAttr(STATRELATT, statstuple,
1281                                                           Anum_pg_statistic_stanumbers1 + i,
1282                                                           &isnull);
1283                 if (isnull)
1284                         elog(ERROR, "get_attstatsslot: stanumbers is null");
1285                 statarray = DatumGetArrayTypeP(val);
1286
1287                 /*
1288                  * We expect the array to be a 1-D float4 array; verify that. We
1289                  * don't need to use deconstruct_array() since the array data is
1290                  * just going to look like a C array of float4 values.
1291                  */
1292                 narrayelem = ARR_DIMS(statarray)[0];
1293                 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
1294                         ARR_SIZE(statarray) != (ARR_OVERHEAD(1) + narrayelem * sizeof(float4)))
1295                         elog(ERROR, "get_attstatsslot: stanumbers is bogus");
1296                 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
1297                 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
1298                 *nnumbers = narrayelem;
1299
1300                 /*
1301                  * Free statarray if it's a detoasted copy.
1302                  */
1303                 if ((Pointer) statarray != DatumGetPointer(val))
1304                         pfree(statarray);
1305         }
1306
1307         return true;
1308 }
1309
1310 void
1311 free_attstatsslot(Oid atttype,
1312                                   Datum *values, int nvalues,
1313                                   float4 *numbers, int nnumbers)
1314 {
1315         if (values)
1316         {
1317                 if (!get_typbyval(atttype))
1318                 {
1319                         int                     i;
1320
1321                         for (i = 0; i < nvalues; i++)
1322                                 pfree(DatumGetPointer(values[i]));
1323                 }
1324                 pfree(values);
1325         }
1326         if (numbers)
1327                 pfree(numbers);
1328 }
1329
1330 /*                              ---------- PG_NAMESPACE CACHE ----------                                 */
1331
1332 /*
1333  * get_namespace_name
1334  *              Returns the name of a given namespace
1335  *
1336  * Returns a palloc'd copy of the string, or NULL if no such namespace.
1337  */
1338 char *
1339 get_namespace_name(Oid nspid)
1340 {
1341         HeapTuple       tp;
1342
1343         tp = SearchSysCache(NAMESPACEOID,
1344                                                 ObjectIdGetDatum(nspid),
1345                                                 0, 0, 0);
1346         if (HeapTupleIsValid(tp))
1347         {
1348                 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
1349                 char       *result;
1350
1351                 result = pstrdup(NameStr(nsptup->nspname));
1352                 ReleaseSysCache(tp);
1353                 return result;
1354         }
1355         else
1356                 return NULL;
1357 }
1358
1359 /*                              ---------- PG_SHADOW CACHE ----------                                    */
1360
1361 /*
1362  * get_usesysid
1363  *
1364  *        Given a user name, look up the user's sysid.
1365  *        Raises an error if no such user (rather than returning zero,
1366  *        which might possibly be a valid usesysid).
1367  *
1368  * Note: the type of usesysid is currently int4, but may change to Oid
1369  * someday.  It'd be reasonable to return zero on failure if we were
1370  * using Oid ...
1371  */
1372 int32
1373 get_usesysid(const char *username)
1374 {
1375         int32           result;
1376         HeapTuple       userTup;
1377
1378         userTup = SearchSysCache(SHADOWNAME,
1379                                                          PointerGetDatum(username),
1380                                                          0, 0, 0);
1381         if (!HeapTupleIsValid(userTup))
1382                 elog(ERROR, "user \"%s\" does not exist", username);
1383
1384         result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
1385
1386         ReleaseSysCache(userTup);
1387
1388         return result;
1389 }