1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/utils/cache/lsyscache.c
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
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_collation.h"
24 #include "catalog/pg_constraint.h"
25 #include "catalog/pg_namespace.h"
26 #include "catalog/pg_opclass.h"
27 #include "catalog/pg_operator.h"
28 #include "catalog/pg_proc.h"
29 #include "catalog/pg_range.h"
30 #include "catalog/pg_statistic.h"
31 #include "catalog/pg_type.h"
32 #include "miscadmin.h"
33 #include "nodes/makefuncs.h"
34 #include "utils/array.h"
35 #include "utils/builtins.h"
36 #include "utils/datum.h"
37 #include "utils/fmgroids.h"
38 #include "utils/lsyscache.h"
39 #include "utils/rel.h"
40 #include "utils/syscache.h"
41 #include "utils/typcache.h"
43 /* Hook for plugins to get control in get_attavgwidth() */
44 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
47 /* ---------- AMOP CACHES ---------- */
52 * Return t iff operator 'opno' is in operator family 'opfamily'.
54 * This function only considers search operators, not ordering operators.
57 op_in_opfamily(Oid opno, Oid opfamily)
59 return SearchSysCacheExists3(AMOPOPID,
60 ObjectIdGetDatum(opno),
61 CharGetDatum(AMOP_SEARCH),
62 ObjectIdGetDatum(opfamily));
66 * get_op_opfamily_strategy
68 * Get the operator's strategy number within the specified opfamily,
69 * or 0 if it's not a member of the opfamily.
71 * This function only considers search operators, not ordering operators.
74 get_op_opfamily_strategy(Oid opno, Oid opfamily)
77 Form_pg_amop amop_tup;
80 tp = SearchSysCache3(AMOPOPID,
81 ObjectIdGetDatum(opno),
82 CharGetDatum(AMOP_SEARCH),
83 ObjectIdGetDatum(opfamily));
84 if (!HeapTupleIsValid(tp))
86 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
87 result = amop_tup->amopstrategy;
93 * get_op_opfamily_sortfamily
95 * If the operator is an ordering operator within the specified opfamily,
96 * return its amopsortfamily OID; else return InvalidOid.
99 get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
102 Form_pg_amop amop_tup;
105 tp = SearchSysCache3(AMOPOPID,
106 ObjectIdGetDatum(opno),
107 CharGetDatum(AMOP_ORDER),
108 ObjectIdGetDatum(opfamily));
109 if (!HeapTupleIsValid(tp))
111 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
112 result = amop_tup->amopsortfamily;
118 * get_op_opfamily_properties
120 * Get the operator's strategy number and declared input data types
121 * within the specified opfamily.
123 * Caller should already have verified that opno is a member of opfamily,
124 * therefore we raise an error if the tuple is not found.
127 get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
133 Form_pg_amop amop_tup;
135 tp = SearchSysCache3(AMOPOPID,
136 ObjectIdGetDatum(opno),
137 CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
138 ObjectIdGetDatum(opfamily));
139 if (!HeapTupleIsValid(tp))
140 elog(ERROR, "operator %u is not a member of opfamily %u",
142 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
143 *strategy = amop_tup->amopstrategy;
144 *lefttype = amop_tup->amoplefttype;
145 *righttype = amop_tup->amoprighttype;
150 * get_opfamily_member
151 * Get the OID of the operator that implements the specified strategy
152 * with the specified datatypes for the specified opfamily.
154 * Returns InvalidOid if there is no pg_amop entry for the given keys.
157 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
161 Form_pg_amop amop_tup;
164 tp = SearchSysCache4(AMOPSTRATEGY,
165 ObjectIdGetDatum(opfamily),
166 ObjectIdGetDatum(lefttype),
167 ObjectIdGetDatum(righttype),
168 Int16GetDatum(strategy));
169 if (!HeapTupleIsValid(tp))
171 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
172 result = amop_tup->amopopr;
178 * get_ordering_op_properties
179 * Given the OID of an ordering operator (a btree "<" or ">" operator),
180 * determine its opfamily, its declared input datatype, and its
181 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
183 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
184 * (This indicates that the operator is not a valid ordering operator.)
186 * Note: the operator could be registered in multiple families, for example
187 * if someone were to build a "reverse sort" opfamily. This would result in
188 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
189 * or NULLS LAST, as well as inefficient planning due to failure to match up
190 * pathkeys that should be the same. So we want a determinate result here.
191 * Because of the way the syscache search works, we'll use the interpretation
192 * associated with the opfamily with smallest OID, which is probably
193 * determinate enough. Since there is no longer any particularly good reason
194 * to build reverse-sort opfamilies, it doesn't seem worth expending any
195 * additional effort on ensuring consistency.
198 get_ordering_op_properties(Oid opno,
199 Oid *opfamily, Oid *opcintype, int16 *strategy)
205 /* ensure outputs are initialized on failure */
206 *opfamily = InvalidOid;
207 *opcintype = InvalidOid;
211 * Search pg_amop to see if the target operator is registered as the "<"
212 * or ">" operator of any btree opfamily.
214 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
216 for (i = 0; i < catlist->n_members; i++)
218 HeapTuple tuple = &catlist->members[i]->tuple;
219 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
222 if (aform->amopmethod != BTREE_AM_OID)
225 if (aform->amopstrategy == BTLessStrategyNumber ||
226 aform->amopstrategy == BTGreaterStrategyNumber)
228 /* Found it ... should have consistent input types */
229 if (aform->amoplefttype == aform->amoprighttype)
231 /* Found a suitable opfamily, return info */
232 *opfamily = aform->amopfamily;
233 *opcintype = aform->amoplefttype;
234 *strategy = aform->amopstrategy;
241 ReleaseSysCacheList(catlist);
247 * get_sort_function_for_ordering_op
248 * Get the OID of the datatype-specific btree sort support function,
249 * or if there is none, the btree comparison function,
250 * associated with an ordering operator (a "<" or ">" operator).
252 * *sortfunc receives the support or comparison function OID.
253 * *issupport is set TRUE if it's a support func, FALSE if a comparison func.
254 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
255 * (indicating that comparison results must be negated before use).
257 * Returns TRUE if successful, FALSE if no btree function can be found.
258 * (This indicates that the operator is not a valid ordering operator.)
261 get_sort_function_for_ordering_op(Oid opno, Oid *sortfunc,
262 bool *issupport, bool *reverse)
268 /* Find the operator in pg_amop */
269 if (get_ordering_op_properties(opno,
270 &opfamily, &opcintype, &strategy))
272 /* Found a suitable opfamily, get matching support function */
273 *sortfunc = get_opfamily_proc(opfamily,
277 if (OidIsValid(*sortfunc))
281 /* opfamily doesn't provide sort support, get comparison func */
282 *sortfunc = get_opfamily_proc(opfamily,
286 if (!OidIsValid(*sortfunc)) /* should not happen */
287 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
288 BTORDER_PROC, opcintype, opcintype, opfamily);
291 *reverse = (strategy == BTGreaterStrategyNumber);
295 /* ensure outputs are set on failure */
296 *sortfunc = InvalidOid;
303 * get_equality_op_for_ordering_op
304 * Get the OID of the datatype-specific btree equality operator
305 * associated with an ordering operator (a "<" or ">" operator).
307 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
310 * Returns InvalidOid if no matching equality operator can be found.
311 * (This indicates that the operator is not a valid ordering operator.)
314 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
316 Oid result = InvalidOid;
321 /* Find the operator in pg_amop */
322 if (get_ordering_op_properties(opno,
323 &opfamily, &opcintype, &strategy))
325 /* Found a suitable opfamily, get matching equality operator */
326 result = get_opfamily_member(opfamily,
329 BTEqualStrategyNumber);
331 *reverse = (strategy == BTGreaterStrategyNumber);
338 * get_ordering_op_for_equality_op
339 * Get the OID of a datatype-specific btree ordering operator
340 * associated with an equality operator. (If there are multiple
341 * possibilities, assume any one will do.)
343 * This function is used when we have to sort data before unique-ifying,
344 * and don't much care which sorting op is used as long as it's compatible
345 * with the intended equality operator. Since we need a sorting operator,
346 * it should be single-data-type even if the given operator is cross-type.
347 * The caller specifies whether to find an op for the LHS or RHS data type.
349 * Returns InvalidOid if no matching ordering operator can be found.
352 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
354 Oid result = InvalidOid;
359 * Search pg_amop to see if the target operator is registered as the "="
360 * operator of any btree opfamily.
362 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
364 for (i = 0; i < catlist->n_members; i++)
366 HeapTuple tuple = &catlist->members[i]->tuple;
367 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
370 if (aform->amopmethod != BTREE_AM_OID)
373 if (aform->amopstrategy == BTEqualStrategyNumber)
375 /* Found a suitable opfamily, get matching ordering operator */
378 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
379 result = get_opfamily_member(aform->amopfamily,
381 BTLessStrategyNumber);
382 if (OidIsValid(result))
384 /* failure probably shouldn't happen, but keep looking if so */
388 ReleaseSysCacheList(catlist);
394 * get_mergejoin_opfamilies
395 * Given a putatively mergejoinable operator, return a list of the OIDs
396 * of the btree opfamilies in which it represents equality.
398 * It is possible (though at present unusual) for an operator to be equality
399 * in more than one opfamily, hence the result is a list. This also lets us
400 * return NIL if the operator is not found in any opfamilies.
402 * The planner currently uses simple equal() tests to compare the lists
403 * returned by this function, which makes the list order relevant, though
404 * strictly speaking it should not be. Because of the way syscache list
405 * searches are handled, in normal operation the result will be sorted by OID
406 * so everything works fine. If running with system index usage disabled,
407 * the result ordering is unspecified and hence the planner might fail to
408 * recognize optimization opportunities ... but that's hardly a scenario in
409 * which performance is good anyway, so there's no point in expending code
410 * or cycles here to guarantee the ordering in that case.
413 get_mergejoin_opfamilies(Oid opno)
420 * Search pg_amop to see if the target operator is registered as the "="
421 * operator of any btree opfamily.
423 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
425 for (i = 0; i < catlist->n_members; i++)
427 HeapTuple tuple = &catlist->members[i]->tuple;
428 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
430 /* must be btree equality */
431 if (aform->amopmethod == BTREE_AM_OID &&
432 aform->amopstrategy == BTEqualStrategyNumber)
433 result = lappend_oid(result, aform->amopfamily);
436 ReleaseSysCacheList(catlist);
442 * get_compatible_hash_operators
443 * Get the OID(s) of hash equality operator(s) compatible with the given
444 * operator, but operating on its LHS and/or RHS datatype.
446 * An operator for the LHS type is sought and returned into *lhs_opno if
447 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
448 * and returned into *rhs_opno if rhs_opno isn't NULL.
450 * If the given operator is not cross-type, the results should be the same
451 * operator, but in cross-type situations they will be different.
453 * Returns true if able to find the requested operator(s), false if not.
454 * (This indicates that the operator should not have been marked oprcanhash.)
457 get_compatible_hash_operators(Oid opno,
458 Oid *lhs_opno, Oid *rhs_opno)
464 /* Ensure output args are initialized on failure */
466 *lhs_opno = InvalidOid;
468 *rhs_opno = InvalidOid;
471 * Search pg_amop to see if the target operator is registered as the "="
472 * operator of any hash opfamily. If the operator is registered in
473 * multiple opfamilies, assume we can use any one.
475 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
477 for (i = 0; i < catlist->n_members; i++)
479 HeapTuple tuple = &catlist->members[i]->tuple;
480 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
482 if (aform->amopmethod == HASH_AM_OID &&
483 aform->amopstrategy == HTEqualStrategyNumber)
485 /* No extra lookup needed if given operator is single-type */
486 if (aform->amoplefttype == aform->amoprighttype)
497 * Get the matching single-type operator(s). Failure probably
498 * shouldn't happen --- it implies a bogus opfamily --- but
499 * continue looking if so.
503 *lhs_opno = get_opfamily_member(aform->amopfamily,
506 HTEqualStrategyNumber);
507 if (!OidIsValid(*lhs_opno))
509 /* Matching LHS found, done if caller doesn't want RHS */
518 *rhs_opno = get_opfamily_member(aform->amopfamily,
519 aform->amoprighttype,
520 aform->amoprighttype,
521 HTEqualStrategyNumber);
522 if (!OidIsValid(*rhs_opno))
524 /* Forget any LHS operator from this opfamily */
526 *lhs_opno = InvalidOid;
529 /* Matching RHS found, so done */
536 ReleaseSysCacheList(catlist);
542 * get_op_hash_functions
543 * Get the OID(s) of hash support function(s) compatible with the given
544 * operator, operating on its LHS and/or RHS datatype as required.
546 * A function for the LHS type is sought and returned into *lhs_procno if
547 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
548 * and returned into *rhs_procno if rhs_procno isn't NULL.
550 * If the given operator is not cross-type, the results should be the same
551 * function, but in cross-type situations they will be different.
553 * Returns true if able to find the requested function(s), false if not.
554 * (This indicates that the operator should not have been marked oprcanhash.)
557 get_op_hash_functions(Oid opno,
558 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
564 /* Ensure output args are initialized on failure */
566 *lhs_procno = InvalidOid;
568 *rhs_procno = InvalidOid;
571 * Search pg_amop to see if the target operator is registered as the "="
572 * operator of any hash opfamily. If the operator is registered in
573 * multiple opfamilies, assume we can use any one.
575 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
577 for (i = 0; i < catlist->n_members; i++)
579 HeapTuple tuple = &catlist->members[i]->tuple;
580 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
582 if (aform->amopmethod == HASH_AM_OID &&
583 aform->amopstrategy == HTEqualStrategyNumber)
586 * Get the matching support function(s). Failure probably
587 * shouldn't happen --- it implies a bogus opfamily --- but
588 * continue looking if so.
592 *lhs_procno = get_opfamily_proc(aform->amopfamily,
596 if (!OidIsValid(*lhs_procno))
598 /* Matching LHS found, done if caller doesn't want RHS */
604 /* Only one lookup needed if given operator is single-type */
605 if (aform->amoplefttype == aform->amoprighttype)
607 *rhs_procno = *lhs_procno;
614 *rhs_procno = get_opfamily_proc(aform->amopfamily,
615 aform->amoprighttype,
616 aform->amoprighttype,
618 if (!OidIsValid(*rhs_procno))
620 /* Forget any LHS function from this opfamily */
622 *lhs_procno = InvalidOid;
625 /* Matching RHS found, so done */
632 ReleaseSysCacheList(catlist);
638 * get_op_btree_interpretation
639 * Given an operator's OID, find out which btree opfamilies it belongs to,
640 * and what properties it has within each one. The results are returned
641 * as a palloc'd list of OpBtreeInterpretation structs.
643 * In addition to the normal btree operators, we consider a <> operator to be
644 * a "member" of an opfamily if its negator is an equality operator of the
645 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
648 get_op_btree_interpretation(Oid opno)
651 OpBtreeInterpretation *thisresult;
656 * Find all the pg_amop entries containing the operator.
658 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
660 for (i = 0; i < catlist->n_members; i++)
662 HeapTuple op_tuple = &catlist->members[i]->tuple;
663 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
664 StrategyNumber op_strategy;
667 if (op_form->amopmethod != BTREE_AM_OID)
670 /* Get the operator's btree strategy number */
671 op_strategy = (StrategyNumber) op_form->amopstrategy;
672 Assert(op_strategy >= 1 && op_strategy <= 5);
674 thisresult = (OpBtreeInterpretation *)
675 palloc(sizeof(OpBtreeInterpretation));
676 thisresult->opfamily_id = op_form->amopfamily;
677 thisresult->strategy = op_strategy;
678 thisresult->oplefttype = op_form->amoplefttype;
679 thisresult->oprighttype = op_form->amoprighttype;
680 result = lappend(result, thisresult);
683 ReleaseSysCacheList(catlist);
686 * If we didn't find any btree opfamily containing the operator, perhaps
687 * it is a <> operator. See if it has a negator that is in an opfamily.
691 Oid op_negator = get_negator(opno);
693 if (OidIsValid(op_negator))
695 catlist = SearchSysCacheList1(AMOPOPID,
696 ObjectIdGetDatum(op_negator));
698 for (i = 0; i < catlist->n_members; i++)
700 HeapTuple op_tuple = &catlist->members[i]->tuple;
701 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
702 StrategyNumber op_strategy;
705 if (op_form->amopmethod != BTREE_AM_OID)
708 /* Get the operator's btree strategy number */
709 op_strategy = (StrategyNumber) op_form->amopstrategy;
710 Assert(op_strategy >= 1 && op_strategy <= 5);
712 /* Only consider negators that are = */
713 if (op_strategy != BTEqualStrategyNumber)
716 /* OK, report it with "strategy" ROWCOMPARE_NE */
717 thisresult = (OpBtreeInterpretation *)
718 palloc(sizeof(OpBtreeInterpretation));
719 thisresult->opfamily_id = op_form->amopfamily;
720 thisresult->strategy = ROWCOMPARE_NE;
721 thisresult->oplefttype = op_form->amoplefttype;
722 thisresult->oprighttype = op_form->amoprighttype;
723 result = lappend(result, thisresult);
726 ReleaseSysCacheList(catlist);
734 * equality_ops_are_compatible
735 * Return TRUE if the two given equality operators have compatible
738 * This is trivially true if they are the same operator. Otherwise,
739 * we look to see if they can be found in the same btree or hash opfamily.
740 * Either finding allows us to assume that they have compatible notions
741 * of equality. (The reason we need to do these pushups is that one might
742 * be a cross-type operator; for instance int24eq vs int4eq.)
745 equality_ops_are_compatible(Oid opno1, Oid opno2)
751 /* Easy if they're the same operator */
756 * We search through all the pg_amop entries for opno1.
758 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
761 for (i = 0; i < catlist->n_members; i++)
763 HeapTuple op_tuple = &catlist->members[i]->tuple;
764 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
766 /* must be btree or hash */
767 if (op_form->amopmethod == BTREE_AM_OID ||
768 op_form->amopmethod == HASH_AM_OID)
770 if (op_in_opfamily(opno2, op_form->amopfamily))
778 ReleaseSysCacheList(catlist);
784 /* ---------- AMPROC CACHES ---------- */
788 * Get the OID of the specified support function
789 * for the specified opfamily and datatypes.
791 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
794 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
797 Form_pg_amproc amproc_tup;
800 tp = SearchSysCache4(AMPROCNUM,
801 ObjectIdGetDatum(opfamily),
802 ObjectIdGetDatum(lefttype),
803 ObjectIdGetDatum(righttype),
804 Int16GetDatum(procnum));
805 if (!HeapTupleIsValid(tp))
807 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
808 result = amproc_tup->amproc;
814 /* ---------- ATTRIBUTE CACHES ---------- */
818 * Given the relation id and the attribute number,
819 * return the "attname" field from the attribute relation.
821 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
824 get_attname(Oid relid, AttrNumber attnum)
828 tp = SearchSysCache2(ATTNUM,
829 ObjectIdGetDatum(relid),
830 Int16GetDatum(attnum));
831 if (HeapTupleIsValid(tp))
833 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
836 result = pstrdup(NameStr(att_tup->attname));
845 * get_relid_attribute_name
847 * Same as above routine get_attname(), except that error
848 * is handled by elog() instead of returning NULL.
851 get_relid_attribute_name(Oid relid, AttrNumber attnum)
855 attname = get_attname(relid, attnum);
857 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
865 * Given the relation id and the attribute name,
866 * return the "attnum" field from the attribute relation.
868 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
871 get_attnum(Oid relid, const char *attname)
875 tp = SearchSysCacheAttName(relid, attname);
876 if (HeapTupleIsValid(tp))
878 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
881 result = att_tup->attnum;
886 return InvalidAttrNumber;
892 * Given the relation OID and the attribute number with the relation,
893 * return the attribute type OID.
896 get_atttype(Oid relid, AttrNumber attnum)
900 tp = SearchSysCache2(ATTNUM,
901 ObjectIdGetDatum(relid),
902 Int16GetDatum(attnum));
903 if (HeapTupleIsValid(tp))
905 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
908 result = att_tup->atttypid;
919 * Given the relation id and the attribute number,
920 * return the "atttypmod" field from the attribute relation.
923 get_atttypmod(Oid relid, AttrNumber attnum)
927 tp = SearchSysCache2(ATTNUM,
928 ObjectIdGetDatum(relid),
929 Int16GetDatum(attnum));
930 if (HeapTupleIsValid(tp))
932 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
935 result = att_tup->atttypmod;
944 * get_atttypetypmodcoll
946 * A three-fer: given the relation id and the attribute number,
947 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
949 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
950 * raises an error if it can't obtain the information.
953 get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
954 Oid *typid, int32 *typmod, Oid *collid)
957 Form_pg_attribute att_tup;
959 tp = SearchSysCache2(ATTNUM,
960 ObjectIdGetDatum(relid),
961 Int16GetDatum(attnum));
962 if (!HeapTupleIsValid(tp))
963 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
965 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
967 *typid = att_tup->atttypid;
968 *typmod = att_tup->atttypmod;
969 *collid = att_tup->attcollation;
973 /* ---------- COLLATION CACHE ---------- */
977 * Returns the name of a given pg_collation entry.
979 * Returns a palloc'd copy of the string, or NULL if no such constraint.
981 * NOTE: since collation name is not unique, be wary of code that uses this
982 * for anything except preparing error messages.
985 get_collation_name(Oid colloid)
989 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
990 if (HeapTupleIsValid(tp))
992 Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
995 result = pstrdup(NameStr(colltup->collname));
1003 /* ---------- CONSTRAINT CACHE ---------- */
1006 * get_constraint_name
1007 * Returns the name of a given pg_constraint entry.
1009 * Returns a palloc'd copy of the string, or NULL if no such constraint.
1011 * NOTE: since constraint name is not unique, be wary of code that uses this
1012 * for anything except preparing error messages.
1015 get_constraint_name(Oid conoid)
1019 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1020 if (HeapTupleIsValid(tp))
1022 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
1025 result = pstrdup(NameStr(contup->conname));
1026 ReleaseSysCache(tp);
1033 /* ---------- OPCLASS CACHE ---------- */
1036 * get_opclass_family
1038 * Returns the OID of the operator family the opclass belongs to.
1041 get_opclass_family(Oid opclass)
1044 Form_pg_opclass cla_tup;
1047 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1048 if (!HeapTupleIsValid(tp))
1049 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1050 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1052 result = cla_tup->opcfamily;
1053 ReleaseSysCache(tp);
1058 * get_opclass_input_type
1060 * Returns the OID of the datatype the opclass indexes.
1063 get_opclass_input_type(Oid opclass)
1066 Form_pg_opclass cla_tup;
1069 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1070 if (!HeapTupleIsValid(tp))
1071 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1072 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1074 result = cla_tup->opcintype;
1075 ReleaseSysCache(tp);
1079 /* ---------- OPERATOR CACHE ---------- */
1084 * Returns the regproc id of the routine used to implement an
1085 * operator given the operator oid.
1088 get_opcode(Oid opno)
1092 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1093 if (HeapTupleIsValid(tp))
1095 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1096 RegProcedure result;
1098 result = optup->oprcode;
1099 ReleaseSysCache(tp);
1103 return (RegProcedure) InvalidOid;
1108 * returns the name of the operator with the given opno
1110 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1113 get_opname(Oid opno)
1117 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1118 if (HeapTupleIsValid(tp))
1120 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1123 result = pstrdup(NameStr(optup->oprname));
1124 ReleaseSysCache(tp);
1134 * Returns the left and right input datatypes for an operator
1135 * (InvalidOid if not relevant).
1138 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1141 Form_pg_operator optup;
1143 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1144 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1145 elog(ERROR, "cache lookup failed for operator %u", opno);
1146 optup = (Form_pg_operator) GETSTRUCT(tp);
1147 *lefttype = optup->oprleft;
1148 *righttype = optup->oprright;
1149 ReleaseSysCache(tp);
1155 * Returns true if the operator is potentially mergejoinable. (The planner
1156 * will fail to find any mergejoin plans unless there are suitable btree
1157 * opfamily entries for this operator and associated sortops. The pg_operator
1158 * flag is just a hint to tell the planner whether to bother looking.)
1160 * In some cases (currently only array_eq and record_eq), mergejoinability
1161 * depends on the specific input data type the operator is invoked for, so
1162 * that must be passed as well. We currently assume that only one input's type
1163 * is needed to check this --- by convention, pass the left input's data type.
1166 op_mergejoinable(Oid opno, Oid inputtype)
1168 bool result = false;
1170 TypeCacheEntry *typentry;
1173 * For array_eq or record_eq, we can sort if the element or field types
1174 * are all sortable. We could implement all the checks for that here, but
1175 * the typcache already does that and caches the results too, so let's
1176 * rely on the typcache.
1178 if (opno == ARRAY_EQ_OP)
1180 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1181 if (typentry->cmp_proc == F_BTARRAYCMP)
1184 else if (opno == RECORD_EQ_OP)
1186 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1187 if (typentry->cmp_proc == F_BTRECORDCMP)
1192 /* For all other operators, rely on pg_operator.oprcanmerge */
1193 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1194 if (HeapTupleIsValid(tp))
1196 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1198 result = optup->oprcanmerge;
1199 ReleaseSysCache(tp);
1208 * Returns true if the operator is hashjoinable. (There must be a suitable
1209 * hash opfamily entry for this operator if it is so marked.)
1211 * In some cases (currently only array_eq), hashjoinability depends on the
1212 * specific input data type the operator is invoked for, so that must be
1213 * passed as well. We currently assume that only one input's type is needed
1214 * to check this --- by convention, pass the left input's data type.
1217 op_hashjoinable(Oid opno, Oid inputtype)
1219 bool result = false;
1221 TypeCacheEntry *typentry;
1223 /* As in op_mergejoinable, let the typcache handle the hard cases */
1224 /* Eventually we'll need a similar case for record_eq ... */
1225 if (opno == ARRAY_EQ_OP)
1227 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1228 if (typentry->hash_proc == F_HASH_ARRAY)
1233 /* For all other operators, rely on pg_operator.oprcanhash */
1234 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1235 if (HeapTupleIsValid(tp))
1237 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1239 result = optup->oprcanhash;
1240 ReleaseSysCache(tp);
1249 * Get the proisstrict flag for the operator's underlying function.
1254 RegProcedure funcid = get_opcode(opno);
1256 if (funcid == (RegProcedure) InvalidOid)
1257 elog(ERROR, "operator %u does not exist", opno);
1259 return func_strict((Oid) funcid);
1265 * Get the provolatile flag for the operator's underlying function.
1268 op_volatile(Oid opno)
1270 RegProcedure funcid = get_opcode(opno);
1272 if (funcid == (RegProcedure) InvalidOid)
1273 elog(ERROR, "operator %u does not exist", opno);
1275 return func_volatile((Oid) funcid);
1281 * Returns the corresponding commutator of an operator.
1284 get_commutator(Oid opno)
1288 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1289 if (HeapTupleIsValid(tp))
1291 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1294 result = optup->oprcom;
1295 ReleaseSysCache(tp);
1305 * Returns the corresponding negator of an operator.
1308 get_negator(Oid opno)
1312 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1313 if (HeapTupleIsValid(tp))
1315 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1318 result = optup->oprnegate;
1319 ReleaseSysCache(tp);
1329 * Returns procedure id for computing selectivity of an operator.
1332 get_oprrest(Oid opno)
1336 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1337 if (HeapTupleIsValid(tp))
1339 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1340 RegProcedure result;
1342 result = optup->oprrest;
1343 ReleaseSysCache(tp);
1347 return (RegProcedure) InvalidOid;
1353 * Returns procedure id for computing selectivity of a join.
1356 get_oprjoin(Oid opno)
1360 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1361 if (HeapTupleIsValid(tp))
1363 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1364 RegProcedure result;
1366 result = optup->oprjoin;
1367 ReleaseSysCache(tp);
1371 return (RegProcedure) InvalidOid;
1374 /* ---------- FUNCTION CACHE ---------- */
1378 * returns the name of the function with the given funcid
1380 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1383 get_func_name(Oid funcid)
1387 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1388 if (HeapTupleIsValid(tp))
1390 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1393 result = pstrdup(NameStr(functup->proname));
1394 ReleaseSysCache(tp);
1402 * get_func_namespace
1404 * Returns the pg_namespace OID associated with a given function.
1407 get_func_namespace(Oid funcid)
1411 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1412 if (HeapTupleIsValid(tp))
1414 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1417 result = functup->pronamespace;
1418 ReleaseSysCache(tp);
1427 * Given procedure id, return the function's result type.
1430 get_func_rettype(Oid funcid)
1435 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1436 if (!HeapTupleIsValid(tp))
1437 elog(ERROR, "cache lookup failed for function %u", funcid);
1439 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1440 ReleaseSysCache(tp);
1446 * Given procedure id, return the number of arguments.
1449 get_func_nargs(Oid funcid)
1454 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1455 if (!HeapTupleIsValid(tp))
1456 elog(ERROR, "cache lookup failed for function %u", funcid);
1458 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1459 ReleaseSysCache(tp);
1464 * get_func_signature
1465 * Given procedure id, return the function's argument and result types.
1466 * (The return value is the result type.)
1468 * The arguments are returned as a palloc'd array.
1471 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1474 Form_pg_proc procstruct;
1477 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1478 if (!HeapTupleIsValid(tp))
1479 elog(ERROR, "cache lookup failed for function %u", funcid);
1481 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1483 result = procstruct->prorettype;
1484 *nargs = (int) procstruct->pronargs;
1485 Assert(*nargs == procstruct->proargtypes.dim1);
1486 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1487 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1489 ReleaseSysCache(tp);
1495 * Given procedure id, return the function's proretset flag.
1498 get_func_retset(Oid funcid)
1503 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1504 if (!HeapTupleIsValid(tp))
1505 elog(ERROR, "cache lookup failed for function %u", funcid);
1507 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1508 ReleaseSysCache(tp);
1514 * Given procedure id, return the function's proisstrict flag.
1517 func_strict(Oid funcid)
1522 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1523 if (!HeapTupleIsValid(tp))
1524 elog(ERROR, "cache lookup failed for function %u", funcid);
1526 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1527 ReleaseSysCache(tp);
1533 * Given procedure id, return the function's provolatile flag.
1536 func_volatile(Oid funcid)
1541 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1542 if (!HeapTupleIsValid(tp))
1543 elog(ERROR, "cache lookup failed for function %u", funcid);
1545 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1546 ReleaseSysCache(tp);
1552 * Given procedure id, return the function's procost field.
1555 get_func_cost(Oid funcid)
1560 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1561 if (!HeapTupleIsValid(tp))
1562 elog(ERROR, "cache lookup failed for function %u", funcid);
1564 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1565 ReleaseSysCache(tp);
1571 * Given procedure id, return the function's prorows field.
1574 get_func_rows(Oid funcid)
1579 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1580 if (!HeapTupleIsValid(tp))
1581 elog(ERROR, "cache lookup failed for function %u", funcid);
1583 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1584 ReleaseSysCache(tp);
1588 /* ---------- RELATION CACHE ---------- */
1592 * Given name and namespace of a relation, look up the OID.
1594 * Returns InvalidOid if there is no such relation.
1597 get_relname_relid(const char *relname, Oid relnamespace)
1599 return GetSysCacheOid2(RELNAMENSP,
1600 PointerGetDatum(relname),
1601 ObjectIdGetDatum(relnamespace));
1608 * Returns the number of attributes for a given relation.
1611 get_relnatts(Oid relid)
1615 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1616 if (HeapTupleIsValid(tp))
1618 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1621 result = reltup->relnatts;
1622 ReleaseSysCache(tp);
1626 return InvalidAttrNumber;
1632 * Returns the name of a given relation.
1634 * Returns a palloc'd copy of the string, or NULL if no such relation.
1636 * NOTE: since relation name is not unique, be wary of code that uses this
1637 * for anything except preparing error messages.
1640 get_rel_name(Oid relid)
1644 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1645 if (HeapTupleIsValid(tp))
1647 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1650 result = pstrdup(NameStr(reltup->relname));
1651 ReleaseSysCache(tp);
1661 * Returns the pg_namespace OID associated with a given relation.
1664 get_rel_namespace(Oid relid)
1668 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1669 if (HeapTupleIsValid(tp))
1671 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1674 result = reltup->relnamespace;
1675 ReleaseSysCache(tp);
1685 * Returns the pg_type OID associated with a given relation.
1687 * Note: not all pg_class entries have associated pg_type OIDs; so be
1688 * careful to check for InvalidOid result.
1691 get_rel_type_id(Oid relid)
1695 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1696 if (HeapTupleIsValid(tp))
1698 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1701 result = reltup->reltype;
1702 ReleaseSysCache(tp);
1712 * Returns the relkind associated with a given relation.
1715 get_rel_relkind(Oid relid)
1719 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1720 if (HeapTupleIsValid(tp))
1722 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1725 result = reltup->relkind;
1726 ReleaseSysCache(tp);
1734 * get_rel_tablespace
1736 * Returns the pg_tablespace OID associated with a given relation.
1738 * Note: InvalidOid might mean either that we couldn't find the relation,
1739 * or that it is in the database's default tablespace.
1742 get_rel_tablespace(Oid relid)
1746 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1747 if (HeapTupleIsValid(tp))
1749 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1752 result = reltup->reltablespace;
1753 ReleaseSysCache(tp);
1761 /* ---------- TYPE CACHE ---------- */
1766 * Given the type OID, determine whether the type is defined
1767 * (if not, it's only a shell).
1770 get_typisdefined(Oid typid)
1774 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1775 if (HeapTupleIsValid(tp))
1777 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1780 result = typtup->typisdefined;
1781 ReleaseSysCache(tp);
1791 * Given the type OID, return the length of the type.
1794 get_typlen(Oid typid)
1798 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1799 if (HeapTupleIsValid(tp))
1801 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1804 result = typtup->typlen;
1805 ReleaseSysCache(tp);
1815 * Given the type OID, determine whether the type is returned by value or
1816 * not. Returns true if by value, false if by reference.
1819 get_typbyval(Oid typid)
1823 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1824 if (HeapTupleIsValid(tp))
1826 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1829 result = typtup->typbyval;
1830 ReleaseSysCache(tp);
1840 * A two-fer: given the type OID, return both typlen and typbyval.
1842 * Since both pieces of info are needed to know how to copy a Datum,
1843 * many places need both. Might as well get them with one cache lookup
1844 * instead of two. Also, this routine raises an error instead of
1845 * returning a bogus value when given a bad type OID.
1848 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1851 Form_pg_type typtup;
1853 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1854 if (!HeapTupleIsValid(tp))
1855 elog(ERROR, "cache lookup failed for type %u", typid);
1856 typtup = (Form_pg_type) GETSTRUCT(tp);
1857 *typlen = typtup->typlen;
1858 *typbyval = typtup->typbyval;
1859 ReleaseSysCache(tp);
1863 * get_typlenbyvalalign
1865 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1868 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1872 Form_pg_type typtup;
1874 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1875 if (!HeapTupleIsValid(tp))
1876 elog(ERROR, "cache lookup failed for type %u", typid);
1877 typtup = (Form_pg_type) GETSTRUCT(tp);
1878 *typlen = typtup->typlen;
1879 *typbyval = typtup->typbyval;
1880 *typalign = typtup->typalign;
1881 ReleaseSysCache(tp);
1886 * Given a pg_type row, select the type OID to pass to I/O functions
1888 * Formerly, all I/O functions were passed pg_type.typelem as their second
1889 * parameter, but we now have a more complex rule about what to pass.
1890 * This knowledge is intended to be centralized here --- direct references
1891 * to typelem elsewhere in the code are wrong, if they are associated with
1892 * I/O calls and not with actual subscripting operations! (But see
1893 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1895 * As of PostgreSQL 8.1, output functions receive only the value itself
1896 * and not any auxiliary parameters, so the name of this routine is now
1897 * a bit of a misnomer ... it should be getTypeInputParam.
1900 getTypeIOParam(HeapTuple typeTuple)
1902 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1905 * Array types get their typelem as parameter; everybody else gets their
1906 * own type OID as parameter.
1908 if (OidIsValid(typeStruct->typelem))
1909 return typeStruct->typelem;
1911 return HeapTupleGetOid(typeTuple);
1917 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1918 * typdelim, typioparam, and IO function OID. The IO function
1919 * returned is controlled by IOFuncSelector
1922 get_type_io_data(Oid typid,
1923 IOFuncSelector which_func,
1931 HeapTuple typeTuple;
1932 Form_pg_type typeStruct;
1935 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1936 * use array_in and array_out during bootstrap.
1938 if (IsBootstrapProcessingMode())
1943 boot_get_type_io_data(typid,
1960 elog(ERROR, "binary I/O not supported during bootstrap");
1966 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1967 if (!HeapTupleIsValid(typeTuple))
1968 elog(ERROR, "cache lookup failed for type %u", typid);
1969 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1971 *typlen = typeStruct->typlen;
1972 *typbyval = typeStruct->typbyval;
1973 *typalign = typeStruct->typalign;
1974 *typdelim = typeStruct->typdelim;
1975 *typioparam = getTypeIOParam(typeTuple);
1979 *func = typeStruct->typinput;
1982 *func = typeStruct->typoutput;
1984 case IOFunc_receive:
1985 *func = typeStruct->typreceive;
1988 *func = typeStruct->typsend;
1991 ReleaseSysCache(typeTuple);
1996 get_typalign(Oid typid)
2000 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2001 if (HeapTupleIsValid(tp))
2003 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2006 result = typtup->typalign;
2007 ReleaseSysCache(tp);
2016 get_typstorage(Oid typid)
2020 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2021 if (HeapTupleIsValid(tp))
2023 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2026 result = typtup->typstorage;
2027 ReleaseSysCache(tp);
2036 * Given a type OID, return the type's default value, if any.
2038 * The result is a palloc'd expression node tree, or NULL if there
2039 * is no defined default for the datatype.
2041 * NB: caller should be prepared to coerce result to correct datatype;
2042 * the returned expression tree might produce something of the wrong type.
2045 get_typdefault(Oid typid)
2047 HeapTuple typeTuple;
2053 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2054 if (!HeapTupleIsValid(typeTuple))
2055 elog(ERROR, "cache lookup failed for type %u", typid);
2056 type = (Form_pg_type) GETSTRUCT(typeTuple);
2059 * typdefault and typdefaultbin are potentially null, so don't try to
2060 * access 'em as struct fields. Must do it the hard way with
2063 datum = SysCacheGetAttr(TYPEOID,
2065 Anum_pg_type_typdefaultbin,
2070 /* We have an expression default */
2071 expr = stringToNode(TextDatumGetCString(datum));
2075 /* Perhaps we have a plain literal default */
2076 datum = SysCacheGetAttr(TYPEOID,
2078 Anum_pg_type_typdefault,
2083 char *strDefaultVal;
2085 /* Convert text datum to C string */
2086 strDefaultVal = TextDatumGetCString(datum);
2087 /* Convert C string to a value of the given type */
2088 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2089 getTypeIOParam(typeTuple), -1);
2090 /* Build a Const node containing the value */
2091 expr = (Node *) makeConst(typid,
2098 pfree(strDefaultVal);
2107 ReleaseSysCache(typeTuple);
2114 * If the given type is a domain, return its base type;
2115 * otherwise return the type's own OID.
2118 getBaseType(Oid typid)
2122 return getBaseTypeAndTypmod(typid, &typmod);
2126 * getBaseTypeAndTypmod
2127 * If the given type is a domain, return its base type and typmod;
2128 * otherwise return the type's own OID, and leave *typmod unchanged.
2130 * Note that the "applied typmod" should be -1 for every domain level
2131 * above the bottommost; therefore, if the passed-in typid is indeed
2132 * a domain, *typmod should be -1.
2135 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2138 * We loop to find the bottom base type in a stack of domains.
2143 Form_pg_type typTup;
2145 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2146 if (!HeapTupleIsValid(tup))
2147 elog(ERROR, "cache lookup failed for type %u", typid);
2148 typTup = (Form_pg_type) GETSTRUCT(tup);
2149 if (typTup->typtype != TYPTYPE_DOMAIN)
2151 /* Not a domain, so done */
2152 ReleaseSysCache(tup);
2156 Assert(*typmod == -1);
2157 typid = typTup->typbasetype;
2158 *typmod = typTup->typtypmod;
2160 ReleaseSysCache(tup);
2169 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2170 * estimate the average width of values of the type. This is used by
2171 * the planner, which doesn't require absolutely correct results;
2172 * it's OK (and expected) to guess if we don't know for sure.
2175 get_typavgwidth(Oid typid, int32 typmod)
2177 int typlen = get_typlen(typid);
2181 * Easy if it's a fixed-width type
2187 * type_maximum_size knows the encoding of typmod for some datatypes;
2188 * don't duplicate that knowledge here.
2190 maxwidth = type_maximum_size(typid, typmod);
2194 * For BPCHAR, the max width is also the only width. Otherwise we
2195 * need to guess about the typical data width given the max. A sliding
2196 * scale for percentage of max width seems reasonable.
2198 if (typid == BPCHAROID)
2201 return maxwidth; /* assume full width */
2202 if (maxwidth < 1000)
2203 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2206 * Beyond 1000, assume we're looking at something like
2207 * "varchar(10000)" where the limit isn't actually reached often, and
2208 * use a fixed estimate.
2210 return 32 + (1000 - 32) / 2;
2214 * Ooops, we have no idea ... wild guess time.
2222 * Given the type OID, find if it is a basic type, a complex type, etc.
2223 * It returns the null char if the cache lookup fails...
2226 get_typtype(Oid typid)
2230 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2231 if (HeapTupleIsValid(tp))
2233 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2236 result = typtup->typtype;
2237 ReleaseSysCache(tp);
2247 * Convenience function to determine whether a type OID represents
2248 * a "rowtype" type --- either RECORD or a named composite type.
2251 type_is_rowtype(Oid typid)
2253 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2258 * Returns true if the given type is an enum type.
2261 type_is_enum(Oid typid)
2263 return (get_typtype(typid) == TYPTYPE_ENUM);
2268 * Returns true if the given type is a range type.
2271 type_is_range(Oid typid)
2273 return (get_typtype(typid) == TYPTYPE_RANGE);
2277 * get_type_category_preferred
2279 * Given the type OID, fetch its category and preferred-type status.
2280 * Throws error on failure.
2283 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2286 Form_pg_type typtup;
2288 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2289 if (!HeapTupleIsValid(tp))
2290 elog(ERROR, "cache lookup failed for type %u", typid);
2291 typtup = (Form_pg_type) GETSTRUCT(tp);
2292 *typcategory = typtup->typcategory;
2293 *typispreferred = typtup->typispreferred;
2294 ReleaseSysCache(tp);
2300 * Given the type OID, get the typrelid (InvalidOid if not a complex
2304 get_typ_typrelid(Oid typid)
2308 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2309 if (HeapTupleIsValid(tp))
2311 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2314 result = typtup->typrelid;
2315 ReleaseSysCache(tp);
2325 * Given the type OID, get the typelem (InvalidOid if not an array type).
2327 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2328 * returned if the input is a fixed-length array type.
2331 get_element_type(Oid typid)
2335 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2336 if (HeapTupleIsValid(tp))
2338 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2341 if (typtup->typlen == -1)
2342 result = typtup->typelem;
2344 result = InvalidOid;
2345 ReleaseSysCache(tp);
2355 * Given the type OID, get the corresponding "true" array type.
2356 * Returns InvalidOid if no array type can be found.
2359 get_array_type(Oid typid)
2362 Oid result = InvalidOid;
2364 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2365 if (HeapTupleIsValid(tp))
2367 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2368 ReleaseSysCache(tp);
2374 * get_base_element_type
2375 * Given the type OID, get the typelem, looking "through" any domain
2376 * to its underlying array type.
2378 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2379 * an extra cache lookup. Note that it fails to provide any information
2380 * about the typmod of the array.
2383 get_base_element_type(Oid typid)
2386 * We loop to find the bottom base type in a stack of domains.
2391 Form_pg_type typTup;
2393 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2394 if (!HeapTupleIsValid(tup))
2396 typTup = (Form_pg_type) GETSTRUCT(tup);
2397 if (typTup->typtype != TYPTYPE_DOMAIN)
2399 /* Not a domain, so stop descending */
2402 /* This test must match get_element_type */
2403 if (typTup->typlen == -1)
2404 result = typTup->typelem;
2406 result = InvalidOid;
2407 ReleaseSysCache(tup);
2411 typid = typTup->typbasetype;
2412 ReleaseSysCache(tup);
2415 /* Like get_element_type, silently return InvalidOid for bogus input */
2422 * Get info needed for converting values of a type to internal form
2425 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2427 HeapTuple typeTuple;
2430 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2431 if (!HeapTupleIsValid(typeTuple))
2432 elog(ERROR, "cache lookup failed for type %u", type);
2433 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2435 if (!pt->typisdefined)
2437 (errcode(ERRCODE_UNDEFINED_OBJECT),
2438 errmsg("type %s is only a shell",
2439 format_type_be(type))));
2440 if (!OidIsValid(pt->typinput))
2442 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2443 errmsg("no input function available for type %s",
2444 format_type_be(type))));
2446 *typInput = pt->typinput;
2447 *typIOParam = getTypeIOParam(typeTuple);
2449 ReleaseSysCache(typeTuple);
2455 * Get info needed for printing values of a type
2458 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2460 HeapTuple typeTuple;
2463 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2464 if (!HeapTupleIsValid(typeTuple))
2465 elog(ERROR, "cache lookup failed for type %u", type);
2466 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2468 if (!pt->typisdefined)
2470 (errcode(ERRCODE_UNDEFINED_OBJECT),
2471 errmsg("type %s is only a shell",
2472 format_type_be(type))));
2473 if (!OidIsValid(pt->typoutput))
2475 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2476 errmsg("no output function available for type %s",
2477 format_type_be(type))));
2479 *typOutput = pt->typoutput;
2480 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2482 ReleaseSysCache(typeTuple);
2486 * getTypeBinaryInputInfo
2488 * Get info needed for binary input of values of a type
2491 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2493 HeapTuple typeTuple;
2496 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2497 if (!HeapTupleIsValid(typeTuple))
2498 elog(ERROR, "cache lookup failed for type %u", type);
2499 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2501 if (!pt->typisdefined)
2503 (errcode(ERRCODE_UNDEFINED_OBJECT),
2504 errmsg("type %s is only a shell",
2505 format_type_be(type))));
2506 if (!OidIsValid(pt->typreceive))
2508 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2509 errmsg("no binary input function available for type %s",
2510 format_type_be(type))));
2512 *typReceive = pt->typreceive;
2513 *typIOParam = getTypeIOParam(typeTuple);
2515 ReleaseSysCache(typeTuple);
2519 * getTypeBinaryOutputInfo
2521 * Get info needed for binary output of values of a type
2524 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2526 HeapTuple typeTuple;
2529 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2530 if (!HeapTupleIsValid(typeTuple))
2531 elog(ERROR, "cache lookup failed for type %u", type);
2532 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2534 if (!pt->typisdefined)
2536 (errcode(ERRCODE_UNDEFINED_OBJECT),
2537 errmsg("type %s is only a shell",
2538 format_type_be(type))));
2539 if (!OidIsValid(pt->typsend))
2541 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2542 errmsg("no binary output function available for type %s",
2543 format_type_be(type))));
2545 *typSend = pt->typsend;
2546 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2548 ReleaseSysCache(typeTuple);
2554 * Given the type OID, return the type's typmodin procedure, if any.
2557 get_typmodin(Oid typid)
2561 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2562 if (HeapTupleIsValid(tp))
2564 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2567 result = typtup->typmodin;
2568 ReleaseSysCache(tp);
2579 * Given the type OID, return the type's typmodout procedure, if any.
2582 get_typmodout(Oid typid)
2586 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2587 if (HeapTupleIsValid(tp))
2589 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2592 result = typtup->typmodout;
2593 ReleaseSysCache(tp);
2599 #endif /* NOT_USED */
2604 * Given the type OID, return the type's typcollation attribute.
2607 get_typcollation(Oid typid)
2611 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2612 if (HeapTupleIsValid(tp))
2614 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2617 result = typtup->typcollation;
2618 ReleaseSysCache(tp);
2627 * type_is_collatable
2629 * Return whether the type cares about collations
2632 type_is_collatable(Oid typid)
2634 return OidIsValid(get_typcollation(typid));
2638 /* ---------- STATISTICS CACHE ---------- */
2643 * Given the table and attribute number of a column, get the average
2644 * width of entries in the column. Return zero if no data available.
2646 * Currently this is only consulted for individual tables, not for inheritance
2647 * trees, so we don't need an "inh" parameter.
2649 * Calling a hook at this point looks somewhat strange, but is required
2650 * because the optimizer calls this function without any other way for
2651 * plug-ins to control the result.
2654 get_attavgwidth(Oid relid, AttrNumber attnum)
2659 if (get_attavgwidth_hook)
2661 stawidth = (*get_attavgwidth_hook) (relid, attnum);
2665 tp = SearchSysCache3(STATRELATTINH,
2666 ObjectIdGetDatum(relid),
2667 Int16GetDatum(attnum),
2668 BoolGetDatum(false));
2669 if (HeapTupleIsValid(tp))
2671 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2672 ReleaseSysCache(tp);
2682 * Extract the contents of a "slot" of a pg_statistic tuple.
2683 * Returns TRUE if requested slot type was found, else FALSE.
2685 * Unlike other routines in this file, this takes a pointer to an
2686 * already-looked-up tuple in the pg_statistic cache. We do this since
2687 * most callers will want to extract more than one value from the cache
2688 * entry, and we don't want to repeat the cache lookup unnecessarily.
2689 * Also, this API allows this routine to be used with statistics tuples
2690 * that have been provided by a stats hook and didn't really come from
2693 * statstuple: pg_statistics tuple to be examined.
2694 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2695 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2696 * reqkind: STAKIND code for desired statistics slot kind.
2697 * reqop: STAOP value wanted, or InvalidOid if don't care.
2698 * actualop: if not NULL, *actualop receives the actual STAOP value.
2699 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2700 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2702 * If assigned, values and numbers are set to point to palloc'd arrays.
2703 * If the attribute type is pass-by-reference, the values referenced by
2704 * the values array are themselves palloc'd. The palloc'd stuff can be
2705 * freed by calling free_attstatsslot.
2707 * Note: at present, atttype/atttypmod aren't actually used here at all.
2708 * But the caller must have the correct (or at least binary-compatible)
2709 * type ID to pass to free_attstatsslot later.
2712 get_attstatsslot(HeapTuple statstuple,
2713 Oid atttype, int32 atttypmod,
2714 int reqkind, Oid reqop,
2716 Datum **values, int *nvalues,
2717 float4 **numbers, int *nnumbers)
2719 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2724 ArrayType *statarray;
2727 HeapTuple typeTuple;
2728 Form_pg_type typeForm;
2730 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2732 if ((&stats->stakind1)[i] == reqkind &&
2733 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2736 if (i >= STATISTIC_NUM_SLOTS)
2737 return false; /* not there */
2740 *actualop = (&stats->staop1)[i];
2744 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2745 Anum_pg_statistic_stavalues1 + i,
2748 elog(ERROR, "stavalues is null");
2749 statarray = DatumGetArrayTypeP(val);
2752 * Need to get info about the array element type. We look at the
2753 * actual element type embedded in the array, which might be only
2754 * binary-compatible with the passed-in atttype. The info we extract
2755 * here should be the same either way, but deconstruct_array is picky
2756 * about having an exact type OID match.
2758 arrayelemtype = ARR_ELEMTYPE(statarray);
2759 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
2760 if (!HeapTupleIsValid(typeTuple))
2761 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
2762 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2764 /* Deconstruct array into Datum elements; NULLs not expected */
2765 deconstruct_array(statarray,
2770 values, NULL, nvalues);
2773 * If the element type is pass-by-reference, we now have a bunch of
2774 * Datums that are pointers into the syscache value. Copy them to
2775 * avoid problems if syscache decides to drop the entry.
2777 if (!typeForm->typbyval)
2779 for (j = 0; j < *nvalues; j++)
2781 (*values)[j] = datumCopy((*values)[j],
2787 ReleaseSysCache(typeTuple);
2790 * Free statarray if it's a detoasted copy.
2792 if ((Pointer) statarray != DatumGetPointer(val))
2798 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2799 Anum_pg_statistic_stanumbers1 + i,
2802 elog(ERROR, "stanumbers is null");
2803 statarray = DatumGetArrayTypeP(val);
2806 * We expect the array to be a 1-D float4 array; verify that. We don't
2807 * need to use deconstruct_array() since the array data is just going
2808 * to look like a C array of float4 values.
2810 narrayelem = ARR_DIMS(statarray)[0];
2811 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2812 ARR_HASNULL(statarray) ||
2813 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2814 elog(ERROR, "stanumbers is not a 1-D float4 array");
2815 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2816 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2817 *nnumbers = narrayelem;
2820 * Free statarray if it's a detoasted copy.
2822 if ((Pointer) statarray != DatumGetPointer(val))
2831 * Free data allocated by get_attstatsslot
2833 * atttype need be valid only if values != NULL.
2836 free_attstatsslot(Oid atttype,
2837 Datum *values, int nvalues,
2838 float4 *numbers, int nnumbers)
2842 if (!get_typbyval(atttype))
2846 for (i = 0; i < nvalues; i++)
2847 pfree(DatumGetPointer(values[i]));
2855 /* ---------- PG_NAMESPACE CACHE ---------- */
2858 * get_namespace_name
2859 * Returns the name of a given namespace
2861 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2864 get_namespace_name(Oid nspid)
2868 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
2869 if (HeapTupleIsValid(tp))
2871 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2874 result = pstrdup(NameStr(nsptup->nspname));
2875 ReleaseSysCache(tp);
2882 /* ---------- PG_RANGE CACHE ---------- */
2886 * Returns the subtype of a given range type
2888 * Returns InvalidOid if the type is not a range type.
2891 get_range_subtype(Oid rangeOid)
2895 tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
2896 if (HeapTupleIsValid(tp))
2898 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
2901 result = rngtup->rngsubtype;
2902 ReleaseSysCache(tp);