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