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_statistic.h"
30 #include "catalog/pg_type.h"
31 #include "miscadmin.h"
32 #include "nodes/makefuncs.h"
33 #include "utils/array.h"
34 #include "utils/builtins.h"
35 #include "utils/datum.h"
36 #include "utils/fmgroids.h"
37 #include "utils/lsyscache.h"
38 #include "utils/rel.h"
39 #include "utils/syscache.h"
40 #include "utils/typcache.h"
42 /* Hook for plugins to get control in get_attavgwidth() */
43 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
46 /* ---------- AMOP CACHES ---------- */
51 * Return t iff operator 'opno' is in operator family 'opfamily'.
53 * This function only considers search operators, not ordering operators.
56 op_in_opfamily(Oid opno, Oid opfamily)
58 return SearchSysCacheExists3(AMOPOPID,
59 ObjectIdGetDatum(opno),
60 CharGetDatum(AMOP_SEARCH),
61 ObjectIdGetDatum(opfamily));
65 * get_op_opfamily_strategy
67 * Get the operator's strategy number within the specified opfamily,
68 * or 0 if it's not a member of the opfamily.
70 * This function only considers search operators, not ordering operators.
73 get_op_opfamily_strategy(Oid opno, Oid opfamily)
76 Form_pg_amop amop_tup;
79 tp = SearchSysCache3(AMOPOPID,
80 ObjectIdGetDatum(opno),
81 CharGetDatum(AMOP_SEARCH),
82 ObjectIdGetDatum(opfamily));
83 if (!HeapTupleIsValid(tp))
85 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
86 result = amop_tup->amopstrategy;
92 * get_op_opfamily_sortfamily
94 * If the operator is an ordering operator within the specified opfamily,
95 * return its amopsortfamily OID; else return InvalidOid.
98 get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
101 Form_pg_amop amop_tup;
104 tp = SearchSysCache3(AMOPOPID,
105 ObjectIdGetDatum(opno),
106 CharGetDatum(AMOP_ORDER),
107 ObjectIdGetDatum(opfamily));
108 if (!HeapTupleIsValid(tp))
110 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
111 result = amop_tup->amopsortfamily;
117 * get_op_opfamily_properties
119 * Get the operator's strategy number and declared input data types
120 * within the specified opfamily.
122 * Caller should already have verified that opno is a member of opfamily,
123 * therefore we raise an error if the tuple is not found.
126 get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
132 Form_pg_amop amop_tup;
134 tp = SearchSysCache3(AMOPOPID,
135 ObjectIdGetDatum(opno),
136 CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
137 ObjectIdGetDatum(opfamily));
138 if (!HeapTupleIsValid(tp))
139 elog(ERROR, "operator %u is not a member of opfamily %u",
141 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
142 *strategy = amop_tup->amopstrategy;
143 *lefttype = amop_tup->amoplefttype;
144 *righttype = amop_tup->amoprighttype;
149 * get_opfamily_member
150 * Get the OID of the operator that implements the specified strategy
151 * with the specified datatypes for the specified opfamily.
153 * Returns InvalidOid if there is no pg_amop entry for the given keys.
156 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
160 Form_pg_amop amop_tup;
163 tp = SearchSysCache4(AMOPSTRATEGY,
164 ObjectIdGetDatum(opfamily),
165 ObjectIdGetDatum(lefttype),
166 ObjectIdGetDatum(righttype),
167 Int16GetDatum(strategy));
168 if (!HeapTupleIsValid(tp))
170 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
171 result = amop_tup->amopopr;
177 * get_ordering_op_properties
178 * Given the OID of an ordering operator (a btree "<" or ">" operator),
179 * determine its opfamily, its declared input datatype, and its
180 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
182 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
183 * (This indicates that the operator is not a valid ordering operator.)
185 * Note: the operator could be registered in multiple families, for example
186 * if someone were to build a "reverse sort" opfamily. This would result in
187 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
188 * or NULLS LAST, as well as inefficient planning due to failure to match up
189 * pathkeys that should be the same. So we want a determinate result here.
190 * Because of the way the syscache search works, we'll use the interpretation
191 * associated with the opfamily with smallest OID, which is probably
192 * determinate enough. Since there is no longer any particularly good reason
193 * to build reverse-sort opfamilies, it doesn't seem worth expending any
194 * additional effort on ensuring consistency.
197 get_ordering_op_properties(Oid opno,
198 Oid *opfamily, Oid *opcintype, int16 *strategy)
204 /* ensure outputs are initialized on failure */
205 *opfamily = InvalidOid;
206 *opcintype = InvalidOid;
210 * Search pg_amop to see if the target operator is registered as the "<"
211 * or ">" operator of any btree opfamily.
213 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
215 for (i = 0; i < catlist->n_members; i++)
217 HeapTuple tuple = &catlist->members[i]->tuple;
218 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
221 if (aform->amopmethod != BTREE_AM_OID)
224 if (aform->amopstrategy == BTLessStrategyNumber ||
225 aform->amopstrategy == BTGreaterStrategyNumber)
227 /* Found it ... should have consistent input types */
228 if (aform->amoplefttype == aform->amoprighttype)
230 /* Found a suitable opfamily, return info */
231 *opfamily = aform->amopfamily;
232 *opcintype = aform->amoplefttype;
233 *strategy = aform->amopstrategy;
240 ReleaseSysCacheList(catlist);
246 * get_compare_function_for_ordering_op
247 * Get the OID of the datatype-specific btree comparison function
248 * associated with an ordering operator (a "<" or ">" operator).
250 * *cmpfunc receives the comparison function OID.
251 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
252 * (indicating the comparison result must be negated before use).
254 * Returns TRUE if successful, FALSE if no btree function can be found.
255 * (This indicates that the operator is not a valid ordering operator.)
258 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
264 /* Find the operator in pg_amop */
265 if (get_ordering_op_properties(opno,
266 &opfamily, &opcintype, &strategy))
268 /* Found a suitable opfamily, get matching support function */
269 *cmpfunc = get_opfamily_proc(opfamily,
274 if (!OidIsValid(*cmpfunc)) /* should not happen */
275 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
276 BTORDER_PROC, opcintype, opcintype, opfamily);
277 *reverse = (strategy == BTGreaterStrategyNumber);
281 /* ensure outputs are set on failure */
282 *cmpfunc = InvalidOid;
289 * get_equality_op_for_ordering_op
290 * Get the OID of the datatype-specific btree equality operator
291 * associated with an ordering operator (a "<" or ">" operator).
293 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
296 * Returns InvalidOid if no matching equality operator can be found.
297 * (This indicates that the operator is not a valid ordering operator.)
300 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
302 Oid result = InvalidOid;
307 /* Find the operator in pg_amop */
308 if (get_ordering_op_properties(opno,
309 &opfamily, &opcintype, &strategy))
311 /* Found a suitable opfamily, get matching equality operator */
312 result = get_opfamily_member(opfamily,
315 BTEqualStrategyNumber);
317 *reverse = (strategy == BTGreaterStrategyNumber);
324 * get_ordering_op_for_equality_op
325 * Get the OID of a datatype-specific btree ordering operator
326 * associated with an equality operator. (If there are multiple
327 * possibilities, assume any one will do.)
329 * This function is used when we have to sort data before unique-ifying,
330 * and don't much care which sorting op is used as long as it's compatible
331 * with the intended equality operator. Since we need a sorting operator,
332 * it should be single-data-type even if the given operator is cross-type.
333 * The caller specifies whether to find an op for the LHS or RHS data type.
335 * Returns InvalidOid if no matching ordering operator can be found.
338 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
340 Oid result = InvalidOid;
345 * Search pg_amop to see if the target operator is registered as the "="
346 * operator of any btree opfamily.
348 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
350 for (i = 0; i < catlist->n_members; i++)
352 HeapTuple tuple = &catlist->members[i]->tuple;
353 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
356 if (aform->amopmethod != BTREE_AM_OID)
359 if (aform->amopstrategy == BTEqualStrategyNumber)
361 /* Found a suitable opfamily, get matching ordering operator */
364 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
365 result = get_opfamily_member(aform->amopfamily,
367 BTLessStrategyNumber);
368 if (OidIsValid(result))
370 /* failure probably shouldn't happen, but keep looking if so */
374 ReleaseSysCacheList(catlist);
380 * get_mergejoin_opfamilies
381 * Given a putatively mergejoinable operator, return a list of the OIDs
382 * of the btree opfamilies in which it represents equality.
384 * It is possible (though at present unusual) for an operator to be equality
385 * in more than one opfamily, hence the result is a list. This also lets us
386 * return NIL if the operator is not found in any opfamilies.
388 * The planner currently uses simple equal() tests to compare the lists
389 * returned by this function, which makes the list order relevant, though
390 * strictly speaking it should not be. Because of the way syscache list
391 * searches are handled, in normal operation the result will be sorted by OID
392 * so everything works fine. If running with system index usage disabled,
393 * the result ordering is unspecified and hence the planner might fail to
394 * recognize optimization opportunities ... but that's hardly a scenario in
395 * which performance is good anyway, so there's no point in expending code
396 * or cycles here to guarantee the ordering in that case.
399 get_mergejoin_opfamilies(Oid opno)
406 * Search pg_amop to see if the target operator is registered as the "="
407 * operator of any btree opfamily.
409 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
411 for (i = 0; i < catlist->n_members; i++)
413 HeapTuple tuple = &catlist->members[i]->tuple;
414 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
416 /* must be btree equality */
417 if (aform->amopmethod == BTREE_AM_OID &&
418 aform->amopstrategy == BTEqualStrategyNumber)
419 result = lappend_oid(result, aform->amopfamily);
422 ReleaseSysCacheList(catlist);
428 * get_compatible_hash_operators
429 * Get the OID(s) of hash equality operator(s) compatible with the given
430 * operator, but operating on its LHS and/or RHS datatype.
432 * An operator for the LHS type is sought and returned into *lhs_opno if
433 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
434 * and returned into *rhs_opno if rhs_opno isn't NULL.
436 * If the given operator is not cross-type, the results should be the same
437 * operator, but in cross-type situations they will be different.
439 * Returns true if able to find the requested operator(s), false if not.
440 * (This indicates that the operator should not have been marked oprcanhash.)
443 get_compatible_hash_operators(Oid opno,
444 Oid *lhs_opno, Oid *rhs_opno)
450 /* Ensure output args are initialized on failure */
452 *lhs_opno = InvalidOid;
454 *rhs_opno = InvalidOid;
457 * Search pg_amop to see if the target operator is registered as the "="
458 * operator of any hash opfamily. If the operator is registered in
459 * multiple opfamilies, assume we can use any one.
461 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
463 for (i = 0; i < catlist->n_members; i++)
465 HeapTuple tuple = &catlist->members[i]->tuple;
466 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
468 if (aform->amopmethod == HASH_AM_OID &&
469 aform->amopstrategy == HTEqualStrategyNumber)
471 /* No extra lookup needed if given operator is single-type */
472 if (aform->amoplefttype == aform->amoprighttype)
483 * Get the matching single-type operator(s). Failure probably
484 * shouldn't happen --- it implies a bogus opfamily --- but
485 * continue looking if so.
489 *lhs_opno = get_opfamily_member(aform->amopfamily,
492 HTEqualStrategyNumber);
493 if (!OidIsValid(*lhs_opno))
495 /* Matching LHS found, done if caller doesn't want RHS */
504 *rhs_opno = get_opfamily_member(aform->amopfamily,
505 aform->amoprighttype,
506 aform->amoprighttype,
507 HTEqualStrategyNumber);
508 if (!OidIsValid(*rhs_opno))
510 /* Forget any LHS operator from this opfamily */
512 *lhs_opno = InvalidOid;
515 /* Matching RHS found, so done */
522 ReleaseSysCacheList(catlist);
528 * get_op_hash_functions
529 * Get the OID(s) of hash support function(s) compatible with the given
530 * operator, operating on its LHS and/or RHS datatype as required.
532 * A function for the LHS type is sought and returned into *lhs_procno if
533 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
534 * and returned into *rhs_procno if rhs_procno isn't NULL.
536 * If the given operator is not cross-type, the results should be the same
537 * function, but in cross-type situations they will be different.
539 * Returns true if able to find the requested function(s), false if not.
540 * (This indicates that the operator should not have been marked oprcanhash.)
543 get_op_hash_functions(Oid opno,
544 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
550 /* Ensure output args are initialized on failure */
552 *lhs_procno = InvalidOid;
554 *rhs_procno = InvalidOid;
557 * Search pg_amop to see if the target operator is registered as the "="
558 * operator of any hash opfamily. If the operator is registered in
559 * multiple opfamilies, assume we can use any one.
561 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
563 for (i = 0; i < catlist->n_members; i++)
565 HeapTuple tuple = &catlist->members[i]->tuple;
566 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
568 if (aform->amopmethod == HASH_AM_OID &&
569 aform->amopstrategy == HTEqualStrategyNumber)
572 * Get the matching support function(s). Failure probably
573 * shouldn't happen --- it implies a bogus opfamily --- but
574 * continue looking if so.
578 *lhs_procno = get_opfamily_proc(aform->amopfamily,
582 if (!OidIsValid(*lhs_procno))
584 /* Matching LHS found, done if caller doesn't want RHS */
590 /* Only one lookup needed if given operator is single-type */
591 if (aform->amoplefttype == aform->amoprighttype)
593 *rhs_procno = *lhs_procno;
600 *rhs_procno = get_opfamily_proc(aform->amopfamily,
601 aform->amoprighttype,
602 aform->amoprighttype,
604 if (!OidIsValid(*rhs_procno))
606 /* Forget any LHS function from this opfamily */
608 *lhs_procno = InvalidOid;
611 /* Matching RHS found, so done */
618 ReleaseSysCacheList(catlist);
624 * get_op_btree_interpretation
625 * Given an operator's OID, find out which btree opfamilies it belongs to,
626 * and what strategy number it has within each one. The results are
627 * returned as an OID list and a parallel integer list.
629 * In addition to the normal btree operators, we consider a <> operator to be
630 * a "member" of an opfamily if its negator is an equality operator of the
631 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
634 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
644 * Find all the pg_amop entries containing the operator.
646 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
649 * If we can't find any opfamily containing the op, perhaps it is a <>
650 * operator. See if it has a negator that is in an opfamily.
653 if (catlist->n_members == 0)
655 Oid op_negator = get_negator(opno);
657 if (OidIsValid(op_negator))
660 ReleaseSysCacheList(catlist);
661 catlist = SearchSysCacheList1(AMOPOPID,
662 ObjectIdGetDatum(op_negator));
666 /* Now search the opfamilies */
667 for (i = 0; i < catlist->n_members; i++)
669 HeapTuple op_tuple = &catlist->members[i]->tuple;
670 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
672 StrategyNumber op_strategy;
675 if (op_form->amopmethod != BTREE_AM_OID)
678 /* Get the operator's btree strategy number */
679 opfamily_id = op_form->amopfamily;
680 op_strategy = (StrategyNumber) op_form->amopstrategy;
681 Assert(op_strategy >= 1 && op_strategy <= 5);
685 /* Only consider negators that are = */
686 if (op_strategy != BTEqualStrategyNumber)
688 op_strategy = ROWCOMPARE_NE;
691 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
692 *opstrats = lappend_int(*opstrats, op_strategy);
695 ReleaseSysCacheList(catlist);
699 * equality_ops_are_compatible
700 * Return TRUE if the two given equality operators have compatible
703 * This is trivially true if they are the same operator. Otherwise,
704 * we look to see if they can be found in the same btree or hash opfamily.
705 * Either finding allows us to assume that they have compatible notions
706 * of equality. (The reason we need to do these pushups is that one might
707 * be a cross-type operator; for instance int24eq vs int4eq.)
710 equality_ops_are_compatible(Oid opno1, Oid opno2)
716 /* Easy if they're the same operator */
721 * We search through all the pg_amop entries for opno1.
723 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
726 for (i = 0; i < catlist->n_members; i++)
728 HeapTuple op_tuple = &catlist->members[i]->tuple;
729 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
731 /* must be btree or hash */
732 if (op_form->amopmethod == BTREE_AM_OID ||
733 op_form->amopmethod == HASH_AM_OID)
735 if (op_in_opfamily(opno2, op_form->amopfamily))
743 ReleaseSysCacheList(catlist);
749 /* ---------- AMPROC CACHES ---------- */
753 * Get the OID of the specified support function
754 * for the specified opfamily and datatypes.
756 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
759 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
762 Form_pg_amproc amproc_tup;
765 tp = SearchSysCache4(AMPROCNUM,
766 ObjectIdGetDatum(opfamily),
767 ObjectIdGetDatum(lefttype),
768 ObjectIdGetDatum(righttype),
769 Int16GetDatum(procnum));
770 if (!HeapTupleIsValid(tp))
772 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
773 result = amproc_tup->amproc;
779 /* ---------- ATTRIBUTE CACHES ---------- */
783 * Given the relation id and the attribute number,
784 * return the "attname" field from the attribute relation.
786 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
789 get_attname(Oid relid, AttrNumber attnum)
793 tp = SearchSysCache2(ATTNUM,
794 ObjectIdGetDatum(relid),
795 Int16GetDatum(attnum));
796 if (HeapTupleIsValid(tp))
798 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
801 result = pstrdup(NameStr(att_tup->attname));
810 * get_relid_attribute_name
812 * Same as above routine get_attname(), except that error
813 * is handled by elog() instead of returning NULL.
816 get_relid_attribute_name(Oid relid, AttrNumber attnum)
820 attname = get_attname(relid, attnum);
822 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
830 * Given the relation id and the attribute name,
831 * return the "attnum" field from the attribute relation.
833 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
836 get_attnum(Oid relid, const char *attname)
840 tp = SearchSysCacheAttName(relid, attname);
841 if (HeapTupleIsValid(tp))
843 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
846 result = att_tup->attnum;
851 return InvalidAttrNumber;
857 * Given the relation OID and the attribute number with the relation,
858 * return the attribute type OID.
861 get_atttype(Oid relid, AttrNumber attnum)
865 tp = SearchSysCache2(ATTNUM,
866 ObjectIdGetDatum(relid),
867 Int16GetDatum(attnum));
868 if (HeapTupleIsValid(tp))
870 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
873 result = att_tup->atttypid;
884 * Given the relation id and the attribute number,
885 * return the "atttypmod" field from the attribute relation.
888 get_atttypmod(Oid relid, AttrNumber attnum)
892 tp = SearchSysCache2(ATTNUM,
893 ObjectIdGetDatum(relid),
894 Int16GetDatum(attnum));
895 if (HeapTupleIsValid(tp))
897 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
900 result = att_tup->atttypmod;
909 * get_atttypetypmodcoll
911 * A three-fer: given the relation id and the attribute number,
912 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
914 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
915 * raises an error if it can't obtain the information.
918 get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
919 Oid *typid, int32 *typmod, Oid *collid)
922 Form_pg_attribute att_tup;
924 tp = SearchSysCache2(ATTNUM,
925 ObjectIdGetDatum(relid),
926 Int16GetDatum(attnum));
927 if (!HeapTupleIsValid(tp))
928 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
930 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
932 *typid = att_tup->atttypid;
933 *typmod = att_tup->atttypmod;
934 *collid = att_tup->attcollation;
938 /* ---------- COLLATION CACHE ---------- */
942 * Returns the name of a given pg_collation entry.
944 * Returns a palloc'd copy of the string, or NULL if no such constraint.
946 * NOTE: since collation name is not unique, be wary of code that uses this
947 * for anything except preparing error messages.
950 get_collation_name(Oid colloid)
954 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
955 if (HeapTupleIsValid(tp))
957 Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
960 result = pstrdup(NameStr(colltup->collname));
968 /* ---------- CONSTRAINT CACHE ---------- */
971 * get_constraint_name
972 * Returns the name of a given pg_constraint entry.
974 * Returns a palloc'd copy of the string, or NULL if no such constraint.
976 * NOTE: since constraint name is not unique, be wary of code that uses this
977 * for anything except preparing error messages.
980 get_constraint_name(Oid conoid)
984 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
985 if (HeapTupleIsValid(tp))
987 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
990 result = pstrdup(NameStr(contup->conname));
998 /* ---------- OPCLASS CACHE ---------- */
1001 * get_opclass_family
1003 * Returns the OID of the operator family the opclass belongs to.
1006 get_opclass_family(Oid opclass)
1009 Form_pg_opclass cla_tup;
1012 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1013 if (!HeapTupleIsValid(tp))
1014 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1015 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1017 result = cla_tup->opcfamily;
1018 ReleaseSysCache(tp);
1023 * get_opclass_input_type
1025 * Returns the OID of the datatype the opclass indexes.
1028 get_opclass_input_type(Oid opclass)
1031 Form_pg_opclass cla_tup;
1034 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1035 if (!HeapTupleIsValid(tp))
1036 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1037 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1039 result = cla_tup->opcintype;
1040 ReleaseSysCache(tp);
1044 /* ---------- OPERATOR CACHE ---------- */
1049 * Returns the regproc id of the routine used to implement an
1050 * operator given the operator oid.
1053 get_opcode(Oid opno)
1057 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1058 if (HeapTupleIsValid(tp))
1060 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1061 RegProcedure result;
1063 result = optup->oprcode;
1064 ReleaseSysCache(tp);
1068 return (RegProcedure) InvalidOid;
1073 * returns the name of the operator with the given opno
1075 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1078 get_opname(Oid opno)
1082 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1083 if (HeapTupleIsValid(tp))
1085 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1088 result = pstrdup(NameStr(optup->oprname));
1089 ReleaseSysCache(tp);
1099 * Returns the left and right input datatypes for an operator
1100 * (InvalidOid if not relevant).
1103 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1106 Form_pg_operator optup;
1108 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1109 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1110 elog(ERROR, "cache lookup failed for operator %u", opno);
1111 optup = (Form_pg_operator) GETSTRUCT(tp);
1112 *lefttype = optup->oprleft;
1113 *righttype = optup->oprright;
1114 ReleaseSysCache(tp);
1120 * Returns true if the operator is potentially mergejoinable. (The planner
1121 * will fail to find any mergejoin plans unless there are suitable btree
1122 * opfamily entries for this operator and associated sortops. The pg_operator
1123 * flag is just a hint to tell the planner whether to bother looking.)
1125 * In some cases (currently only array_eq and record_eq), mergejoinability
1126 * depends on the specific input data type the operator is invoked for, so
1127 * that must be passed as well. We currently assume that only one input's type
1128 * is needed to check this --- by convention, pass the left input's data type.
1131 op_mergejoinable(Oid opno, Oid inputtype)
1133 bool result = false;
1135 TypeCacheEntry *typentry;
1138 * For array_eq or record_eq, we can sort if the element or field types
1139 * are all sortable. We could implement all the checks for that here, but
1140 * the typcache already does that and caches the results too, so let's
1141 * rely on the typcache.
1143 if (opno == ARRAY_EQ_OP)
1145 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1146 if (typentry->cmp_proc == F_BTARRAYCMP)
1149 else if (opno == RECORD_EQ_OP)
1151 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1152 if (typentry->cmp_proc == F_BTRECORDCMP)
1157 /* For all other operators, rely on pg_operator.oprcanmerge */
1158 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1159 if (HeapTupleIsValid(tp))
1161 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1163 result = optup->oprcanmerge;
1164 ReleaseSysCache(tp);
1173 * Returns true if the operator is hashjoinable. (There must be a suitable
1174 * hash opfamily entry for this operator if it is so marked.)
1176 * In some cases (currently only array_eq), hashjoinability depends on the
1177 * specific input data type the operator is invoked for, so that must be
1178 * passed as well. We currently assume that only one input's type is needed
1179 * to check this --- by convention, pass the left input's data type.
1182 op_hashjoinable(Oid opno, Oid inputtype)
1184 bool result = false;
1186 TypeCacheEntry *typentry;
1188 /* As in op_mergejoinable, let the typcache handle the hard cases */
1189 /* Eventually we'll need a similar case for record_eq ... */
1190 if (opno == ARRAY_EQ_OP)
1192 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1193 if (typentry->hash_proc == F_HASH_ARRAY)
1198 /* For all other operators, rely on pg_operator.oprcanhash */
1199 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1200 if (HeapTupleIsValid(tp))
1202 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1204 result = optup->oprcanhash;
1205 ReleaseSysCache(tp);
1214 * Get the proisstrict flag for the operator's underlying function.
1219 RegProcedure funcid = get_opcode(opno);
1221 if (funcid == (RegProcedure) InvalidOid)
1222 elog(ERROR, "operator %u does not exist", opno);
1224 return func_strict((Oid) funcid);
1230 * Get the provolatile flag for the operator's underlying function.
1233 op_volatile(Oid opno)
1235 RegProcedure funcid = get_opcode(opno);
1237 if (funcid == (RegProcedure) InvalidOid)
1238 elog(ERROR, "operator %u does not exist", opno);
1240 return func_volatile((Oid) funcid);
1246 * Returns the corresponding commutator of an operator.
1249 get_commutator(Oid opno)
1253 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1254 if (HeapTupleIsValid(tp))
1256 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1259 result = optup->oprcom;
1260 ReleaseSysCache(tp);
1270 * Returns the corresponding negator of an operator.
1273 get_negator(Oid opno)
1277 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1278 if (HeapTupleIsValid(tp))
1280 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1283 result = optup->oprnegate;
1284 ReleaseSysCache(tp);
1294 * Returns procedure id for computing selectivity of an operator.
1297 get_oprrest(Oid opno)
1301 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1302 if (HeapTupleIsValid(tp))
1304 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1305 RegProcedure result;
1307 result = optup->oprrest;
1308 ReleaseSysCache(tp);
1312 return (RegProcedure) InvalidOid;
1318 * Returns procedure id for computing selectivity of a join.
1321 get_oprjoin(Oid opno)
1325 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1326 if (HeapTupleIsValid(tp))
1328 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1329 RegProcedure result;
1331 result = optup->oprjoin;
1332 ReleaseSysCache(tp);
1336 return (RegProcedure) InvalidOid;
1339 /* ---------- FUNCTION CACHE ---------- */
1343 * returns the name of the function with the given funcid
1345 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1348 get_func_name(Oid funcid)
1352 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1353 if (HeapTupleIsValid(tp))
1355 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1358 result = pstrdup(NameStr(functup->proname));
1359 ReleaseSysCache(tp);
1367 * get_func_namespace
1369 * Returns the pg_namespace OID associated with a given function.
1372 get_func_namespace(Oid funcid)
1376 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1377 if (HeapTupleIsValid(tp))
1379 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1382 result = functup->pronamespace;
1383 ReleaseSysCache(tp);
1392 * Given procedure id, return the function's result type.
1395 get_func_rettype(Oid funcid)
1400 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1401 if (!HeapTupleIsValid(tp))
1402 elog(ERROR, "cache lookup failed for function %u", funcid);
1404 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1405 ReleaseSysCache(tp);
1411 * Given procedure id, return the number of arguments.
1414 get_func_nargs(Oid funcid)
1419 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1420 if (!HeapTupleIsValid(tp))
1421 elog(ERROR, "cache lookup failed for function %u", funcid);
1423 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1424 ReleaseSysCache(tp);
1429 * get_func_signature
1430 * Given procedure id, return the function's argument and result types.
1431 * (The return value is the result type.)
1433 * The arguments are returned as a palloc'd array.
1436 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1439 Form_pg_proc procstruct;
1442 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1443 if (!HeapTupleIsValid(tp))
1444 elog(ERROR, "cache lookup failed for function %u", funcid);
1446 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1448 result = procstruct->prorettype;
1449 *nargs = (int) procstruct->pronargs;
1450 Assert(*nargs == procstruct->proargtypes.dim1);
1451 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1452 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1454 ReleaseSysCache(tp);
1460 * Given procedure id, return the function's proretset flag.
1463 get_func_retset(Oid funcid)
1468 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1469 if (!HeapTupleIsValid(tp))
1470 elog(ERROR, "cache lookup failed for function %u", funcid);
1472 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1473 ReleaseSysCache(tp);
1479 * Given procedure id, return the function's proisstrict flag.
1482 func_strict(Oid funcid)
1487 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1488 if (!HeapTupleIsValid(tp))
1489 elog(ERROR, "cache lookup failed for function %u", funcid);
1491 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1492 ReleaseSysCache(tp);
1498 * Given procedure id, return the function's provolatile flag.
1501 func_volatile(Oid funcid)
1506 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1507 if (!HeapTupleIsValid(tp))
1508 elog(ERROR, "cache lookup failed for function %u", funcid);
1510 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1511 ReleaseSysCache(tp);
1517 * Given procedure id, return the function's procost field.
1520 get_func_cost(Oid funcid)
1525 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1526 if (!HeapTupleIsValid(tp))
1527 elog(ERROR, "cache lookup failed for function %u", funcid);
1529 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1530 ReleaseSysCache(tp);
1536 * Given procedure id, return the function's prorows field.
1539 get_func_rows(Oid funcid)
1544 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1545 if (!HeapTupleIsValid(tp))
1546 elog(ERROR, "cache lookup failed for function %u", funcid);
1548 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1549 ReleaseSysCache(tp);
1553 /* ---------- RELATION CACHE ---------- */
1557 * Given name and namespace of a relation, look up the OID.
1559 * Returns InvalidOid if there is no such relation.
1562 get_relname_relid(const char *relname, Oid relnamespace)
1564 return GetSysCacheOid2(RELNAMENSP,
1565 PointerGetDatum(relname),
1566 ObjectIdGetDatum(relnamespace));
1573 * Returns the number of attributes for a given relation.
1576 get_relnatts(Oid relid)
1580 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1581 if (HeapTupleIsValid(tp))
1583 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1586 result = reltup->relnatts;
1587 ReleaseSysCache(tp);
1591 return InvalidAttrNumber;
1597 * Returns the name of a given relation.
1599 * Returns a palloc'd copy of the string, or NULL if no such relation.
1601 * NOTE: since relation name is not unique, be wary of code that uses this
1602 * for anything except preparing error messages.
1605 get_rel_name(Oid relid)
1609 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1610 if (HeapTupleIsValid(tp))
1612 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1615 result = pstrdup(NameStr(reltup->relname));
1616 ReleaseSysCache(tp);
1626 * Returns the pg_namespace OID associated with a given relation.
1629 get_rel_namespace(Oid relid)
1633 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1634 if (HeapTupleIsValid(tp))
1636 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1639 result = reltup->relnamespace;
1640 ReleaseSysCache(tp);
1650 * Returns the pg_type OID associated with a given relation.
1652 * Note: not all pg_class entries have associated pg_type OIDs; so be
1653 * careful to check for InvalidOid result.
1656 get_rel_type_id(Oid relid)
1660 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1661 if (HeapTupleIsValid(tp))
1663 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1666 result = reltup->reltype;
1667 ReleaseSysCache(tp);
1677 * Returns the relkind associated with a given relation.
1680 get_rel_relkind(Oid relid)
1684 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1685 if (HeapTupleIsValid(tp))
1687 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1690 result = reltup->relkind;
1691 ReleaseSysCache(tp);
1699 * get_rel_tablespace
1701 * Returns the pg_tablespace OID associated with a given relation.
1703 * Note: InvalidOid might mean either that we couldn't find the relation,
1704 * or that it is in the database's default tablespace.
1707 get_rel_tablespace(Oid relid)
1711 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1712 if (HeapTupleIsValid(tp))
1714 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1717 result = reltup->reltablespace;
1718 ReleaseSysCache(tp);
1726 /* ---------- TYPE CACHE ---------- */
1731 * Given the type OID, determine whether the type is defined
1732 * (if not, it's only a shell).
1735 get_typisdefined(Oid typid)
1739 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1740 if (HeapTupleIsValid(tp))
1742 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1745 result = typtup->typisdefined;
1746 ReleaseSysCache(tp);
1756 * Given the type OID, return the length of the type.
1759 get_typlen(Oid typid)
1763 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1764 if (HeapTupleIsValid(tp))
1766 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1769 result = typtup->typlen;
1770 ReleaseSysCache(tp);
1780 * Given the type OID, determine whether the type is returned by value or
1781 * not. Returns true if by value, false if by reference.
1784 get_typbyval(Oid typid)
1788 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1789 if (HeapTupleIsValid(tp))
1791 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1794 result = typtup->typbyval;
1795 ReleaseSysCache(tp);
1805 * A two-fer: given the type OID, return both typlen and typbyval.
1807 * Since both pieces of info are needed to know how to copy a Datum,
1808 * many places need both. Might as well get them with one cache lookup
1809 * instead of two. Also, this routine raises an error instead of
1810 * returning a bogus value when given a bad type OID.
1813 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1816 Form_pg_type typtup;
1818 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1819 if (!HeapTupleIsValid(tp))
1820 elog(ERROR, "cache lookup failed for type %u", typid);
1821 typtup = (Form_pg_type) GETSTRUCT(tp);
1822 *typlen = typtup->typlen;
1823 *typbyval = typtup->typbyval;
1824 ReleaseSysCache(tp);
1828 * get_typlenbyvalalign
1830 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1833 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1837 Form_pg_type typtup;
1839 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1840 if (!HeapTupleIsValid(tp))
1841 elog(ERROR, "cache lookup failed for type %u", typid);
1842 typtup = (Form_pg_type) GETSTRUCT(tp);
1843 *typlen = typtup->typlen;
1844 *typbyval = typtup->typbyval;
1845 *typalign = typtup->typalign;
1846 ReleaseSysCache(tp);
1851 * Given a pg_type row, select the type OID to pass to I/O functions
1853 * Formerly, all I/O functions were passed pg_type.typelem as their second
1854 * parameter, but we now have a more complex rule about what to pass.
1855 * This knowledge is intended to be centralized here --- direct references
1856 * to typelem elsewhere in the code are wrong, if they are associated with
1857 * I/O calls and not with actual subscripting operations! (But see
1858 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1860 * As of PostgreSQL 8.1, output functions receive only the value itself
1861 * and not any auxiliary parameters, so the name of this routine is now
1862 * a bit of a misnomer ... it should be getTypeInputParam.
1865 getTypeIOParam(HeapTuple typeTuple)
1867 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1870 * Array types get their typelem as parameter; everybody else gets their
1871 * own type OID as parameter. (As of 8.2, domains must get their own OID
1872 * even if their base type is an array.)
1874 if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem))
1875 return typeStruct->typelem;
1877 return HeapTupleGetOid(typeTuple);
1883 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1884 * typdelim, typioparam, and IO function OID. The IO function
1885 * returned is controlled by IOFuncSelector
1888 get_type_io_data(Oid typid,
1889 IOFuncSelector which_func,
1897 HeapTuple typeTuple;
1898 Form_pg_type typeStruct;
1901 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1902 * use array_in and array_out during bootstrap.
1904 if (IsBootstrapProcessingMode())
1909 boot_get_type_io_data(typid,
1926 elog(ERROR, "binary I/O not supported during bootstrap");
1932 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1933 if (!HeapTupleIsValid(typeTuple))
1934 elog(ERROR, "cache lookup failed for type %u", typid);
1935 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1937 *typlen = typeStruct->typlen;
1938 *typbyval = typeStruct->typbyval;
1939 *typalign = typeStruct->typalign;
1940 *typdelim = typeStruct->typdelim;
1941 *typioparam = getTypeIOParam(typeTuple);
1945 *func = typeStruct->typinput;
1948 *func = typeStruct->typoutput;
1950 case IOFunc_receive:
1951 *func = typeStruct->typreceive;
1954 *func = typeStruct->typsend;
1957 ReleaseSysCache(typeTuple);
1962 get_typalign(Oid typid)
1966 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1967 if (HeapTupleIsValid(tp))
1969 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1972 result = typtup->typalign;
1973 ReleaseSysCache(tp);
1982 get_typstorage(Oid typid)
1986 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1987 if (HeapTupleIsValid(tp))
1989 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1992 result = typtup->typstorage;
1993 ReleaseSysCache(tp);
2002 * Given a type OID, return the type's default value, if any.
2004 * The result is a palloc'd expression node tree, or NULL if there
2005 * is no defined default for the datatype.
2007 * NB: caller should be prepared to coerce result to correct datatype;
2008 * the returned expression tree might produce something of the wrong type.
2011 get_typdefault(Oid typid)
2013 HeapTuple typeTuple;
2019 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2020 if (!HeapTupleIsValid(typeTuple))
2021 elog(ERROR, "cache lookup failed for type %u", typid);
2022 type = (Form_pg_type) GETSTRUCT(typeTuple);
2025 * typdefault and typdefaultbin are potentially null, so don't try to
2026 * access 'em as struct fields. Must do it the hard way with
2029 datum = SysCacheGetAttr(TYPEOID,
2031 Anum_pg_type_typdefaultbin,
2036 /* We have an expression default */
2037 expr = stringToNode(TextDatumGetCString(datum));
2041 /* Perhaps we have a plain literal default */
2042 datum = SysCacheGetAttr(TYPEOID,
2044 Anum_pg_type_typdefault,
2049 char *strDefaultVal;
2051 /* Convert text datum to C string */
2052 strDefaultVal = TextDatumGetCString(datum);
2053 /* Convert C string to a value of the given type */
2054 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2055 getTypeIOParam(typeTuple), -1);
2056 /* Build a Const node containing the value */
2057 expr = (Node *) makeConst(typid,
2064 pfree(strDefaultVal);
2073 ReleaseSysCache(typeTuple);
2080 * If the given type is a domain, return its base type;
2081 * otherwise return the type's own OID.
2084 getBaseType(Oid typid)
2088 return getBaseTypeAndTypmod(typid, &typmod);
2092 * getBaseTypeAndTypmod
2093 * If the given type is a domain, return its base type and typmod;
2094 * otherwise return the type's own OID, and leave *typmod unchanged.
2096 * Note that the "applied typmod" should be -1 for every domain level
2097 * above the bottommost; therefore, if the passed-in typid is indeed
2098 * a domain, *typmod should be -1.
2101 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2104 * We loop to find the bottom base type in a stack of domains.
2109 Form_pg_type typTup;
2111 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2112 if (!HeapTupleIsValid(tup))
2113 elog(ERROR, "cache lookup failed for type %u", typid);
2114 typTup = (Form_pg_type) GETSTRUCT(tup);
2115 if (typTup->typtype != TYPTYPE_DOMAIN)
2117 /* Not a domain, so done */
2118 ReleaseSysCache(tup);
2122 Assert(*typmod == -1);
2123 typid = typTup->typbasetype;
2124 *typmod = typTup->typtypmod;
2126 ReleaseSysCache(tup);
2135 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2136 * estimate the average width of values of the type. This is used by
2137 * the planner, which doesn't require absolutely correct results;
2138 * it's OK (and expected) to guess if we don't know for sure.
2141 get_typavgwidth(Oid typid, int32 typmod)
2143 int typlen = get_typlen(typid);
2147 * Easy if it's a fixed-width type
2153 * type_maximum_size knows the encoding of typmod for some datatypes;
2154 * don't duplicate that knowledge here.
2156 maxwidth = type_maximum_size(typid, typmod);
2160 * For BPCHAR, the max width is also the only width. Otherwise we
2161 * need to guess about the typical data width given the max. A sliding
2162 * scale for percentage of max width seems reasonable.
2164 if (typid == BPCHAROID)
2167 return maxwidth; /* assume full width */
2168 if (maxwidth < 1000)
2169 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2172 * Beyond 1000, assume we're looking at something like
2173 * "varchar(10000)" where the limit isn't actually reached often, and
2174 * use a fixed estimate.
2176 return 32 + (1000 - 32) / 2;
2180 * Ooops, we have no idea ... wild guess time.
2188 * Given the type OID, find if it is a basic type, a complex type, etc.
2189 * It returns the null char if the cache lookup fails...
2192 get_typtype(Oid typid)
2196 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2197 if (HeapTupleIsValid(tp))
2199 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2202 result = typtup->typtype;
2203 ReleaseSysCache(tp);
2213 * Convenience function to determine whether a type OID represents
2214 * a "rowtype" type --- either RECORD or a named composite type.
2217 type_is_rowtype(Oid typid)
2219 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2224 * Returns true if the given type is an enum type.
2227 type_is_enum(Oid typid)
2229 return (get_typtype(typid) == TYPTYPE_ENUM);
2233 * get_type_category_preferred
2235 * Given the type OID, fetch its category and preferred-type status.
2236 * Throws error on failure.
2239 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2242 Form_pg_type typtup;
2244 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2245 if (!HeapTupleIsValid(tp))
2246 elog(ERROR, "cache lookup failed for type %u", typid);
2247 typtup = (Form_pg_type) GETSTRUCT(tp);
2248 *typcategory = typtup->typcategory;
2249 *typispreferred = typtup->typispreferred;
2250 ReleaseSysCache(tp);
2256 * Given the type OID, get the typrelid (InvalidOid if not a complex
2260 get_typ_typrelid(Oid typid)
2264 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2265 if (HeapTupleIsValid(tp))
2267 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2270 result = typtup->typrelid;
2271 ReleaseSysCache(tp);
2281 * Given the type OID, get the typelem (InvalidOid if not an array type).
2283 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2284 * returned if the input is a fixed-length array type.
2287 get_element_type(Oid typid)
2291 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2292 if (HeapTupleIsValid(tp))
2294 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2297 if (typtup->typlen == -1)
2298 result = typtup->typelem;
2300 result = InvalidOid;
2301 ReleaseSysCache(tp);
2311 * Given the type OID, get the corresponding "true" array type.
2312 * Returns InvalidOid if no array type can be found.
2315 get_array_type(Oid typid)
2318 Oid result = InvalidOid;
2320 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2321 if (HeapTupleIsValid(tp))
2323 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2324 ReleaseSysCache(tp);
2330 * get_base_element_type
2331 * Given the type OID, get the typelem, looking "through" any domain
2332 * to its underlying array type.
2334 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2335 * an extra cache lookup. Note that it fails to provide any information
2336 * about the typmod of the array.
2339 get_base_element_type(Oid typid)
2342 * We loop to find the bottom base type in a stack of domains.
2347 Form_pg_type typTup;
2349 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2350 if (!HeapTupleIsValid(tup))
2352 typTup = (Form_pg_type) GETSTRUCT(tup);
2353 if (typTup->typtype != TYPTYPE_DOMAIN)
2355 /* Not a domain, so stop descending */
2358 /* This test must match get_element_type */
2359 if (typTup->typlen == -1)
2360 result = typTup->typelem;
2362 result = InvalidOid;
2363 ReleaseSysCache(tup);
2367 typid = typTup->typbasetype;
2368 ReleaseSysCache(tup);
2371 /* Like get_element_type, silently return InvalidOid for bogus input */
2378 * Get info needed for converting values of a type to internal form
2381 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2383 HeapTuple typeTuple;
2386 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2387 if (!HeapTupleIsValid(typeTuple))
2388 elog(ERROR, "cache lookup failed for type %u", type);
2389 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2391 if (!pt->typisdefined)
2393 (errcode(ERRCODE_UNDEFINED_OBJECT),
2394 errmsg("type %s is only a shell",
2395 format_type_be(type))));
2396 if (!OidIsValid(pt->typinput))
2398 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2399 errmsg("no input function available for type %s",
2400 format_type_be(type))));
2402 *typInput = pt->typinput;
2403 *typIOParam = getTypeIOParam(typeTuple);
2405 ReleaseSysCache(typeTuple);
2411 * Get info needed for printing values of a type
2414 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2416 HeapTuple typeTuple;
2419 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2420 if (!HeapTupleIsValid(typeTuple))
2421 elog(ERROR, "cache lookup failed for type %u", type);
2422 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2424 if (!pt->typisdefined)
2426 (errcode(ERRCODE_UNDEFINED_OBJECT),
2427 errmsg("type %s is only a shell",
2428 format_type_be(type))));
2429 if (!OidIsValid(pt->typoutput))
2431 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2432 errmsg("no output function available for type %s",
2433 format_type_be(type))));
2435 *typOutput = pt->typoutput;
2436 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2438 ReleaseSysCache(typeTuple);
2442 * getTypeBinaryInputInfo
2444 * Get info needed for binary input of values of a type
2447 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2449 HeapTuple typeTuple;
2452 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2453 if (!HeapTupleIsValid(typeTuple))
2454 elog(ERROR, "cache lookup failed for type %u", type);
2455 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2457 if (!pt->typisdefined)
2459 (errcode(ERRCODE_UNDEFINED_OBJECT),
2460 errmsg("type %s is only a shell",
2461 format_type_be(type))));
2462 if (!OidIsValid(pt->typreceive))
2464 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2465 errmsg("no binary input function available for type %s",
2466 format_type_be(type))));
2468 *typReceive = pt->typreceive;
2469 *typIOParam = getTypeIOParam(typeTuple);
2471 ReleaseSysCache(typeTuple);
2475 * getTypeBinaryOutputInfo
2477 * Get info needed for binary output of values of a type
2480 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2482 HeapTuple typeTuple;
2485 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2486 if (!HeapTupleIsValid(typeTuple))
2487 elog(ERROR, "cache lookup failed for type %u", type);
2488 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2490 if (!pt->typisdefined)
2492 (errcode(ERRCODE_UNDEFINED_OBJECT),
2493 errmsg("type %s is only a shell",
2494 format_type_be(type))));
2495 if (!OidIsValid(pt->typsend))
2497 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2498 errmsg("no binary output function available for type %s",
2499 format_type_be(type))));
2501 *typSend = pt->typsend;
2502 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2504 ReleaseSysCache(typeTuple);
2510 * Given the type OID, return the type's typmodin procedure, if any.
2513 get_typmodin(Oid typid)
2517 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2518 if (HeapTupleIsValid(tp))
2520 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2523 result = typtup->typmodin;
2524 ReleaseSysCache(tp);
2535 * Given the type OID, return the type's typmodout procedure, if any.
2538 get_typmodout(Oid typid)
2542 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2543 if (HeapTupleIsValid(tp))
2545 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2548 result = typtup->typmodout;
2549 ReleaseSysCache(tp);
2555 #endif /* NOT_USED */
2560 * Given the type OID, return the type's typcollation attribute.
2563 get_typcollation(Oid typid)
2567 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2568 if (HeapTupleIsValid(tp))
2570 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2573 result = typtup->typcollation;
2574 ReleaseSysCache(tp);
2583 * type_is_collatable
2585 * Return whether the type cares about collations
2588 type_is_collatable(Oid typid)
2590 return OidIsValid(get_typcollation(typid));
2594 /* ---------- STATISTICS CACHE ---------- */
2599 * Given the table and attribute number of a column, get the average
2600 * width of entries in the column. Return zero if no data available.
2602 * Currently this is only consulted for individual tables, not for inheritance
2603 * trees, so we don't need an "inh" parameter.
2605 * Calling a hook at this point looks somewhat strange, but is required
2606 * because the optimizer calls this function without any other way for
2607 * plug-ins to control the result.
2610 get_attavgwidth(Oid relid, AttrNumber attnum)
2615 if (get_attavgwidth_hook)
2617 stawidth = (*get_attavgwidth_hook) (relid, attnum);
2621 tp = SearchSysCache3(STATRELATTINH,
2622 ObjectIdGetDatum(relid),
2623 Int16GetDatum(attnum),
2624 BoolGetDatum(false));
2625 if (HeapTupleIsValid(tp))
2627 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2628 ReleaseSysCache(tp);
2638 * Extract the contents of a "slot" of a pg_statistic tuple.
2639 * Returns TRUE if requested slot type was found, else FALSE.
2641 * Unlike other routines in this file, this takes a pointer to an
2642 * already-looked-up tuple in the pg_statistic cache. We do this since
2643 * most callers will want to extract more than one value from the cache
2644 * entry, and we don't want to repeat the cache lookup unnecessarily.
2645 * Also, this API allows this routine to be used with statistics tuples
2646 * that have been provided by a stats hook and didn't really come from
2649 * statstuple: pg_statistics tuple to be examined.
2650 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2651 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2652 * reqkind: STAKIND code for desired statistics slot kind.
2653 * reqop: STAOP value wanted, or InvalidOid if don't care.
2654 * actualop: if not NULL, *actualop receives the actual STAOP value.
2655 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2656 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2658 * If assigned, values and numbers are set to point to palloc'd arrays.
2659 * If the attribute type is pass-by-reference, the values referenced by
2660 * the values array are themselves palloc'd. The palloc'd stuff can be
2661 * freed by calling free_attstatsslot.
2663 * Note: at present, atttype/atttypmod aren't actually used here at all.
2664 * But the caller must have the correct (or at least binary-compatible)
2665 * type ID to pass to free_attstatsslot later.
2668 get_attstatsslot(HeapTuple statstuple,
2669 Oid atttype, int32 atttypmod,
2670 int reqkind, Oid reqop,
2672 Datum **values, int *nvalues,
2673 float4 **numbers, int *nnumbers)
2675 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2680 ArrayType *statarray;
2683 HeapTuple typeTuple;
2684 Form_pg_type typeForm;
2686 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2688 if ((&stats->stakind1)[i] == reqkind &&
2689 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2692 if (i >= STATISTIC_NUM_SLOTS)
2693 return false; /* not there */
2696 *actualop = (&stats->staop1)[i];
2700 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2701 Anum_pg_statistic_stavalues1 + i,
2704 elog(ERROR, "stavalues is null");
2705 statarray = DatumGetArrayTypeP(val);
2708 * Need to get info about the array element type. We look at the
2709 * actual element type embedded in the array, which might be only
2710 * binary-compatible with the passed-in atttype. The info we extract
2711 * here should be the same either way, but deconstruct_array is picky
2712 * about having an exact type OID match.
2714 arrayelemtype = ARR_ELEMTYPE(statarray);
2715 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
2716 if (!HeapTupleIsValid(typeTuple))
2717 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
2718 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2720 /* Deconstruct array into Datum elements; NULLs not expected */
2721 deconstruct_array(statarray,
2726 values, NULL, nvalues);
2729 * If the element type is pass-by-reference, we now have a bunch of
2730 * Datums that are pointers into the syscache value. Copy them to
2731 * avoid problems if syscache decides to drop the entry.
2733 if (!typeForm->typbyval)
2735 for (j = 0; j < *nvalues; j++)
2737 (*values)[j] = datumCopy((*values)[j],
2743 ReleaseSysCache(typeTuple);
2746 * Free statarray if it's a detoasted copy.
2748 if ((Pointer) statarray != DatumGetPointer(val))
2754 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2755 Anum_pg_statistic_stanumbers1 + i,
2758 elog(ERROR, "stanumbers is null");
2759 statarray = DatumGetArrayTypeP(val);
2762 * We expect the array to be a 1-D float4 array; verify that. We don't
2763 * need to use deconstruct_array() since the array data is just going
2764 * to look like a C array of float4 values.
2766 narrayelem = ARR_DIMS(statarray)[0];
2767 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2768 ARR_HASNULL(statarray) ||
2769 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2770 elog(ERROR, "stanumbers is not a 1-D float4 array");
2771 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2772 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2773 *nnumbers = narrayelem;
2776 * Free statarray if it's a detoasted copy.
2778 if ((Pointer) statarray != DatumGetPointer(val))
2787 * Free data allocated by get_attstatsslot
2789 * atttype need be valid only if values != NULL.
2792 free_attstatsslot(Oid atttype,
2793 Datum *values, int nvalues,
2794 float4 *numbers, int nnumbers)
2798 if (!get_typbyval(atttype))
2802 for (i = 0; i < nvalues; i++)
2803 pfree(DatumGetPointer(values[i]));
2811 /* ---------- PG_NAMESPACE CACHE ---------- */
2814 * get_namespace_name
2815 * Returns the name of a given namespace
2817 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2820 get_namespace_name(Oid nspid)
2824 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
2825 if (HeapTupleIsValid(tp))
2827 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2830 result = pstrdup(NameStr(nsptup->nspname));
2831 ReleaseSysCache(tp);