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