OSDN Git Service

Fix comments that were mis-wrapped, for Tom Lane.
[pg-rex/syncrep.git] / 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-2001, 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.52 2001/03/23 04:49:55 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_operator.h"
20 #include "catalog/pg_proc.h"
21 #include "catalog/pg_type.h"
22 #include "utils/lsyscache.h"
23 #include "utils/syscache.h"
24
25 /*                              ---------- AMOP CACHES ----------                                                */
26
27 /*
28  * op_class
29  *
30  *              Return t iff operator 'opno' is in operator class 'opclass' for
31  *              access method 'amopid'.
32  */
33 bool
34 op_class(Oid opno, Oid opclass, Oid amopid)
35 {
36         return SearchSysCacheExists(AMOPOPID,
37                                                                 ObjectIdGetDatum(opclass),
38                                                                 ObjectIdGetDatum(opno),
39                                                                 ObjectIdGetDatum(amopid),
40                                                                 0);
41 }
42
43 /*                              ---------- ATTRIBUTE CACHES ----------                                   */
44
45 /*
46  * get_attname
47  *
48  *              Given the relation id and the attribute number,
49  *              return the "attname" field from the attribute relation.
50  *
51  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
52  */
53 char *
54 get_attname(Oid relid, AttrNumber attnum)
55 {
56         HeapTuple       tp;
57
58         tp = SearchSysCache(ATTNUM,
59                                                 ObjectIdGetDatum(relid),
60                                                 Int16GetDatum(attnum),
61                                                 0, 0);
62         if (HeapTupleIsValid(tp))
63         {
64                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
65                 char       *result;
66
67                 result = pstrdup(NameStr(att_tup->attname));
68                 ReleaseSysCache(tp);
69                 return result;
70         }
71         else
72                 return NULL;
73 }
74
75 /*
76  * get_attnum
77  *
78  *              Given the relation id and the attribute name,
79  *              return the "attnum" field from the attribute relation.
80  */
81 AttrNumber
82 get_attnum(Oid relid, char *attname)
83 {
84         HeapTuple       tp;
85
86         tp = SearchSysCache(ATTNAME,
87                                                 ObjectIdGetDatum(relid),
88                                                 PointerGetDatum(attname),
89                                                 0, 0);
90         if (HeapTupleIsValid(tp))
91         {
92                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
93                 AttrNumber      result;
94
95                 result = att_tup->attnum;
96                 ReleaseSysCache(tp);
97                 return result;
98         }
99         else
100                 return InvalidAttrNumber;
101 }
102
103 /*
104  * get_atttype
105  *
106  *              Given the relation OID and the attribute number with the relation,
107  *              return the attribute type OID.
108  */
109 Oid
110 get_atttype(Oid relid, AttrNumber attnum)
111 {
112         HeapTuple       tp;
113
114         tp = SearchSysCache(ATTNUM,
115                                                 ObjectIdGetDatum(relid),
116                                                 Int16GetDatum(attnum),
117                                                 0, 0);
118         if (HeapTupleIsValid(tp))
119         {
120                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
121                 Oid                     result;
122
123                 result = att_tup->atttypid;
124                 ReleaseSysCache(tp);
125                 return result;
126         }
127         else
128                 return InvalidOid;
129 }
130
131 /* This routine uses the attname instead of the attnum because it
132  * replaces the routine find_atttype, which is called sometimes when
133  * only the attname, not the attno, is available.
134  */
135 bool
136 get_attisset(Oid relid, char *attname)
137 {
138         HeapTuple       tp;
139
140         tp = SearchSysCache(ATTNAME,
141                                                 ObjectIdGetDatum(relid),
142                                                 PointerGetDatum(attname),
143                                                 0, 0);
144         if (HeapTupleIsValid(tp))
145         {
146                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
147                 bool            result;
148
149                 result = att_tup->attisset;
150                 ReleaseSysCache(tp);
151                 return result;
152         }
153         else
154                 return false;
155 }
156
157 /*
158  * get_atttypmod
159  *
160  *              Given the relation id and the attribute number,
161  *              return the "atttypmod" field from the attribute relation.
162  */
163 int32
164 get_atttypmod(Oid relid, AttrNumber attnum)
165 {
166         HeapTuple       tp;
167
168         tp = SearchSysCache(ATTNUM,
169                                                 ObjectIdGetDatum(relid),
170                                                 Int16GetDatum(attnum),
171                                                 0, 0);
172         if (HeapTupleIsValid(tp))
173         {
174                 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
175                 int32           result;
176
177                 result = att_tup->atttypmod;
178                 ReleaseSysCache(tp);
179                 return result;
180         }
181         else
182                 return -1;
183 }
184
185 /*
186  * get_attdispersion
187  *
188  *        Retrieve the dispersion statistic for an attribute,
189  *        or produce an estimate if no info is available.
190  *
191  * min_estimate is the minimum estimate to return if insufficient data
192  * is available to produce a reliable value.  This value may vary
193  * depending on context.  (For example, when deciding whether it is
194  * safe to use a hashjoin, we want to be more conservative than when
195  * estimating the number of tuples produced by an equijoin.)
196  */
197 double
198 get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate)
199 {
200         HeapTuple       atp;
201         Form_pg_attribute att_tup;
202         double          dispersion;
203         Oid                     atttypid;
204         int32           ntuples;
205
206         atp = SearchSysCache(ATTNUM,
207                                                  ObjectIdGetDatum(relid),
208                                                  Int16GetDatum(attnum),
209                                                  0, 0);
210         if (!HeapTupleIsValid(atp))
211         {
212                 /* this should not happen */
213                 elog(ERROR, "get_attdispersion: no attribute tuple %u %d",
214                          relid, attnum);
215                 return min_estimate;
216         }
217
218         att_tup = (Form_pg_attribute) GETSTRUCT(atp);
219
220         dispersion = att_tup->attdispersion;
221         atttypid = att_tup->atttypid;
222
223         ReleaseSysCache(atp);
224
225         if (dispersion > 0.0)
226                 return dispersion;              /* we have a specific estimate from VACUUM */
227
228         /*
229          * Special-case boolean columns: the dispersion of a boolean is highly
230          * unlikely to be anywhere near 1/numtuples, instead it's probably
231          * more like 0.5.
232          *
233          * Are there any other cases we should wire in special estimates for?
234          */
235         if (atttypid == BOOLOID)
236                 return 0.5;
237
238         /*
239          * Dispersion is either 0 (no data available) or -1 (dispersion is
240          * 1/numtuples).  Either way, we need the relation size.
241          */
242
243         atp = SearchSysCache(RELOID,
244                                                  ObjectIdGetDatum(relid),
245                                                  0, 0, 0);
246         if (!HeapTupleIsValid(atp))
247         {
248                 /* this should not happen */
249                 elog(ERROR, "get_attdispersion: no relation tuple %u", relid);
250                 return min_estimate;
251         }
252
253         ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;
254
255         ReleaseSysCache(atp);
256
257         if (ntuples == 0)
258                 return min_estimate;    /* no data available */
259
260         if (dispersion < 0.0)           /* VACUUM thinks there are no duplicates */
261                 return 1.0 / (double) ntuples;
262
263         /*
264          * VACUUM ANALYZE does not compute dispersion for system attributes,
265          * but some of them can reasonably be assumed unique anyway.
266          */
267         if (attnum == ObjectIdAttributeNumber ||
268                 attnum == SelfItemPointerAttributeNumber)
269                 return 1.0 / (double) ntuples;
270         if (attnum == TableOidAttributeNumber)
271                 return 1.0;
272
273         /*
274          * VACUUM ANALYZE has not been run for this table. Produce an estimate
275          * of 1/numtuples.  This may produce unreasonably small estimates for
276          * large tables, so limit the estimate to no less than min_estimate.
277          */
278         dispersion = 1.0 / (double) ntuples;
279         if (dispersion < min_estimate)
280                 dispersion = min_estimate;
281
282         return dispersion;
283 }
284
285 /*                              ---------- INDEX CACHE ----------                                                */
286
287 /*              watch this space...
288  */
289
290 /*                              ---------- OPERATOR CACHE ----------                                     */
291
292 /*
293  * get_opcode
294  *
295  *              Returns the regproc id of the routine used to implement an
296  *              operator given the operator oid.
297  */
298 RegProcedure
299 get_opcode(Oid opno)
300 {
301         HeapTuple       tp;
302
303         tp = SearchSysCache(OPEROID,
304                                                 ObjectIdGetDatum(opno),
305                                                 0, 0, 0);
306         if (HeapTupleIsValid(tp))
307         {
308                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
309                 RegProcedure result;
310
311                 result = optup->oprcode;
312                 ReleaseSysCache(tp);
313                 return result;
314         }
315         else
316                 return (RegProcedure) InvalidOid;
317 }
318
319 /*
320  * get_opname
321  *        returns the name of the operator with the given opno
322  *
323  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
324  */
325 char *
326 get_opname(Oid opno)
327 {
328         HeapTuple       tp;
329
330         tp = SearchSysCache(OPEROID,
331                                                 ObjectIdGetDatum(opno),
332                                                 0, 0, 0);
333         if (HeapTupleIsValid(tp))
334         {
335                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
336                 char       *result;
337
338                 result = pstrdup(NameStr(optup->oprname));
339                 ReleaseSysCache(tp);
340                 return result;
341         }
342         else
343                 return NULL;
344 }
345
346 /*
347  * op_mergejoinable
348  *
349  *              Returns the left and right sort operators and types corresponding to a
350  *              mergejoinable operator, or nil if the operator is not mergejoinable.
351  */
352 bool
353 op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
354 {
355         HeapTuple       tp;
356         bool            result = false;
357
358         tp = SearchSysCache(OPEROID,
359                                                 ObjectIdGetDatum(opno),
360                                                 0, 0, 0);
361         if (HeapTupleIsValid(tp))
362         {
363                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
364
365                 if (optup->oprlsortop &&
366                         optup->oprrsortop &&
367                         optup->oprleft == ltype &&
368                         optup->oprright == rtype)
369                 {
370                         *leftOp = optup->oprlsortop;
371                         *rightOp = optup->oprrsortop;
372                         result = true;
373                 }
374                 ReleaseSysCache(tp);
375         }
376         return result;
377 }
378
379 /*
380  * op_hashjoinable
381  *
382  * Returns the hash operator corresponding to a hashjoinable operator,
383  * or InvalidOid if the operator is not hashjoinable.
384  */
385 Oid
386 op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
387 {
388         HeapTuple       tp;
389         Oid                     result = InvalidOid;
390
391         tp = SearchSysCache(OPEROID,
392                                                 ObjectIdGetDatum(opno),
393                                                 0, 0, 0);
394         if (HeapTupleIsValid(tp))
395         {
396                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
397
398                 if (optup->oprcanhash &&
399                         optup->oprleft == ltype &&
400                         optup->oprright == rtype)
401                         result = opno;
402                 ReleaseSysCache(tp);
403         }
404         return result;
405 }
406
407 /*
408  * op_iscachable
409  *
410  * Get the proiscachable flag for the operator's underlying function.
411  */
412 bool
413 op_iscachable(Oid opno)
414 {
415         RegProcedure funcid = get_opcode(opno);
416
417         if (funcid == (RegProcedure) InvalidOid)
418                 elog(ERROR, "Operator OID %u does not exist", opno);
419
420         return func_iscachable((Oid) funcid);
421 }
422
423 /*
424  * get_commutator
425  *
426  *              Returns the corresponding commutator of an operator.
427  */
428 Oid
429 get_commutator(Oid opno)
430 {
431         HeapTuple       tp;
432
433         tp = SearchSysCache(OPEROID,
434                                                 ObjectIdGetDatum(opno),
435                                                 0, 0, 0);
436         if (HeapTupleIsValid(tp))
437         {
438                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
439                 Oid                     result;
440
441                 result = optup->oprcom;
442                 ReleaseSysCache(tp);
443                 return result;
444         }
445         else
446                 return InvalidOid;
447 }
448
449 /*
450  * get_negator
451  *
452  *              Returns the corresponding negator of an operator.
453  */
454 Oid
455 get_negator(Oid opno)
456 {
457         HeapTuple       tp;
458
459         tp = SearchSysCache(OPEROID,
460                                                 ObjectIdGetDatum(opno),
461                                                 0, 0, 0);
462         if (HeapTupleIsValid(tp))
463         {
464                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
465                 Oid                     result;
466
467                 result = optup->oprnegate;
468                 ReleaseSysCache(tp);
469                 return result;
470         }
471         else
472                 return InvalidOid;
473 }
474
475 /*
476  * get_oprrest
477  *
478  *              Returns procedure id for computing selectivity of an operator.
479  */
480 RegProcedure
481 get_oprrest(Oid opno)
482 {
483         HeapTuple       tp;
484
485         tp = SearchSysCache(OPEROID,
486                                                 ObjectIdGetDatum(opno),
487                                                 0, 0, 0);
488         if (HeapTupleIsValid(tp))
489         {
490                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
491                 RegProcedure result;
492
493                 result = optup->oprrest;
494                 ReleaseSysCache(tp);
495                 return result;
496         }
497         else
498                 return (RegProcedure) InvalidOid;
499 }
500
501 /*
502  * get_oprjoin
503  *
504  *              Returns procedure id for computing selectivity of a join.
505  */
506 RegProcedure
507 get_oprjoin(Oid opno)
508 {
509         HeapTuple       tp;
510
511         tp = SearchSysCache(OPEROID,
512                                                 ObjectIdGetDatum(opno),
513                                                 0, 0, 0);
514         if (HeapTupleIsValid(tp))
515         {
516                 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
517                 RegProcedure result;
518
519                 result = optup->oprjoin;
520                 ReleaseSysCache(tp);
521                 return result;
522         }
523         else
524                 return (RegProcedure) InvalidOid;
525 }
526
527 /*                              ---------- FUNCTION CACHE ----------                                     */
528
529 /*
530  * get_func_rettype
531  *              Given procedure id, return the function's result type.
532  */
533 Oid
534 get_func_rettype(Oid funcid)
535 {
536         HeapTuple       tp;
537         Oid                     result;
538
539         tp = SearchSysCache(PROCOID,
540                                                 ObjectIdGetDatum(funcid),
541                                                 0, 0, 0);
542         if (!HeapTupleIsValid(tp))
543                 elog(ERROR, "Function OID %u does not exist", funcid);
544
545         result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
546         ReleaseSysCache(tp);
547         return result;
548 }
549
550 /*
551  * func_iscachable
552  *              Given procedure id, return the function's proiscachable flag.
553  */
554 bool
555 func_iscachable(Oid funcid)
556 {
557         HeapTuple       tp;
558         bool            result;
559
560         tp = SearchSysCache(PROCOID,
561                                                 ObjectIdGetDatum(funcid),
562                                                 0, 0, 0);
563         if (!HeapTupleIsValid(tp))
564                 elog(ERROR, "Function OID %u does not exist", funcid);
565
566         result = ((Form_pg_proc) GETSTRUCT(tp))->proiscachable;
567         ReleaseSysCache(tp);
568         return result;
569 }
570
571 /*                              ---------- RELATION CACHE ----------                                     */
572
573 #ifdef NOT_USED
574 /*
575  * get_relnatts
576  *
577  *              Returns the number of attributes for a given relation.
578  */
579 int
580 get_relnatts(Oid relid)
581 {
582         HeapTuple       tp;
583
584         tp = SearchSysCache(RELOID,
585                                                 ObjectIdGetDatum(relid),
586                                                 0, 0, 0);
587         if (HeapTupleIsValid(tp))
588         {
589                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
590                 int                     result;
591
592                 result = reltup->relnatts;
593                 ReleaseSysCache(tp);
594                 return result;
595         }
596         else
597                 return InvalidAttrNumber;
598 }
599
600 #endif
601
602 /*
603  * get_rel_name
604  *
605  *              Returns the name of a given relation.
606  *
607  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
608  */
609 char *
610 get_rel_name(Oid relid)
611 {
612         HeapTuple       tp;
613
614         tp = SearchSysCache(RELOID,
615                                                 ObjectIdGetDatum(relid),
616                                                 0, 0, 0);
617         if (HeapTupleIsValid(tp))
618         {
619                 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
620                 char       *result;
621
622                 result = pstrdup(NameStr(reltup->relname));
623                 ReleaseSysCache(tp);
624                 return result;
625         }
626         else
627                 return NULL;
628 }
629
630 /*                              ---------- TYPE CACHE ----------                                                 */
631
632 /*
633  * get_typlen
634  *
635  *              Given the type OID, return the length of the type.
636  */
637 int16
638 get_typlen(Oid typid)
639 {
640         HeapTuple       tp;
641
642         tp = SearchSysCache(TYPEOID,
643                                                 ObjectIdGetDatum(typid),
644                                                 0, 0, 0);
645         if (HeapTupleIsValid(tp))
646         {
647                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
648                 int16           result;
649
650                 result = typtup->typlen;
651                 ReleaseSysCache(tp);
652                 return result;
653         }
654         else
655                 return 0;
656 }
657
658 /*
659  * get_typbyval
660  *
661  *              Given the type OID, determine whether the type is returned by value or
662  *              not.  Returns true if by value, false if by reference.
663  */
664 bool
665 get_typbyval(Oid typid)
666 {
667         HeapTuple       tp;
668
669         tp = SearchSysCache(TYPEOID,
670                                                 ObjectIdGetDatum(typid),
671                                                 0, 0, 0);
672         if (HeapTupleIsValid(tp))
673         {
674                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
675                 bool            result;
676
677                 result = typtup->typbyval;
678                 ReleaseSysCache(tp);
679                 return result;
680         }
681         else
682                 return false;
683 }
684
685 /*
686  * get_typlenbyval
687  *
688  *              A two-fer: given the type OID, return both typlen and typbyval.
689  *
690  *              Since both pieces of info are needed to know how to copy a Datum,
691  *              many places need both.  Might as well get them with one cache lookup
692  *              instead of two.  Also, this routine raises an error instead of
693  *              returning a bogus value when given a bad type OID.
694  */
695 void
696 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
697 {
698         HeapTuple       tp;
699         Form_pg_type typtup;
700
701         tp = SearchSysCache(TYPEOID,
702                                                 ObjectIdGetDatum(typid),
703                                                 0, 0, 0);
704         if (!HeapTupleIsValid(tp))
705                 elog(ERROR, "cache lookup failed for type %u", typid);
706         typtup = (Form_pg_type) GETSTRUCT(tp);
707         *typlen = typtup->typlen;
708         *typbyval = typtup->typbyval;
709         ReleaseSysCache(tp);
710 }
711
712 #ifdef NOT_USED
713 char
714 get_typalign(Oid typid)
715 {
716         HeapTuple       tp;
717
718         tp = SearchSysCache(TYPEOID,
719                                                 ObjectIdGetDatum(typid),
720                                                 0, 0, 0);
721         if (HeapTupleIsValid(tp))
722         {
723                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
724                 char            result;
725
726                 result = typtup->typalign;
727                 ReleaseSysCache(tp);
728                 return result;
729         }
730         else
731                 return 'i';
732 }
733
734 #endif
735
736 char
737 get_typstorage(Oid typid)
738 {
739         HeapTuple       tp;
740
741         tp = SearchSysCache(TYPEOID,
742                                                 ObjectIdGetDatum(typid),
743                                                 0, 0, 0);
744         if (HeapTupleIsValid(tp))
745         {
746                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
747                 char            result;
748
749                 result = typtup->typstorage;
750                 ReleaseSysCache(tp);
751                 return result;
752         }
753         else
754                 return 'p';
755 }
756
757 /*
758  * get_typdefault
759  *
760  *        Given a type OID, return the typdefault field associated with that
761  *        type, or Datum(NULL) if there is no typdefault.  (This implies
762  *        that pass-by-value types can't have a default value that has
763  *        a representation of zero.  Not worth fixing now.)
764  *        The result points to palloc'd storage for non-pass-by-value types.
765  */
766 Datum
767 get_typdefault(Oid typid)
768 {
769         HeapTuple       typeTuple;
770         Form_pg_type type;
771         struct varlena *typDefault;
772         bool            isNull;
773         int32           dataSize;
774         int32           typLen;
775         bool            typByVal;
776         Datum           returnValue;
777
778         typeTuple = SearchSysCache(TYPEOID,
779                                                            ObjectIdGetDatum(typid),
780                                                            0, 0, 0);
781
782         if (!HeapTupleIsValid(typeTuple))
783                 elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
784
785         type = (Form_pg_type) GETSTRUCT(typeTuple);
786
787         /*
788          * First, see if there is a non-null typdefault field (usually there
789          * isn't)
790          */
791         typDefault = (struct varlena *)
792                 DatumGetPointer(SysCacheGetAttr(TYPEOID,
793                                                                                 typeTuple,
794                                                                                 Anum_pg_type_typdefault,
795                                                                                 &isNull));
796
797         if (isNull)
798         {
799                 ReleaseSysCache(typeTuple);
800                 return PointerGetDatum(NULL);
801         }
802
803         /*
804          * Otherwise, extract/copy the value.
805          */
806         dataSize = VARSIZE(typDefault) - VARHDRSZ;
807         typLen = type->typlen;
808         typByVal = type->typbyval;
809
810         if (typByVal)
811         {
812                 if (dataSize == typLen)
813                         returnValue = fetch_att(VARDATA(typDefault), typByVal, typLen);
814                 else
815                         returnValue = PointerGetDatum(NULL);
816         }
817         else if (typLen < 0)
818         {
819                 /* variable-size type */
820                 if (dataSize < 0)
821                         returnValue = PointerGetDatum(NULL);
822                 else
823                 {
824                         returnValue = PointerGetDatum(palloc(VARSIZE(typDefault)));
825                         memcpy((char *) DatumGetPointer(returnValue),
826                                    (char *) typDefault,
827                                    (int) VARSIZE(typDefault));
828                 }
829         }
830         else
831         {
832                 /* fixed-size pass-by-ref type */
833                 if (dataSize != typLen)
834                         returnValue = PointerGetDatum(NULL);
835                 else
836                 {
837                         returnValue = PointerGetDatum(palloc(dataSize));
838                         memcpy((char *) DatumGetPointer(returnValue),
839                                    VARDATA(typDefault),
840                                    (int) dataSize);
841                 }
842         }
843
844         ReleaseSysCache(typeTuple);
845
846         return returnValue;
847 }
848
849 /*
850  * get_typtype
851  *
852  *              Given the type OID, find if it is a basic type, a named relation
853  *              or the generic type 'relation'.
854  *              It returns the null char if the cache lookup fails...
855  */
856 #ifdef NOT_USED
857 char
858 get_typtype(Oid typid)
859 {
860         HeapTuple       tp;
861
862         tp = SearchSysCache(TYPEOID,
863                                                 ObjectIdGetDatum(typid),
864                                                 0, 0, 0);
865         if (HeapTupleIsValid(tp))
866         {
867                 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
868                 char            result;
869
870                 result = typtup->typtype;
871                 ReleaseSysCache(tp);
872                 return result;
873         }
874         else
875                 return '\0';
876 }
877
878 #endif