Revert dubious message wording change.
[PostgreSQL.git] / src / backend / utils / cache / lsyscache.c
blob8c7439f02bf586b827076c9c7f72f428dbb5f6a9
1 /*-------------------------------------------------------------------------
3 * lsyscache.c
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * IDENTIFICATION
10 * $PostgreSQL$
12 * NOTES
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
16 #include "postgres.h"
18 #include "access/hash.h"
19 #include "access/nbtree.h"
20 #include "bootstrap/bootstrap.h"
21 #include "catalog/pg_amop.h"
22 #include "catalog/pg_amproc.h"
23 #include "catalog/pg_constraint.h"
24 #include "catalog/pg_namespace.h"
25 #include "catalog/pg_opclass.h"
26 #include "catalog/pg_operator.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_statistic.h"
29 #include "catalog/pg_type.h"
30 #include "miscadmin.h"
31 #include "nodes/makefuncs.h"
32 #include "utils/array.h"
33 #include "utils/builtins.h"
34 #include "utils/datum.h"
35 #include "utils/lsyscache.h"
36 #include "utils/syscache.h"
38 /* Hook for plugins to get control in get_attavgwidth() */
39 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
42 /* ---------- AMOP CACHES ---------- */
45 * op_in_opfamily
47 * Return t iff operator 'opno' is in operator family 'opfamily'.
49 bool
50 op_in_opfamily(Oid opno, Oid opfamily)
52 return SearchSysCacheExists(AMOPOPID,
53 ObjectIdGetDatum(opno),
54 ObjectIdGetDatum(opfamily),
55 0, 0);
59 * get_op_opfamily_strategy
61 * Get the operator's strategy number within the specified opfamily,
62 * or 0 if it's not a member of the opfamily.
64 int
65 get_op_opfamily_strategy(Oid opno, Oid opfamily)
67 HeapTuple tp;
68 Form_pg_amop amop_tup;
69 int result;
71 tp = SearchSysCache(AMOPOPID,
72 ObjectIdGetDatum(opno),
73 ObjectIdGetDatum(opfamily),
74 0, 0);
75 if (!HeapTupleIsValid(tp))
76 return 0;
77 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
78 result = amop_tup->amopstrategy;
79 ReleaseSysCache(tp);
80 return result;
84 * get_op_opfamily_properties
86 * Get the operator's strategy number and declared input data types
87 * within the specified opfamily.
89 * Caller should already have verified that opno is a member of opfamily,
90 * therefore we raise an error if the tuple is not found.
92 void
93 get_op_opfamily_properties(Oid opno, Oid opfamily,
94 int *strategy,
95 Oid *lefttype,
96 Oid *righttype)
98 HeapTuple tp;
99 Form_pg_amop amop_tup;
101 tp = SearchSysCache(AMOPOPID,
102 ObjectIdGetDatum(opno),
103 ObjectIdGetDatum(opfamily),
104 0, 0);
105 if (!HeapTupleIsValid(tp))
106 elog(ERROR, "operator %u is not a member of opfamily %u",
107 opno, opfamily);
108 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
109 *strategy = amop_tup->amopstrategy;
110 *lefttype = amop_tup->amoplefttype;
111 *righttype = amop_tup->amoprighttype;
112 ReleaseSysCache(tp);
116 * get_opfamily_member
117 * Get the OID of the operator that implements the specified strategy
118 * with the specified datatypes for the specified opfamily.
120 * Returns InvalidOid if there is no pg_amop entry for the given keys.
123 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
124 int16 strategy)
126 HeapTuple tp;
127 Form_pg_amop amop_tup;
128 Oid result;
130 tp = SearchSysCache(AMOPSTRATEGY,
131 ObjectIdGetDatum(opfamily),
132 ObjectIdGetDatum(lefttype),
133 ObjectIdGetDatum(righttype),
134 Int16GetDatum(strategy));
135 if (!HeapTupleIsValid(tp))
136 return InvalidOid;
137 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
138 result = amop_tup->amopopr;
139 ReleaseSysCache(tp);
140 return result;
144 * get_ordering_op_properties
145 * Given the OID of an ordering operator (a btree "<" or ">" operator),
146 * determine its opfamily, its declared input datatype, and its
147 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
149 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
150 * (This indicates that the operator is not a valid ordering operator.)
152 * Note: the operator could be registered in multiple families, for example
153 * if someone were to build a "reverse sort" opfamily. This would result in
154 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
155 * or NULLS LAST, as well as inefficient planning due to failure to match up
156 * pathkeys that should be the same. So we want a determinate result here.
157 * Because of the way the syscache search works, we'll use the interpretation
158 * associated with the opfamily with smallest OID, which is probably
159 * determinate enough. Since there is no longer any particularly good reason
160 * to build reverse-sort opfamilies, it doesn't seem worth expending any
161 * additional effort on ensuring consistency.
163 bool
164 get_ordering_op_properties(Oid opno,
165 Oid *opfamily, Oid *opcintype, int16 *strategy)
167 bool result = false;
168 CatCList *catlist;
169 int i;
171 /* ensure outputs are initialized on failure */
172 *opfamily = InvalidOid;
173 *opcintype = InvalidOid;
174 *strategy = 0;
177 * Search pg_amop to see if the target operator is registered as the "<"
178 * or ">" operator of any btree opfamily.
180 catlist = SearchSysCacheList(AMOPOPID, 1,
181 ObjectIdGetDatum(opno),
182 0, 0, 0);
184 for (i = 0; i < catlist->n_members; i++)
186 HeapTuple tuple = &catlist->members[i]->tuple;
187 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
189 /* must be btree */
190 if (aform->amopmethod != BTREE_AM_OID)
191 continue;
193 if (aform->amopstrategy == BTLessStrategyNumber ||
194 aform->amopstrategy == BTGreaterStrategyNumber)
196 /* Found it ... should have consistent input types */
197 if (aform->amoplefttype == aform->amoprighttype)
199 /* Found a suitable opfamily, return info */
200 *opfamily = aform->amopfamily;
201 *opcintype = aform->amoplefttype;
202 *strategy = aform->amopstrategy;
203 result = true;
204 break;
209 ReleaseSysCacheList(catlist);
211 return result;
215 * get_compare_function_for_ordering_op
216 * Get the OID of the datatype-specific btree comparison function
217 * associated with an ordering operator (a "<" or ">" operator).
219 * *cmpfunc receives the comparison function OID.
220 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
221 * (indicating the comparison result must be negated before use).
223 * Returns TRUE if successful, FALSE if no btree function can be found.
224 * (This indicates that the operator is not a valid ordering operator.)
226 bool
227 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
229 Oid opfamily;
230 Oid opcintype;
231 int16 strategy;
233 /* Find the operator in pg_amop */
234 if (get_ordering_op_properties(opno,
235 &opfamily, &opcintype, &strategy))
237 /* Found a suitable opfamily, get matching support function */
238 *cmpfunc = get_opfamily_proc(opfamily,
239 opcintype,
240 opcintype,
241 BTORDER_PROC);
243 if (!OidIsValid(*cmpfunc)) /* should not happen */
244 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
245 BTORDER_PROC, opcintype, opcintype, opfamily);
246 *reverse = (strategy == BTGreaterStrategyNumber);
247 return true;
250 /* ensure outputs are set on failure */
251 *cmpfunc = InvalidOid;
253 *reverse = false;
254 return false;
258 * get_equality_op_for_ordering_op
259 * Get the OID of the datatype-specific btree equality operator
260 * associated with an ordering operator (a "<" or ">" operator).
262 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
263 * TRUE if it's ">"
265 * Returns InvalidOid if no matching equality operator can be found.
266 * (This indicates that the operator is not a valid ordering operator.)
269 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
271 Oid result = InvalidOid;
272 Oid opfamily;
273 Oid opcintype;
274 int16 strategy;
276 /* Find the operator in pg_amop */
277 if (get_ordering_op_properties(opno,
278 &opfamily, &opcintype, &strategy))
280 /* Found a suitable opfamily, get matching equality operator */
281 result = get_opfamily_member(opfamily,
282 opcintype,
283 opcintype,
284 BTEqualStrategyNumber);
285 if (reverse)
286 *reverse = (strategy == BTGreaterStrategyNumber);
289 return result;
293 * get_ordering_op_for_equality_op
294 * Get the OID of a datatype-specific btree ordering operator
295 * associated with an equality operator. (If there are multiple
296 * possibilities, assume any one will do.)
298 * This function is used when we have to sort data before unique-ifying,
299 * and don't much care which sorting op is used as long as it's compatible
300 * with the intended equality operator. Since we need a sorting operator,
301 * it should be single-data-type even if the given operator is cross-type.
302 * The caller specifies whether to find an op for the LHS or RHS data type.
304 * Returns InvalidOid if no matching ordering operator can be found.
307 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
309 Oid result = InvalidOid;
310 CatCList *catlist;
311 int i;
314 * Search pg_amop to see if the target operator is registered as the "="
315 * operator of any btree opfamily.
317 catlist = SearchSysCacheList(AMOPOPID, 1,
318 ObjectIdGetDatum(opno),
319 0, 0, 0);
321 for (i = 0; i < catlist->n_members; i++)
323 HeapTuple tuple = &catlist->members[i]->tuple;
324 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
326 /* must be btree */
327 if (aform->amopmethod != BTREE_AM_OID)
328 continue;
330 if (aform->amopstrategy == BTEqualStrategyNumber)
332 /* Found a suitable opfamily, get matching ordering operator */
333 Oid typid;
335 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
336 result = get_opfamily_member(aform->amopfamily,
337 typid, typid,
338 BTLessStrategyNumber);
339 if (OidIsValid(result))
340 break;
341 /* failure probably shouldn't happen, but keep looking if so */
345 ReleaseSysCacheList(catlist);
347 return result;
351 * get_mergejoin_opfamilies
352 * Given a putatively mergejoinable operator, return a list of the OIDs
353 * of the btree opfamilies in which it represents equality.
355 * It is possible (though at present unusual) for an operator to be equality
356 * in more than one opfamily, hence the result is a list. This also lets us
357 * return NIL if the operator is not found in any opfamilies.
359 * The planner currently uses simple equal() tests to compare the lists
360 * returned by this function, which makes the list order relevant, though
361 * strictly speaking it should not be. Because of the way syscache list
362 * searches are handled, in normal operation the result will be sorted by OID
363 * so everything works fine. If running with system index usage disabled,
364 * the result ordering is unspecified and hence the planner might fail to
365 * recognize optimization opportunities ... but that's hardly a scenario in
366 * which performance is good anyway, so there's no point in expending code
367 * or cycles here to guarantee the ordering in that case.
369 List *
370 get_mergejoin_opfamilies(Oid opno)
372 List *result = NIL;
373 CatCList *catlist;
374 int i;
377 * Search pg_amop to see if the target operator is registered as the "="
378 * operator of any btree opfamily.
380 catlist = SearchSysCacheList(AMOPOPID, 1,
381 ObjectIdGetDatum(opno),
382 0, 0, 0);
384 for (i = 0; i < catlist->n_members; i++)
386 HeapTuple tuple = &catlist->members[i]->tuple;
387 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
389 /* must be btree equality */
390 if (aform->amopmethod == BTREE_AM_OID &&
391 aform->amopstrategy == BTEqualStrategyNumber)
392 result = lappend_oid(result, aform->amopfamily);
395 ReleaseSysCacheList(catlist);
397 return result;
401 * get_compatible_hash_operators
402 * Get the OID(s) of hash equality operator(s) compatible with the given
403 * operator, but operating on its LHS and/or RHS datatype.
405 * An operator for the LHS type is sought and returned into *lhs_opno if
406 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
407 * and returned into *rhs_opno if rhs_opno isn't NULL.
409 * If the given operator is not cross-type, the results should be the same
410 * operator, but in cross-type situations they will be different.
412 * Returns true if able to find the requested operator(s), false if not.
413 * (This indicates that the operator should not have been marked oprcanhash.)
415 bool
416 get_compatible_hash_operators(Oid opno,
417 Oid *lhs_opno, Oid *rhs_opno)
419 bool result = false;
420 CatCList *catlist;
421 int i;
423 /* Ensure output args are initialized on failure */
424 if (lhs_opno)
425 *lhs_opno = InvalidOid;
426 if (rhs_opno)
427 *rhs_opno = InvalidOid;
430 * Search pg_amop to see if the target operator is registered as the "="
431 * operator of any hash opfamily. If the operator is registered in
432 * multiple opfamilies, assume we can use any one.
434 catlist = SearchSysCacheList(AMOPOPID, 1,
435 ObjectIdGetDatum(opno),
436 0, 0, 0);
438 for (i = 0; i < catlist->n_members; i++)
440 HeapTuple tuple = &catlist->members[i]->tuple;
441 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
443 if (aform->amopmethod == HASH_AM_OID &&
444 aform->amopstrategy == HTEqualStrategyNumber)
446 /* No extra lookup needed if given operator is single-type */
447 if (aform->amoplefttype == aform->amoprighttype)
449 if (lhs_opno)
450 *lhs_opno = opno;
451 if (rhs_opno)
452 *rhs_opno = opno;
453 result = true;
454 break;
458 * Get the matching single-type operator(s). Failure probably
459 * shouldn't happen --- it implies a bogus opfamily --- but
460 * continue looking if so.
462 if (lhs_opno)
464 *lhs_opno = get_opfamily_member(aform->amopfamily,
465 aform->amoplefttype,
466 aform->amoplefttype,
467 HTEqualStrategyNumber);
468 if (!OidIsValid(*lhs_opno))
469 continue;
470 /* Matching LHS found, done if caller doesn't want RHS */
471 if (!rhs_opno)
473 result = true;
474 break;
477 if (rhs_opno)
479 *rhs_opno = get_opfamily_member(aform->amopfamily,
480 aform->amoprighttype,
481 aform->amoprighttype,
482 HTEqualStrategyNumber);
483 if (!OidIsValid(*rhs_opno))
485 /* Forget any LHS operator from this opfamily */
486 if (lhs_opno)
487 *lhs_opno = InvalidOid;
488 continue;
490 /* Matching RHS found, so done */
491 result = true;
492 break;
497 ReleaseSysCacheList(catlist);
499 return result;
503 * get_op_hash_functions
504 * Get the OID(s) of hash support function(s) compatible with the given
505 * operator, operating on its LHS and/or RHS datatype as required.
507 * A function for the LHS type is sought and returned into *lhs_procno if
508 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
509 * and returned into *rhs_procno if rhs_procno isn't NULL.
511 * If the given operator is not cross-type, the results should be the same
512 * function, but in cross-type situations they will be different.
514 * Returns true if able to find the requested function(s), false if not.
515 * (This indicates that the operator should not have been marked oprcanhash.)
517 bool
518 get_op_hash_functions(Oid opno,
519 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
521 bool result = false;
522 CatCList *catlist;
523 int i;
525 /* Ensure output args are initialized on failure */
526 if (lhs_procno)
527 *lhs_procno = InvalidOid;
528 if (rhs_procno)
529 *rhs_procno = InvalidOid;
532 * Search pg_amop to see if the target operator is registered as the "="
533 * operator of any hash opfamily. If the operator is registered in
534 * multiple opfamilies, assume we can use any one.
536 catlist = SearchSysCacheList(AMOPOPID, 1,
537 ObjectIdGetDatum(opno),
538 0, 0, 0);
540 for (i = 0; i < catlist->n_members; i++)
542 HeapTuple tuple = &catlist->members[i]->tuple;
543 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
545 if (aform->amopmethod == HASH_AM_OID &&
546 aform->amopstrategy == HTEqualStrategyNumber)
549 * Get the matching support function(s). Failure probably
550 * shouldn't happen --- it implies a bogus opfamily --- but
551 * continue looking if so.
553 if (lhs_procno)
555 *lhs_procno = get_opfamily_proc(aform->amopfamily,
556 aform->amoplefttype,
557 aform->amoplefttype,
558 HASHPROC);
559 if (!OidIsValid(*lhs_procno))
560 continue;
561 /* Matching LHS found, done if caller doesn't want RHS */
562 if (!rhs_procno)
564 result = true;
565 break;
567 /* Only one lookup needed if given operator is single-type */
568 if (aform->amoplefttype == aform->amoprighttype)
570 *rhs_procno = *lhs_procno;
571 result = true;
572 break;
575 if (rhs_procno)
577 *rhs_procno = get_opfamily_proc(aform->amopfamily,
578 aform->amoprighttype,
579 aform->amoprighttype,
580 HASHPROC);
581 if (!OidIsValid(*rhs_procno))
583 /* Forget any LHS function from this opfamily */
584 if (lhs_procno)
585 *lhs_procno = InvalidOid;
586 continue;
588 /* Matching RHS found, so done */
589 result = true;
590 break;
595 ReleaseSysCacheList(catlist);
597 return result;
601 * get_op_btree_interpretation
602 * Given an operator's OID, find out which btree opfamilies it belongs to,
603 * and what strategy number it has within each one. The results are
604 * returned as an OID list and a parallel integer list.
606 * In addition to the normal btree operators, we consider a <> operator to be
607 * a "member" of an opfamily if its negator is an equality operator of the
608 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
610 void
611 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
613 CatCList *catlist;
614 bool op_negated;
615 int i;
617 *opfamilies = NIL;
618 *opstrats = NIL;
621 * Find all the pg_amop entries containing the operator.
623 catlist = SearchSysCacheList(AMOPOPID, 1,
624 ObjectIdGetDatum(opno),
625 0, 0, 0);
628 * If we can't find any opfamily containing the op, perhaps it is a <>
629 * operator. See if it has a negator that is in an opfamily.
631 op_negated = false;
632 if (catlist->n_members == 0)
634 Oid op_negator = get_negator(opno);
636 if (OidIsValid(op_negator))
638 op_negated = true;
639 ReleaseSysCacheList(catlist);
640 catlist = SearchSysCacheList(AMOPOPID, 1,
641 ObjectIdGetDatum(op_negator),
642 0, 0, 0);
646 /* Now search the opfamilies */
647 for (i = 0; i < catlist->n_members; i++)
649 HeapTuple op_tuple = &catlist->members[i]->tuple;
650 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
651 Oid opfamily_id;
652 StrategyNumber op_strategy;
654 /* must be btree */
655 if (op_form->amopmethod != BTREE_AM_OID)
656 continue;
658 /* Get the operator's btree strategy number */
659 opfamily_id = op_form->amopfamily;
660 op_strategy = (StrategyNumber) op_form->amopstrategy;
661 Assert(op_strategy >= 1 && op_strategy <= 5);
663 if (op_negated)
665 /* Only consider negators that are = */
666 if (op_strategy != BTEqualStrategyNumber)
667 continue;
668 op_strategy = ROWCOMPARE_NE;
671 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
672 *opstrats = lappend_int(*opstrats, op_strategy);
675 ReleaseSysCacheList(catlist);
679 * equality_ops_are_compatible
680 * Return TRUE if the two given equality operators have compatible
681 * semantics.
683 * This is trivially true if they are the same operator. Otherwise,
684 * we look to see if they can be found in the same btree or hash opfamily.
685 * Either finding allows us to assume that they have compatible notions
686 * of equality. (The reason we need to do these pushups is that one might
687 * be a cross-type operator; for instance int24eq vs int4eq.)
689 bool
690 equality_ops_are_compatible(Oid opno1, Oid opno2)
692 bool result;
693 CatCList *catlist;
694 int i;
696 /* Easy if they're the same operator */
697 if (opno1 == opno2)
698 return true;
701 * We search through all the pg_amop entries for opno1.
703 catlist = SearchSysCacheList(AMOPOPID, 1,
704 ObjectIdGetDatum(opno1),
705 0, 0, 0);
707 result = false;
708 for (i = 0; i < catlist->n_members; i++)
710 HeapTuple op_tuple = &catlist->members[i]->tuple;
711 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
713 /* must be btree or hash */
714 if (op_form->amopmethod == BTREE_AM_OID ||
715 op_form->amopmethod == HASH_AM_OID)
717 if (op_in_opfamily(opno2, op_form->amopfamily))
719 result = true;
720 break;
725 ReleaseSysCacheList(catlist);
727 return result;
731 /* ---------- AMPROC CACHES ---------- */
734 * get_opfamily_proc
735 * Get the OID of the specified support function
736 * for the specified opfamily and datatypes.
738 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
741 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
743 HeapTuple tp;
744 Form_pg_amproc amproc_tup;
745 RegProcedure result;
747 tp = SearchSysCache(AMPROCNUM,
748 ObjectIdGetDatum(opfamily),
749 ObjectIdGetDatum(lefttype),
750 ObjectIdGetDatum(righttype),
751 Int16GetDatum(procnum));
752 if (!HeapTupleIsValid(tp))
753 return InvalidOid;
754 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
755 result = amproc_tup->amproc;
756 ReleaseSysCache(tp);
757 return result;
761 /* ---------- ATTRIBUTE CACHES ---------- */
764 * get_attname
765 * Given the relation id and the attribute number,
766 * return the "attname" field from the attribute relation.
768 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
770 char *
771 get_attname(Oid relid, AttrNumber attnum)
773 HeapTuple tp;
775 tp = SearchSysCache(ATTNUM,
776 ObjectIdGetDatum(relid),
777 Int16GetDatum(attnum),
778 0, 0);
779 if (HeapTupleIsValid(tp))
781 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
782 char *result;
784 result = pstrdup(NameStr(att_tup->attname));
785 ReleaseSysCache(tp);
786 return result;
788 else
789 return NULL;
793 * get_relid_attribute_name
795 * Same as above routine get_attname(), except that error
796 * is handled by elog() instead of returning NULL.
798 char *
799 get_relid_attribute_name(Oid relid, AttrNumber attnum)
801 char *attname;
803 attname = get_attname(relid, attnum);
804 if (attname == NULL)
805 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
806 attnum, relid);
807 return attname;
811 * get_attnum
813 * Given the relation id and the attribute name,
814 * return the "attnum" field from the attribute relation.
816 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
818 AttrNumber
819 get_attnum(Oid relid, const char *attname)
821 HeapTuple tp;
823 tp = SearchSysCacheAttName(relid, attname);
824 if (HeapTupleIsValid(tp))
826 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
827 AttrNumber result;
829 result = att_tup->attnum;
830 ReleaseSysCache(tp);
831 return result;
833 else
834 return InvalidAttrNumber;
838 * get_atttype
840 * Given the relation OID and the attribute number with the relation,
841 * return the attribute type OID.
844 get_atttype(Oid relid, AttrNumber attnum)
846 HeapTuple tp;
848 tp = SearchSysCache(ATTNUM,
849 ObjectIdGetDatum(relid),
850 Int16GetDatum(attnum),
851 0, 0);
852 if (HeapTupleIsValid(tp))
854 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
855 Oid result;
857 result = att_tup->atttypid;
858 ReleaseSysCache(tp);
859 return result;
861 else
862 return InvalidOid;
866 * get_atttypmod
868 * Given the relation id and the attribute number,
869 * return the "atttypmod" field from the attribute relation.
871 int32
872 get_atttypmod(Oid relid, AttrNumber attnum)
874 HeapTuple tp;
876 tp = SearchSysCache(ATTNUM,
877 ObjectIdGetDatum(relid),
878 Int16GetDatum(attnum),
879 0, 0);
880 if (HeapTupleIsValid(tp))
882 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
883 int32 result;
885 result = att_tup->atttypmod;
886 ReleaseSysCache(tp);
887 return result;
889 else
890 return -1;
894 * get_atttypetypmod
896 * A two-fer: given the relation id and the attribute number,
897 * fetch both type OID and atttypmod in a single cache lookup.
899 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
900 * raises an error if it can't obtain the information.
902 void
903 get_atttypetypmod(Oid relid, AttrNumber attnum,
904 Oid *typid, int32 *typmod)
906 HeapTuple tp;
907 Form_pg_attribute att_tup;
909 tp = SearchSysCache(ATTNUM,
910 ObjectIdGetDatum(relid),
911 Int16GetDatum(attnum),
912 0, 0);
913 if (!HeapTupleIsValid(tp))
914 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
915 attnum, relid);
916 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
918 *typid = att_tup->atttypid;
919 *typmod = att_tup->atttypmod;
920 ReleaseSysCache(tp);
923 /* ---------- CONSTRAINT CACHE ---------- */
926 * get_constraint_name
927 * Returns the name of a given pg_constraint entry.
929 * Returns a palloc'd copy of the string, or NULL if no such constraint.
931 * NOTE: since constraint name is not unique, be wary of code that uses this
932 * for anything except preparing error messages.
934 char *
935 get_constraint_name(Oid conoid)
937 HeapTuple tp;
939 tp = SearchSysCache(CONSTROID,
940 ObjectIdGetDatum(conoid),
941 0, 0, 0);
942 if (HeapTupleIsValid(tp))
944 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
945 char *result;
947 result = pstrdup(NameStr(contup->conname));
948 ReleaseSysCache(tp);
949 return result;
951 else
952 return NULL;
955 /* ---------- OPCLASS CACHE ---------- */
958 * get_opclass_family
960 * Returns the OID of the operator family the opclass belongs to.
963 get_opclass_family(Oid opclass)
965 HeapTuple tp;
966 Form_pg_opclass cla_tup;
967 Oid result;
969 tp = SearchSysCache(CLAOID,
970 ObjectIdGetDatum(opclass),
971 0, 0, 0);
972 if (!HeapTupleIsValid(tp))
973 elog(ERROR, "cache lookup failed for opclass %u", opclass);
974 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
976 result = cla_tup->opcfamily;
977 ReleaseSysCache(tp);
978 return result;
982 * get_opclass_input_type
984 * Returns the OID of the datatype the opclass indexes.
987 get_opclass_input_type(Oid opclass)
989 HeapTuple tp;
990 Form_pg_opclass cla_tup;
991 Oid result;
993 tp = SearchSysCache(CLAOID,
994 ObjectIdGetDatum(opclass),
995 0, 0, 0);
996 if (!HeapTupleIsValid(tp))
997 elog(ERROR, "cache lookup failed for opclass %u", opclass);
998 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1000 result = cla_tup->opcintype;
1001 ReleaseSysCache(tp);
1002 return result;
1005 /* ---------- OPERATOR CACHE ---------- */
1008 * get_opcode
1010 * Returns the regproc id of the routine used to implement an
1011 * operator given the operator oid.
1013 RegProcedure
1014 get_opcode(Oid opno)
1016 HeapTuple tp;
1018 tp = SearchSysCache(OPEROID,
1019 ObjectIdGetDatum(opno),
1020 0, 0, 0);
1021 if (HeapTupleIsValid(tp))
1023 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1024 RegProcedure result;
1026 result = optup->oprcode;
1027 ReleaseSysCache(tp);
1028 return result;
1030 else
1031 return (RegProcedure) InvalidOid;
1035 * get_opname
1036 * returns the name of the operator with the given opno
1038 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1040 char *
1041 get_opname(Oid opno)
1043 HeapTuple tp;
1045 tp = SearchSysCache(OPEROID,
1046 ObjectIdGetDatum(opno),
1047 0, 0, 0);
1048 if (HeapTupleIsValid(tp))
1050 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1051 char *result;
1053 result = pstrdup(NameStr(optup->oprname));
1054 ReleaseSysCache(tp);
1055 return result;
1057 else
1058 return NULL;
1062 * op_input_types
1064 * Returns the left and right input datatypes for an operator
1065 * (InvalidOid if not relevant).
1067 void
1068 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1070 HeapTuple tp;
1071 Form_pg_operator optup;
1073 tp = SearchSysCache(OPEROID,
1074 ObjectIdGetDatum(opno),
1075 0, 0, 0);
1076 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1077 elog(ERROR, "cache lookup failed for operator %u", opno);
1078 optup = (Form_pg_operator) GETSTRUCT(tp);
1079 *lefttype = optup->oprleft;
1080 *righttype = optup->oprright;
1081 ReleaseSysCache(tp);
1085 * op_mergejoinable
1087 * Returns true if the operator is potentially mergejoinable. (The planner
1088 * will fail to find any mergejoin plans unless there are suitable btree
1089 * opfamily entries for this operator and associated sortops. The pg_operator
1090 * flag is just a hint to tell the planner whether to bother looking.)
1092 bool
1093 op_mergejoinable(Oid opno)
1095 HeapTuple tp;
1096 bool result = false;
1098 tp = SearchSysCache(OPEROID,
1099 ObjectIdGetDatum(opno),
1100 0, 0, 0);
1101 if (HeapTupleIsValid(tp))
1103 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1105 result = optup->oprcanmerge;
1106 ReleaseSysCache(tp);
1108 return result;
1112 * op_hashjoinable
1114 * Returns true if the operator is hashjoinable. (There must be a suitable
1115 * hash opfamily entry for this operator if it is so marked.)
1117 bool
1118 op_hashjoinable(Oid opno)
1120 HeapTuple tp;
1121 bool result = false;
1123 tp = SearchSysCache(OPEROID,
1124 ObjectIdGetDatum(opno),
1125 0, 0, 0);
1126 if (HeapTupleIsValid(tp))
1128 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1130 result = optup->oprcanhash;
1131 ReleaseSysCache(tp);
1133 return result;
1137 * op_strict
1139 * Get the proisstrict flag for the operator's underlying function.
1141 bool
1142 op_strict(Oid opno)
1144 RegProcedure funcid = get_opcode(opno);
1146 if (funcid == (RegProcedure) InvalidOid)
1147 elog(ERROR, "operator %u does not exist", opno);
1149 return func_strict((Oid) funcid);
1153 * op_volatile
1155 * Get the provolatile flag for the operator's underlying function.
1157 char
1158 op_volatile(Oid opno)
1160 RegProcedure funcid = get_opcode(opno);
1162 if (funcid == (RegProcedure) InvalidOid)
1163 elog(ERROR, "operator %u does not exist", opno);
1165 return func_volatile((Oid) funcid);
1169 * get_commutator
1171 * Returns the corresponding commutator of an operator.
1174 get_commutator(Oid opno)
1176 HeapTuple tp;
1178 tp = SearchSysCache(OPEROID,
1179 ObjectIdGetDatum(opno),
1180 0, 0, 0);
1181 if (HeapTupleIsValid(tp))
1183 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1184 Oid result;
1186 result = optup->oprcom;
1187 ReleaseSysCache(tp);
1188 return result;
1190 else
1191 return InvalidOid;
1195 * get_negator
1197 * Returns the corresponding negator of an operator.
1200 get_negator(Oid opno)
1202 HeapTuple tp;
1204 tp = SearchSysCache(OPEROID,
1205 ObjectIdGetDatum(opno),
1206 0, 0, 0);
1207 if (HeapTupleIsValid(tp))
1209 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1210 Oid result;
1212 result = optup->oprnegate;
1213 ReleaseSysCache(tp);
1214 return result;
1216 else
1217 return InvalidOid;
1221 * get_oprrest
1223 * Returns procedure id for computing selectivity of an operator.
1225 RegProcedure
1226 get_oprrest(Oid opno)
1228 HeapTuple tp;
1230 tp = SearchSysCache(OPEROID,
1231 ObjectIdGetDatum(opno),
1232 0, 0, 0);
1233 if (HeapTupleIsValid(tp))
1235 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1236 RegProcedure result;
1238 result = optup->oprrest;
1239 ReleaseSysCache(tp);
1240 return result;
1242 else
1243 return (RegProcedure) InvalidOid;
1247 * get_oprjoin
1249 * Returns procedure id for computing selectivity of a join.
1251 RegProcedure
1252 get_oprjoin(Oid opno)
1254 HeapTuple tp;
1256 tp = SearchSysCache(OPEROID,
1257 ObjectIdGetDatum(opno),
1258 0, 0, 0);
1259 if (HeapTupleIsValid(tp))
1261 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1262 RegProcedure result;
1264 result = optup->oprjoin;
1265 ReleaseSysCache(tp);
1266 return result;
1268 else
1269 return (RegProcedure) InvalidOid;
1272 /* ---------- FUNCTION CACHE ---------- */
1275 * get_func_name
1276 * returns the name of the function with the given funcid
1278 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1280 char *
1281 get_func_name(Oid funcid)
1283 HeapTuple tp;
1285 tp = SearchSysCache(PROCOID,
1286 ObjectIdGetDatum(funcid),
1287 0, 0, 0);
1288 if (HeapTupleIsValid(tp))
1290 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1291 char *result;
1293 result = pstrdup(NameStr(functup->proname));
1294 ReleaseSysCache(tp);
1295 return result;
1297 else
1298 return NULL;
1302 * get_func_rettype
1303 * Given procedure id, return the function's result type.
1306 get_func_rettype(Oid funcid)
1308 HeapTuple tp;
1309 Oid result;
1311 tp = SearchSysCache(PROCOID,
1312 ObjectIdGetDatum(funcid),
1313 0, 0, 0);
1314 if (!HeapTupleIsValid(tp))
1315 elog(ERROR, "cache lookup failed for function %u", funcid);
1317 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1318 ReleaseSysCache(tp);
1319 return result;
1323 * get_func_nargs
1324 * Given procedure id, return the number of arguments.
1327 get_func_nargs(Oid funcid)
1329 HeapTuple tp;
1330 int result;
1332 tp = SearchSysCache(PROCOID,
1333 ObjectIdGetDatum(funcid),
1334 0, 0, 0);
1335 if (!HeapTupleIsValid(tp))
1336 elog(ERROR, "cache lookup failed for function %u", funcid);
1338 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1339 ReleaseSysCache(tp);
1340 return result;
1344 * get_func_signature
1345 * Given procedure id, return the function's argument and result types.
1346 * (The return value is the result type.)
1348 * The arguments are returned as a palloc'd array.
1351 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1353 HeapTuple tp;
1354 Form_pg_proc procstruct;
1355 Oid result;
1357 tp = SearchSysCache(PROCOID,
1358 ObjectIdGetDatum(funcid),
1359 0, 0, 0);
1360 if (!HeapTupleIsValid(tp))
1361 elog(ERROR, "cache lookup failed for function %u", funcid);
1363 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1365 result = procstruct->prorettype;
1366 *nargs = (int) procstruct->pronargs;
1367 Assert(*nargs == procstruct->proargtypes.dim1);
1368 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1369 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1371 ReleaseSysCache(tp);
1372 return result;
1376 * get_func_retset
1377 * Given procedure id, return the function's proretset flag.
1379 bool
1380 get_func_retset(Oid funcid)
1382 HeapTuple tp;
1383 bool result;
1385 tp = SearchSysCache(PROCOID,
1386 ObjectIdGetDatum(funcid),
1387 0, 0, 0);
1388 if (!HeapTupleIsValid(tp))
1389 elog(ERROR, "cache lookup failed for function %u", funcid);
1391 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1392 ReleaseSysCache(tp);
1393 return result;
1397 * func_strict
1398 * Given procedure id, return the function's proisstrict flag.
1400 bool
1401 func_strict(Oid funcid)
1403 HeapTuple tp;
1404 bool result;
1406 tp = SearchSysCache(PROCOID,
1407 ObjectIdGetDatum(funcid),
1408 0, 0, 0);
1409 if (!HeapTupleIsValid(tp))
1410 elog(ERROR, "cache lookup failed for function %u", funcid);
1412 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1413 ReleaseSysCache(tp);
1414 return result;
1418 * func_volatile
1419 * Given procedure id, return the function's provolatile flag.
1421 char
1422 func_volatile(Oid funcid)
1424 HeapTuple tp;
1425 char result;
1427 tp = SearchSysCache(PROCOID,
1428 ObjectIdGetDatum(funcid),
1429 0, 0, 0);
1430 if (!HeapTupleIsValid(tp))
1431 elog(ERROR, "cache lookup failed for function %u", funcid);
1433 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1434 ReleaseSysCache(tp);
1435 return result;
1439 * get_func_cost
1440 * Given procedure id, return the function's procost field.
1442 float4
1443 get_func_cost(Oid funcid)
1445 HeapTuple tp;
1446 float4 result;
1448 tp = SearchSysCache(PROCOID,
1449 ObjectIdGetDatum(funcid),
1450 0, 0, 0);
1451 if (!HeapTupleIsValid(tp))
1452 elog(ERROR, "cache lookup failed for function %u", funcid);
1454 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1455 ReleaseSysCache(tp);
1456 return result;
1460 * get_func_rows
1461 * Given procedure id, return the function's prorows field.
1463 float4
1464 get_func_rows(Oid funcid)
1466 HeapTuple tp;
1467 float4 result;
1469 tp = SearchSysCache(PROCOID,
1470 ObjectIdGetDatum(funcid),
1471 0, 0, 0);
1472 if (!HeapTupleIsValid(tp))
1473 elog(ERROR, "cache lookup failed for function %u", funcid);
1475 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1476 ReleaseSysCache(tp);
1477 return result;
1480 /* ---------- RELATION CACHE ---------- */
1483 * get_relname_relid
1484 * Given name and namespace of a relation, look up the OID.
1486 * Returns InvalidOid if there is no such relation.
1489 get_relname_relid(const char *relname, Oid relnamespace)
1491 return GetSysCacheOid(RELNAMENSP,
1492 PointerGetDatum(relname),
1493 ObjectIdGetDatum(relnamespace),
1494 0, 0);
1497 #ifdef NOT_USED
1499 * get_relnatts
1501 * Returns the number of attributes for a given relation.
1504 get_relnatts(Oid relid)
1506 HeapTuple tp;
1508 tp = SearchSysCache(RELOID,
1509 ObjectIdGetDatum(relid),
1510 0, 0, 0);
1511 if (HeapTupleIsValid(tp))
1513 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1514 int result;
1516 result = reltup->relnatts;
1517 ReleaseSysCache(tp);
1518 return result;
1520 else
1521 return InvalidAttrNumber;
1523 #endif
1526 * get_rel_name
1527 * Returns the name of a given relation.
1529 * Returns a palloc'd copy of the string, or NULL if no such relation.
1531 * NOTE: since relation name is not unique, be wary of code that uses this
1532 * for anything except preparing error messages.
1534 char *
1535 get_rel_name(Oid relid)
1537 HeapTuple tp;
1539 tp = SearchSysCache(RELOID,
1540 ObjectIdGetDatum(relid),
1541 0, 0, 0);
1542 if (HeapTupleIsValid(tp))
1544 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1545 char *result;
1547 result = pstrdup(NameStr(reltup->relname));
1548 ReleaseSysCache(tp);
1549 return result;
1551 else
1552 return NULL;
1556 * get_rel_namespace
1558 * Returns the pg_namespace OID associated with a given relation.
1561 get_rel_namespace(Oid relid)
1563 HeapTuple tp;
1565 tp = SearchSysCache(RELOID,
1566 ObjectIdGetDatum(relid),
1567 0, 0, 0);
1568 if (HeapTupleIsValid(tp))
1570 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1571 Oid result;
1573 result = reltup->relnamespace;
1574 ReleaseSysCache(tp);
1575 return result;
1577 else
1578 return InvalidOid;
1582 * get_rel_type_id
1584 * Returns the pg_type OID associated with a given relation.
1586 * Note: not all pg_class entries have associated pg_type OIDs; so be
1587 * careful to check for InvalidOid result.
1590 get_rel_type_id(Oid relid)
1592 HeapTuple tp;
1594 tp = SearchSysCache(RELOID,
1595 ObjectIdGetDatum(relid),
1596 0, 0, 0);
1597 if (HeapTupleIsValid(tp))
1599 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1600 Oid result;
1602 result = reltup->reltype;
1603 ReleaseSysCache(tp);
1604 return result;
1606 else
1607 return InvalidOid;
1611 * get_rel_relkind
1613 * Returns the relkind associated with a given relation.
1615 char
1616 get_rel_relkind(Oid relid)
1618 HeapTuple tp;
1620 tp = SearchSysCache(RELOID,
1621 ObjectIdGetDatum(relid),
1622 0, 0, 0);
1623 if (HeapTupleIsValid(tp))
1625 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1626 char result;
1628 result = reltup->relkind;
1629 ReleaseSysCache(tp);
1630 return result;
1632 else
1633 return '\0';
1637 * get_rel_tablespace
1639 * Returns the pg_tablespace OID associated with a given relation.
1641 * Note: InvalidOid might mean either that we couldn't find the relation,
1642 * or that it is in the database's default tablespace.
1645 get_rel_tablespace(Oid relid)
1647 HeapTuple tp;
1649 tp = SearchSysCache(RELOID,
1650 ObjectIdGetDatum(relid),
1651 0, 0, 0);
1652 if (HeapTupleIsValid(tp))
1654 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1655 Oid result;
1657 result = reltup->reltablespace;
1658 ReleaseSysCache(tp);
1659 return result;
1661 else
1662 return InvalidOid;
1666 /* ---------- TYPE CACHE ---------- */
1669 * get_typisdefined
1671 * Given the type OID, determine whether the type is defined
1672 * (if not, it's only a shell).
1674 bool
1675 get_typisdefined(Oid typid)
1677 HeapTuple tp;
1679 tp = SearchSysCache(TYPEOID,
1680 ObjectIdGetDatum(typid),
1681 0, 0, 0);
1682 if (HeapTupleIsValid(tp))
1684 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1685 bool result;
1687 result = typtup->typisdefined;
1688 ReleaseSysCache(tp);
1689 return result;
1691 else
1692 return false;
1696 * get_typlen
1698 * Given the type OID, return the length of the type.
1700 int16
1701 get_typlen(Oid typid)
1703 HeapTuple tp;
1705 tp = SearchSysCache(TYPEOID,
1706 ObjectIdGetDatum(typid),
1707 0, 0, 0);
1708 if (HeapTupleIsValid(tp))
1710 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1711 int16 result;
1713 result = typtup->typlen;
1714 ReleaseSysCache(tp);
1715 return result;
1717 else
1718 return 0;
1722 * get_typbyval
1724 * Given the type OID, determine whether the type is returned by value or
1725 * not. Returns true if by value, false if by reference.
1727 bool
1728 get_typbyval(Oid typid)
1730 HeapTuple tp;
1732 tp = SearchSysCache(TYPEOID,
1733 ObjectIdGetDatum(typid),
1734 0, 0, 0);
1735 if (HeapTupleIsValid(tp))
1737 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1738 bool result;
1740 result = typtup->typbyval;
1741 ReleaseSysCache(tp);
1742 return result;
1744 else
1745 return false;
1749 * get_typlenbyval
1751 * A two-fer: given the type OID, return both typlen and typbyval.
1753 * Since both pieces of info are needed to know how to copy a Datum,
1754 * many places need both. Might as well get them with one cache lookup
1755 * instead of two. Also, this routine raises an error instead of
1756 * returning a bogus value when given a bad type OID.
1758 void
1759 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1761 HeapTuple tp;
1762 Form_pg_type typtup;
1764 tp = SearchSysCache(TYPEOID,
1765 ObjectIdGetDatum(typid),
1766 0, 0, 0);
1767 if (!HeapTupleIsValid(tp))
1768 elog(ERROR, "cache lookup failed for type %u", typid);
1769 typtup = (Form_pg_type) GETSTRUCT(tp);
1770 *typlen = typtup->typlen;
1771 *typbyval = typtup->typbyval;
1772 ReleaseSysCache(tp);
1776 * get_typlenbyvalalign
1778 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1780 void
1781 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1782 char *typalign)
1784 HeapTuple tp;
1785 Form_pg_type typtup;
1787 tp = SearchSysCache(TYPEOID,
1788 ObjectIdGetDatum(typid),
1789 0, 0, 0);
1790 if (!HeapTupleIsValid(tp))
1791 elog(ERROR, "cache lookup failed for type %u", typid);
1792 typtup = (Form_pg_type) GETSTRUCT(tp);
1793 *typlen = typtup->typlen;
1794 *typbyval = typtup->typbyval;
1795 *typalign = typtup->typalign;
1796 ReleaseSysCache(tp);
1800 * getTypeIOParam
1801 * Given a pg_type row, select the type OID to pass to I/O functions
1803 * Formerly, all I/O functions were passed pg_type.typelem as their second
1804 * parameter, but we now have a more complex rule about what to pass.
1805 * This knowledge is intended to be centralized here --- direct references
1806 * to typelem elsewhere in the code are wrong, if they are associated with
1807 * I/O calls and not with actual subscripting operations! (But see
1808 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1810 * As of PostgreSQL 8.1, output functions receive only the value itself
1811 * and not any auxiliary parameters, so the name of this routine is now
1812 * a bit of a misnomer ... it should be getTypeInputParam.
1815 getTypeIOParam(HeapTuple typeTuple)
1817 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1820 * Array types get their typelem as parameter; everybody else gets their
1821 * own type OID as parameter. (As of 8.2, domains must get their own OID
1822 * even if their base type is an array.)
1824 if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem))
1825 return typeStruct->typelem;
1826 else
1827 return HeapTupleGetOid(typeTuple);
1831 * get_type_io_data
1833 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1834 * typdelim, typioparam, and IO function OID. The IO function
1835 * returned is controlled by IOFuncSelector
1837 void
1838 get_type_io_data(Oid typid,
1839 IOFuncSelector which_func,
1840 int16 *typlen,
1841 bool *typbyval,
1842 char *typalign,
1843 char *typdelim,
1844 Oid *typioparam,
1845 Oid *func)
1847 HeapTuple typeTuple;
1848 Form_pg_type typeStruct;
1851 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1852 * use array_in and array_out during bootstrap.
1854 if (IsBootstrapProcessingMode())
1856 Oid typinput;
1857 Oid typoutput;
1859 boot_get_type_io_data(typid,
1860 typlen,
1861 typbyval,
1862 typalign,
1863 typdelim,
1864 typioparam,
1865 &typinput,
1866 &typoutput);
1867 switch (which_func)
1869 case IOFunc_input:
1870 *func = typinput;
1871 break;
1872 case IOFunc_output:
1873 *func = typoutput;
1874 break;
1875 default:
1876 elog(ERROR, "binary I/O not supported during bootstrap");
1877 break;
1879 return;
1882 typeTuple = SearchSysCache(TYPEOID,
1883 ObjectIdGetDatum(typid),
1884 0, 0, 0);
1885 if (!HeapTupleIsValid(typeTuple))
1886 elog(ERROR, "cache lookup failed for type %u", typid);
1887 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1889 *typlen = typeStruct->typlen;
1890 *typbyval = typeStruct->typbyval;
1891 *typalign = typeStruct->typalign;
1892 *typdelim = typeStruct->typdelim;
1893 *typioparam = getTypeIOParam(typeTuple);
1894 switch (which_func)
1896 case IOFunc_input:
1897 *func = typeStruct->typinput;
1898 break;
1899 case IOFunc_output:
1900 *func = typeStruct->typoutput;
1901 break;
1902 case IOFunc_receive:
1903 *func = typeStruct->typreceive;
1904 break;
1905 case IOFunc_send:
1906 *func = typeStruct->typsend;
1907 break;
1909 ReleaseSysCache(typeTuple);
1912 #ifdef NOT_USED
1913 char
1914 get_typalign(Oid typid)
1916 HeapTuple tp;
1918 tp = SearchSysCache(TYPEOID,
1919 ObjectIdGetDatum(typid),
1920 0, 0, 0);
1921 if (HeapTupleIsValid(tp))
1923 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1924 char result;
1926 result = typtup->typalign;
1927 ReleaseSysCache(tp);
1928 return result;
1930 else
1931 return 'i';
1933 #endif
1935 char
1936 get_typstorage(Oid typid)
1938 HeapTuple tp;
1940 tp = SearchSysCache(TYPEOID,
1941 ObjectIdGetDatum(typid),
1942 0, 0, 0);
1943 if (HeapTupleIsValid(tp))
1945 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1946 char result;
1948 result = typtup->typstorage;
1949 ReleaseSysCache(tp);
1950 return result;
1952 else
1953 return 'p';
1957 * get_typdefault
1958 * Given a type OID, return the type's default value, if any.
1960 * The result is a palloc'd expression node tree, or NULL if there
1961 * is no defined default for the datatype.
1963 * NB: caller should be prepared to coerce result to correct datatype;
1964 * the returned expression tree might produce something of the wrong type.
1966 Node *
1967 get_typdefault(Oid typid)
1969 HeapTuple typeTuple;
1970 Form_pg_type type;
1971 Datum datum;
1972 bool isNull;
1973 Node *expr;
1975 typeTuple = SearchSysCache(TYPEOID,
1976 ObjectIdGetDatum(typid),
1977 0, 0, 0);
1978 if (!HeapTupleIsValid(typeTuple))
1979 elog(ERROR, "cache lookup failed for type %u", typid);
1980 type = (Form_pg_type) GETSTRUCT(typeTuple);
1983 * typdefault and typdefaultbin are potentially null, so don't try to
1984 * access 'em as struct fields. Must do it the hard way with
1985 * SysCacheGetAttr.
1987 datum = SysCacheGetAttr(TYPEOID,
1988 typeTuple,
1989 Anum_pg_type_typdefaultbin,
1990 &isNull);
1992 if (!isNull)
1994 /* We have an expression default */
1995 expr = stringToNode(TextDatumGetCString(datum));
1997 else
1999 /* Perhaps we have a plain literal default */
2000 datum = SysCacheGetAttr(TYPEOID,
2001 typeTuple,
2002 Anum_pg_type_typdefault,
2003 &isNull);
2005 if (!isNull)
2007 char *strDefaultVal;
2009 /* Convert text datum to C string */
2010 strDefaultVal = TextDatumGetCString(datum);
2011 /* Convert C string to a value of the given type */
2012 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2013 getTypeIOParam(typeTuple), -1);
2014 /* Build a Const node containing the value */
2015 expr = (Node *) makeConst(typid,
2017 type->typlen,
2018 datum,
2019 false,
2020 type->typbyval);
2021 pfree(strDefaultVal);
2023 else
2025 /* No default */
2026 expr = NULL;
2030 ReleaseSysCache(typeTuple);
2032 return expr;
2036 * getBaseType
2037 * If the given type is a domain, return its base type;
2038 * otherwise return the type's own OID.
2041 getBaseType(Oid typid)
2043 int32 typmod = -1;
2045 return getBaseTypeAndTypmod(typid, &typmod);
2049 * getBaseTypeAndTypmod
2050 * If the given type is a domain, return its base type and typmod;
2051 * otherwise return the type's own OID, and leave *typmod unchanged.
2053 * Note that the "applied typmod" should be -1 for every domain level
2054 * above the bottommost; therefore, if the passed-in typid is indeed
2055 * a domain, *typmod should be -1.
2058 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2061 * We loop to find the bottom base type in a stack of domains.
2063 for (;;)
2065 HeapTuple tup;
2066 Form_pg_type typTup;
2068 tup = SearchSysCache(TYPEOID,
2069 ObjectIdGetDatum(typid),
2070 0, 0, 0);
2071 if (!HeapTupleIsValid(tup))
2072 elog(ERROR, "cache lookup failed for type %u", typid);
2073 typTup = (Form_pg_type) GETSTRUCT(tup);
2074 if (typTup->typtype != TYPTYPE_DOMAIN)
2076 /* Not a domain, so done */
2077 ReleaseSysCache(tup);
2078 break;
2081 Assert(*typmod == -1);
2082 typid = typTup->typbasetype;
2083 *typmod = typTup->typtypmod;
2085 ReleaseSysCache(tup);
2088 return typid;
2092 * get_typavgwidth
2094 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2095 * estimate the average width of values of the type. This is used by
2096 * the planner, which doesn't require absolutely correct results;
2097 * it's OK (and expected) to guess if we don't know for sure.
2099 int32
2100 get_typavgwidth(Oid typid, int32 typmod)
2102 int typlen = get_typlen(typid);
2103 int32 maxwidth;
2106 * Easy if it's a fixed-width type
2108 if (typlen > 0)
2109 return typlen;
2112 * type_maximum_size knows the encoding of typmod for some datatypes;
2113 * don't duplicate that knowledge here.
2115 maxwidth = type_maximum_size(typid, typmod);
2116 if (maxwidth > 0)
2119 * For BPCHAR, the max width is also the only width. Otherwise we
2120 * need to guess about the typical data width given the max. A sliding
2121 * scale for percentage of max width seems reasonable.
2123 if (typid == BPCHAROID)
2124 return maxwidth;
2125 if (maxwidth <= 32)
2126 return maxwidth; /* assume full width */
2127 if (maxwidth < 1000)
2128 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2131 * Beyond 1000, assume we're looking at something like
2132 * "varchar(10000)" where the limit isn't actually reached often, and
2133 * use a fixed estimate.
2135 return 32 + (1000 - 32) / 2;
2139 * Ooops, we have no idea ... wild guess time.
2141 return 32;
2145 * get_typtype
2147 * Given the type OID, find if it is a basic type, a complex type, etc.
2148 * It returns the null char if the cache lookup fails...
2150 char
2151 get_typtype(Oid typid)
2153 HeapTuple tp;
2155 tp = SearchSysCache(TYPEOID,
2156 ObjectIdGetDatum(typid),
2157 0, 0, 0);
2158 if (HeapTupleIsValid(tp))
2160 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2161 char result;
2163 result = typtup->typtype;
2164 ReleaseSysCache(tp);
2165 return result;
2167 else
2168 return '\0';
2172 * type_is_rowtype
2174 * Convenience function to determine whether a type OID represents
2175 * a "rowtype" type --- either RECORD or a named composite type.
2177 bool
2178 type_is_rowtype(Oid typid)
2180 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2184 * type_is_enum
2185 * Returns true if the given type is an enum type.
2187 bool
2188 type_is_enum(Oid typid)
2190 return (get_typtype(typid) == TYPTYPE_ENUM);
2194 * get_type_category_preferred
2196 * Given the type OID, fetch its category and preferred-type status.
2197 * Throws error on failure.
2199 void
2200 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2202 HeapTuple tp;
2203 Form_pg_type typtup;
2205 tp = SearchSysCache(TYPEOID,
2206 ObjectIdGetDatum(typid),
2207 0, 0, 0);
2208 if (!HeapTupleIsValid(tp))
2209 elog(ERROR, "cache lookup failed for type %u", typid);
2210 typtup = (Form_pg_type) GETSTRUCT(tp);
2211 *typcategory = typtup->typcategory;
2212 *typispreferred = typtup->typispreferred;
2213 ReleaseSysCache(tp);
2217 * get_typ_typrelid
2219 * Given the type OID, get the typrelid (InvalidOid if not a complex
2220 * type).
2223 get_typ_typrelid(Oid typid)
2225 HeapTuple tp;
2227 tp = SearchSysCache(TYPEOID,
2228 ObjectIdGetDatum(typid),
2229 0, 0, 0);
2230 if (HeapTupleIsValid(tp))
2232 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2233 Oid result;
2235 result = typtup->typrelid;
2236 ReleaseSysCache(tp);
2237 return result;
2239 else
2240 return InvalidOid;
2244 * get_element_type
2246 * Given the type OID, get the typelem (InvalidOid if not an array type).
2248 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2249 * returned if the input is a fixed-length array type.
2252 get_element_type(Oid typid)
2254 HeapTuple tp;
2256 tp = SearchSysCache(TYPEOID,
2257 ObjectIdGetDatum(typid),
2258 0, 0, 0);
2259 if (HeapTupleIsValid(tp))
2261 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2262 Oid result;
2264 if (typtup->typlen == -1)
2265 result = typtup->typelem;
2266 else
2267 result = InvalidOid;
2268 ReleaseSysCache(tp);
2269 return result;
2271 else
2272 return InvalidOid;
2276 * get_array_type
2278 * Given the type OID, get the corresponding "true" array type.
2279 * Returns InvalidOid if no array type can be found.
2282 get_array_type(Oid typid)
2284 HeapTuple tp;
2285 Oid result = InvalidOid;
2287 tp = SearchSysCache(TYPEOID,
2288 ObjectIdGetDatum(typid),
2289 0, 0, 0);
2290 if (HeapTupleIsValid(tp))
2292 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2293 ReleaseSysCache(tp);
2295 return result;
2299 * getTypeInputInfo
2301 * Get info needed for converting values of a type to internal form
2303 void
2304 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2306 HeapTuple typeTuple;
2307 Form_pg_type pt;
2309 typeTuple = SearchSysCache(TYPEOID,
2310 ObjectIdGetDatum(type),
2311 0, 0, 0);
2312 if (!HeapTupleIsValid(typeTuple))
2313 elog(ERROR, "cache lookup failed for type %u", type);
2314 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2316 if (!pt->typisdefined)
2317 ereport(ERROR,
2318 (errcode(ERRCODE_UNDEFINED_OBJECT),
2319 errmsg("type %s is only a shell",
2320 format_type_be(type))));
2321 if (!OidIsValid(pt->typinput))
2322 ereport(ERROR,
2323 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2324 errmsg("no input function available for type %s",
2325 format_type_be(type))));
2327 *typInput = pt->typinput;
2328 *typIOParam = getTypeIOParam(typeTuple);
2330 ReleaseSysCache(typeTuple);
2334 * getTypeOutputInfo
2336 * Get info needed for printing values of a type
2338 void
2339 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2341 HeapTuple typeTuple;
2342 Form_pg_type pt;
2344 typeTuple = SearchSysCache(TYPEOID,
2345 ObjectIdGetDatum(type),
2346 0, 0, 0);
2347 if (!HeapTupleIsValid(typeTuple))
2348 elog(ERROR, "cache lookup failed for type %u", type);
2349 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2351 if (!pt->typisdefined)
2352 ereport(ERROR,
2353 (errcode(ERRCODE_UNDEFINED_OBJECT),
2354 errmsg("type %s is only a shell",
2355 format_type_be(type))));
2356 if (!OidIsValid(pt->typoutput))
2357 ereport(ERROR,
2358 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2359 errmsg("no output function available for type %s",
2360 format_type_be(type))));
2362 *typOutput = pt->typoutput;
2363 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2365 ReleaseSysCache(typeTuple);
2369 * getTypeBinaryInputInfo
2371 * Get info needed for binary input of values of a type
2373 void
2374 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2376 HeapTuple typeTuple;
2377 Form_pg_type pt;
2379 typeTuple = SearchSysCache(TYPEOID,
2380 ObjectIdGetDatum(type),
2381 0, 0, 0);
2382 if (!HeapTupleIsValid(typeTuple))
2383 elog(ERROR, "cache lookup failed for type %u", type);
2384 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2386 if (!pt->typisdefined)
2387 ereport(ERROR,
2388 (errcode(ERRCODE_UNDEFINED_OBJECT),
2389 errmsg("type %s is only a shell",
2390 format_type_be(type))));
2391 if (!OidIsValid(pt->typreceive))
2392 ereport(ERROR,
2393 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2394 errmsg("no binary input function available for type %s",
2395 format_type_be(type))));
2397 *typReceive = pt->typreceive;
2398 *typIOParam = getTypeIOParam(typeTuple);
2400 ReleaseSysCache(typeTuple);
2404 * getTypeBinaryOutputInfo
2406 * Get info needed for binary output of values of a type
2408 void
2409 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2411 HeapTuple typeTuple;
2412 Form_pg_type pt;
2414 typeTuple = SearchSysCache(TYPEOID,
2415 ObjectIdGetDatum(type),
2416 0, 0, 0);
2417 if (!HeapTupleIsValid(typeTuple))
2418 elog(ERROR, "cache lookup failed for type %u", type);
2419 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2421 if (!pt->typisdefined)
2422 ereport(ERROR,
2423 (errcode(ERRCODE_UNDEFINED_OBJECT),
2424 errmsg("type %s is only a shell",
2425 format_type_be(type))));
2426 if (!OidIsValid(pt->typsend))
2427 ereport(ERROR,
2428 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2429 errmsg("no binary output function available for type %s",
2430 format_type_be(type))));
2432 *typSend = pt->typsend;
2433 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2435 ReleaseSysCache(typeTuple);
2439 * get_typmodin
2441 * Given the type OID, return the type's typmodin procedure, if any.
2444 get_typmodin(Oid typid)
2446 HeapTuple tp;
2448 tp = SearchSysCache(TYPEOID,
2449 ObjectIdGetDatum(typid),
2450 0, 0, 0);
2451 if (HeapTupleIsValid(tp))
2453 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2454 Oid result;
2456 result = typtup->typmodin;
2457 ReleaseSysCache(tp);
2458 return result;
2460 else
2461 return InvalidOid;
2464 #ifdef NOT_USED
2466 * get_typmodout
2468 * Given the type OID, return the type's typmodout procedure, if any.
2471 get_typmodout(Oid typid)
2473 HeapTuple tp;
2475 tp = SearchSysCache(TYPEOID,
2476 ObjectIdGetDatum(typid),
2477 0, 0, 0);
2478 if (HeapTupleIsValid(tp))
2480 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2481 Oid result;
2483 result = typtup->typmodout;
2484 ReleaseSysCache(tp);
2485 return result;
2487 else
2488 return InvalidOid;
2490 #endif /* NOT_USED */
2493 /* ---------- STATISTICS CACHE ---------- */
2496 * get_attavgwidth
2498 * Given the table and attribute number of a column, get the average
2499 * width of entries in the column. Return zero if no data available.
2501 * Calling a hook at this point looks somewhat strange, but is required
2502 * because the optimizer calls this function without any other way for
2503 * plug-ins to control the result.
2505 int32
2506 get_attavgwidth(Oid relid, AttrNumber attnum)
2508 HeapTuple tp;
2509 int32 stawidth;
2511 if (get_attavgwidth_hook)
2513 stawidth = (*get_attavgwidth_hook) (relid, attnum);
2514 if (stawidth > 0)
2515 return stawidth;
2517 tp = SearchSysCache(STATRELATT,
2518 ObjectIdGetDatum(relid),
2519 Int16GetDatum(attnum),
2520 0, 0);
2521 if (HeapTupleIsValid(tp))
2523 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2524 ReleaseSysCache(tp);
2525 if (stawidth > 0)
2526 return stawidth;
2528 return 0;
2532 * get_attstatsslot
2534 * Extract the contents of a "slot" of a pg_statistic tuple.
2535 * Returns TRUE if requested slot type was found, else FALSE.
2537 * Unlike other routines in this file, this takes a pointer to an
2538 * already-looked-up tuple in the pg_statistic cache. We do this since
2539 * most callers will want to extract more than one value from the cache
2540 * entry, and we don't want to repeat the cache lookup unnecessarily.
2541 * Also, this API allows this routine to be used with statistics tuples
2542 * that have been provided by a stats hook and didn't really come from
2543 * pg_statistic.
2545 * statstuple: pg_statistics tuple to be examined.
2546 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2547 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2548 * reqkind: STAKIND code for desired statistics slot kind.
2549 * reqop: STAOP value wanted, or InvalidOid if don't care.
2550 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2551 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2553 * If assigned, values and numbers are set to point to palloc'd arrays.
2554 * If the attribute type is pass-by-reference, the values referenced by
2555 * the values array are themselves palloc'd. The palloc'd stuff can be
2556 * freed by calling free_attstatsslot.
2558 bool
2559 get_attstatsslot(HeapTuple statstuple,
2560 Oid atttype, int32 atttypmod,
2561 int reqkind, Oid reqop,
2562 Datum **values, int *nvalues,
2563 float4 **numbers, int *nnumbers)
2565 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2566 int i,
2568 Datum val;
2569 bool isnull;
2570 ArrayType *statarray;
2571 int narrayelem;
2572 HeapTuple typeTuple;
2573 Form_pg_type typeForm;
2575 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2577 if ((&stats->stakind1)[i] == reqkind &&
2578 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2579 break;
2581 if (i >= STATISTIC_NUM_SLOTS)
2582 return false; /* not there */
2584 if (values)
2586 val = SysCacheGetAttr(STATRELATT, statstuple,
2587 Anum_pg_statistic_stavalues1 + i,
2588 &isnull);
2589 if (isnull)
2590 elog(ERROR, "stavalues is null");
2591 statarray = DatumGetArrayTypeP(val);
2593 /* Need to get info about the array element type */
2594 typeTuple = SearchSysCache(TYPEOID,
2595 ObjectIdGetDatum(atttype),
2596 0, 0, 0);
2597 if (!HeapTupleIsValid(typeTuple))
2598 elog(ERROR, "cache lookup failed for type %u", atttype);
2599 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2601 /* Deconstruct array into Datum elements; NULLs not expected */
2602 deconstruct_array(statarray,
2603 atttype,
2604 typeForm->typlen,
2605 typeForm->typbyval,
2606 typeForm->typalign,
2607 values, NULL, nvalues);
2610 * If the element type is pass-by-reference, we now have a bunch of
2611 * Datums that are pointers into the syscache value. Copy them to
2612 * avoid problems if syscache decides to drop the entry.
2614 if (!typeForm->typbyval)
2616 for (j = 0; j < *nvalues; j++)
2618 (*values)[j] = datumCopy((*values)[j],
2619 typeForm->typbyval,
2620 typeForm->typlen);
2624 ReleaseSysCache(typeTuple);
2627 * Free statarray if it's a detoasted copy.
2629 if ((Pointer) statarray != DatumGetPointer(val))
2630 pfree(statarray);
2633 if (numbers)
2635 val = SysCacheGetAttr(STATRELATT, statstuple,
2636 Anum_pg_statistic_stanumbers1 + i,
2637 &isnull);
2638 if (isnull)
2639 elog(ERROR, "stanumbers is null");
2640 statarray = DatumGetArrayTypeP(val);
2643 * We expect the array to be a 1-D float4 array; verify that. We don't
2644 * need to use deconstruct_array() since the array data is just going
2645 * to look like a C array of float4 values.
2647 narrayelem = ARR_DIMS(statarray)[0];
2648 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2649 ARR_HASNULL(statarray) ||
2650 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2651 elog(ERROR, "stanumbers is not a 1-D float4 array");
2652 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2653 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2654 *nnumbers = narrayelem;
2657 * Free statarray if it's a detoasted copy.
2659 if ((Pointer) statarray != DatumGetPointer(val))
2660 pfree(statarray);
2663 return true;
2667 * free_attstatsslot
2668 * Free data allocated by get_attstatsslot
2670 * atttype need be valid only if values != NULL.
2672 void
2673 free_attstatsslot(Oid atttype,
2674 Datum *values, int nvalues,
2675 float4 *numbers, int nnumbers)
2677 if (values)
2679 if (!get_typbyval(atttype))
2681 int i;
2683 for (i = 0; i < nvalues; i++)
2684 pfree(DatumGetPointer(values[i]));
2686 pfree(values);
2688 if (numbers)
2689 pfree(numbers);
2692 /* ---------- PG_NAMESPACE CACHE ---------- */
2695 * get_namespace_name
2696 * Returns the name of a given namespace
2698 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2700 char *
2701 get_namespace_name(Oid nspid)
2703 HeapTuple tp;
2705 tp = SearchSysCache(NAMESPACEOID,
2706 ObjectIdGetDatum(nspid),
2707 0, 0, 0);
2708 if (HeapTupleIsValid(tp))
2710 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2711 char *result;
2713 result = pstrdup(NameStr(nsptup->nspname));
2714 ReleaseSysCache(tp);
2715 return result;
2717 else
2718 return NULL;
2721 /* ---------- PG_AUTHID CACHE ---------- */
2724 * get_roleid
2725 * Given a role name, look up the role's OID.
2726 * Returns InvalidOid if no such role.
2729 get_roleid(const char *rolname)
2731 return GetSysCacheOid(AUTHNAME,
2732 PointerGetDatum(rolname),
2733 0, 0, 0);
2737 * get_roleid_checked
2738 * Given a role name, look up the role's OID.
2739 * ereports if no such role.
2742 get_roleid_checked(const char *rolname)
2744 Oid roleid;
2746 roleid = get_roleid(rolname);
2747 if (!OidIsValid(roleid))
2748 ereport(ERROR,
2749 (errcode(ERRCODE_UNDEFINED_OBJECT),
2750 errmsg("role \"%s\" does not exist", rolname)));
2751 return roleid;