1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2010, 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_constraint.h"
24 #include "catalog/pg_namespace.h"
25 #include "catalog/pg_opclass.h"
26 #include "catalog/pg_operator.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_statistic.h"
29 #include "catalog/pg_type.h"
30 #include "miscadmin.h"
31 #include "nodes/makefuncs.h"
32 #include "utils/array.h"
33 #include "utils/builtins.h"
34 #include "utils/datum.h"
35 #include "utils/lsyscache.h"
36 #include "utils/syscache.h"
37 #include "utils/typcache.h"
39 /* Hook for plugins to get control in get_attavgwidth() */
40 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
43 /* ---------- AMOP CACHES ---------- */
48 * Return t iff operator 'opno' is in operator family 'opfamily'.
50 * This function only considers search operators, not ordering operators.
53 op_in_opfamily(Oid opno, Oid opfamily)
55 return SearchSysCacheExists3(AMOPOPID,
56 ObjectIdGetDatum(opno),
57 CharGetDatum(AMOP_SEARCH),
58 ObjectIdGetDatum(opfamily));
62 * get_op_opfamily_strategy
64 * Get the operator's strategy number within the specified opfamily,
65 * or 0 if it's not a member of the opfamily.
67 * This function only considers search operators, not ordering operators.
70 get_op_opfamily_strategy(Oid opno, Oid opfamily)
73 Form_pg_amop amop_tup;
76 tp = SearchSysCache3(AMOPOPID,
77 ObjectIdGetDatum(opno),
78 CharGetDatum(AMOP_SEARCH),
79 ObjectIdGetDatum(opfamily));
80 if (!HeapTupleIsValid(tp))
82 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
83 result = amop_tup->amopstrategy;
89 * get_op_opfamily_properties
91 * Get the operator's strategy number and declared input data types
92 * within the specified opfamily.
94 * This function only considers search operators, not ordering operators.
96 * Caller should already have verified that opno is a member of opfamily,
97 * therefore we raise an error if the tuple is not found.
100 get_op_opfamily_properties(Oid opno, Oid opfamily,
106 Form_pg_amop amop_tup;
108 tp = SearchSysCache3(AMOPOPID,
109 ObjectIdGetDatum(opno),
110 CharGetDatum(AMOP_SEARCH),
111 ObjectIdGetDatum(opfamily));
112 if (!HeapTupleIsValid(tp))
113 elog(ERROR, "operator %u is not a member of opfamily %u",
115 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
116 *strategy = amop_tup->amopstrategy;
117 *lefttype = amop_tup->amoplefttype;
118 *righttype = amop_tup->amoprighttype;
123 * get_opfamily_member
124 * Get the OID of the operator that implements the specified strategy
125 * with the specified datatypes for the specified opfamily.
127 * Returns InvalidOid if there is no pg_amop entry for the given keys.
130 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
134 Form_pg_amop amop_tup;
137 tp = SearchSysCache4(AMOPSTRATEGY,
138 ObjectIdGetDatum(opfamily),
139 ObjectIdGetDatum(lefttype),
140 ObjectIdGetDatum(righttype),
141 Int16GetDatum(strategy));
142 if (!HeapTupleIsValid(tp))
144 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
145 result = amop_tup->amopopr;
151 * get_ordering_op_properties
152 * Given the OID of an ordering operator (a btree "<" or ">" operator),
153 * determine its opfamily, its declared input datatype, and its
154 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
156 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
157 * (This indicates that the operator is not a valid ordering operator.)
159 * Note: the operator could be registered in multiple families, for example
160 * if someone were to build a "reverse sort" opfamily. This would result in
161 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
162 * or NULLS LAST, as well as inefficient planning due to failure to match up
163 * pathkeys that should be the same. So we want a determinate result here.
164 * Because of the way the syscache search works, we'll use the interpretation
165 * associated with the opfamily with smallest OID, which is probably
166 * determinate enough. Since there is no longer any particularly good reason
167 * to build reverse-sort opfamilies, it doesn't seem worth expending any
168 * additional effort on ensuring consistency.
171 get_ordering_op_properties(Oid opno,
172 Oid *opfamily, Oid *opcintype, int16 *strategy)
178 /* ensure outputs are initialized on failure */
179 *opfamily = InvalidOid;
180 *opcintype = InvalidOid;
184 * Search pg_amop to see if the target operator is registered as the "<"
185 * or ">" operator of any btree opfamily.
187 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
189 for (i = 0; i < catlist->n_members; i++)
191 HeapTuple tuple = &catlist->members[i]->tuple;
192 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
195 if (aform->amopmethod != BTREE_AM_OID)
198 if (aform->amopstrategy == BTLessStrategyNumber ||
199 aform->amopstrategy == BTGreaterStrategyNumber)
201 /* Found it ... should have consistent input types */
202 if (aform->amoplefttype == aform->amoprighttype)
204 /* Found a suitable opfamily, return info */
205 *opfamily = aform->amopfamily;
206 *opcintype = aform->amoplefttype;
207 *strategy = aform->amopstrategy;
214 ReleaseSysCacheList(catlist);
220 * get_compare_function_for_ordering_op
221 * Get the OID of the datatype-specific btree comparison function
222 * associated with an ordering operator (a "<" or ">" operator).
224 * *cmpfunc receives the comparison function OID.
225 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
226 * (indicating the comparison result must be negated before use).
228 * Returns TRUE if successful, FALSE if no btree function can be found.
229 * (This indicates that the operator is not a valid ordering operator.)
232 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
238 /* Find the operator in pg_amop */
239 if (get_ordering_op_properties(opno,
240 &opfamily, &opcintype, &strategy))
242 /* Found a suitable opfamily, get matching support function */
243 *cmpfunc = get_opfamily_proc(opfamily,
248 if (!OidIsValid(*cmpfunc)) /* should not happen */
249 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
250 BTORDER_PROC, opcintype, opcintype, opfamily);
251 *reverse = (strategy == BTGreaterStrategyNumber);
255 /* ensure outputs are set on failure */
256 *cmpfunc = InvalidOid;
263 * get_equality_op_for_ordering_op
264 * Get the OID of the datatype-specific btree equality operator
265 * associated with an ordering operator (a "<" or ">" operator).
267 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
270 * Returns InvalidOid if no matching equality operator can be found.
271 * (This indicates that the operator is not a valid ordering operator.)
274 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
276 Oid result = InvalidOid;
281 /* Find the operator in pg_amop */
282 if (get_ordering_op_properties(opno,
283 &opfamily, &opcintype, &strategy))
285 /* Found a suitable opfamily, get matching equality operator */
286 result = get_opfamily_member(opfamily,
289 BTEqualStrategyNumber);
291 *reverse = (strategy == BTGreaterStrategyNumber);
298 * get_ordering_op_for_equality_op
299 * Get the OID of a datatype-specific btree ordering operator
300 * associated with an equality operator. (If there are multiple
301 * possibilities, assume any one will do.)
303 * This function is used when we have to sort data before unique-ifying,
304 * and don't much care which sorting op is used as long as it's compatible
305 * with the intended equality operator. Since we need a sorting operator,
306 * it should be single-data-type even if the given operator is cross-type.
307 * The caller specifies whether to find an op for the LHS or RHS data type.
309 * Returns InvalidOid if no matching ordering operator can be found.
312 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
314 Oid result = InvalidOid;
319 * Search pg_amop to see if the target operator is registered as the "="
320 * operator of any btree opfamily.
322 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
324 for (i = 0; i < catlist->n_members; i++)
326 HeapTuple tuple = &catlist->members[i]->tuple;
327 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
330 if (aform->amopmethod != BTREE_AM_OID)
333 if (aform->amopstrategy == BTEqualStrategyNumber)
335 /* Found a suitable opfamily, get matching ordering operator */
338 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
339 result = get_opfamily_member(aform->amopfamily,
341 BTLessStrategyNumber);
342 if (OidIsValid(result))
344 /* failure probably shouldn't happen, but keep looking if so */
348 ReleaseSysCacheList(catlist);
354 * get_mergejoin_opfamilies
355 * Given a putatively mergejoinable operator, return a list of the OIDs
356 * of the btree opfamilies in which it represents equality.
358 * It is possible (though at present unusual) for an operator to be equality
359 * in more than one opfamily, hence the result is a list. This also lets us
360 * return NIL if the operator is not found in any opfamilies.
362 * The planner currently uses simple equal() tests to compare the lists
363 * returned by this function, which makes the list order relevant, though
364 * strictly speaking it should not be. Because of the way syscache list
365 * searches are handled, in normal operation the result will be sorted by OID
366 * so everything works fine. If running with system index usage disabled,
367 * the result ordering is unspecified and hence the planner might fail to
368 * recognize optimization opportunities ... but that's hardly a scenario in
369 * which performance is good anyway, so there's no point in expending code
370 * or cycles here to guarantee the ordering in that case.
373 get_mergejoin_opfamilies(Oid opno)
380 * Search pg_amop to see if the target operator is registered as the "="
381 * operator of any btree opfamily.
383 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
385 for (i = 0; i < catlist->n_members; i++)
387 HeapTuple tuple = &catlist->members[i]->tuple;
388 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
390 /* must be btree equality */
391 if (aform->amopmethod == BTREE_AM_OID &&
392 aform->amopstrategy == BTEqualStrategyNumber)
393 result = lappend_oid(result, aform->amopfamily);
396 ReleaseSysCacheList(catlist);
402 * get_compatible_hash_operators
403 * Get the OID(s) of hash equality operator(s) compatible with the given
404 * operator, but operating on its LHS and/or RHS datatype.
406 * An operator for the LHS type is sought and returned into *lhs_opno if
407 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
408 * and returned into *rhs_opno if rhs_opno isn't NULL.
410 * If the given operator is not cross-type, the results should be the same
411 * operator, but in cross-type situations they will be different.
413 * Returns true if able to find the requested operator(s), false if not.
414 * (This indicates that the operator should not have been marked oprcanhash.)
417 get_compatible_hash_operators(Oid opno,
418 Oid *lhs_opno, Oid *rhs_opno)
424 /* Ensure output args are initialized on failure */
426 *lhs_opno = InvalidOid;
428 *rhs_opno = InvalidOid;
431 * Search pg_amop to see if the target operator is registered as the "="
432 * operator of any hash opfamily. If the operator is registered in
433 * multiple opfamilies, assume we can use any one.
435 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
437 for (i = 0; i < catlist->n_members; i++)
439 HeapTuple tuple = &catlist->members[i]->tuple;
440 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
442 if (aform->amopmethod == HASH_AM_OID &&
443 aform->amopstrategy == HTEqualStrategyNumber)
445 /* No extra lookup needed if given operator is single-type */
446 if (aform->amoplefttype == aform->amoprighttype)
457 * Get the matching single-type operator(s). Failure probably
458 * shouldn't happen --- it implies a bogus opfamily --- but
459 * continue looking if so.
463 *lhs_opno = get_opfamily_member(aform->amopfamily,
466 HTEqualStrategyNumber);
467 if (!OidIsValid(*lhs_opno))
469 /* Matching LHS found, done if caller doesn't want RHS */
478 *rhs_opno = get_opfamily_member(aform->amopfamily,
479 aform->amoprighttype,
480 aform->amoprighttype,
481 HTEqualStrategyNumber);
482 if (!OidIsValid(*rhs_opno))
484 /* Forget any LHS operator from this opfamily */
486 *lhs_opno = InvalidOid;
489 /* Matching RHS found, so done */
496 ReleaseSysCacheList(catlist);
502 * get_op_hash_functions
503 * Get the OID(s) of hash support function(s) compatible with the given
504 * operator, operating on its LHS and/or RHS datatype as required.
506 * A function for the LHS type is sought and returned into *lhs_procno if
507 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
508 * and returned into *rhs_procno if rhs_procno isn't NULL.
510 * If the given operator is not cross-type, the results should be the same
511 * function, but in cross-type situations they will be different.
513 * Returns true if able to find the requested function(s), false if not.
514 * (This indicates that the operator should not have been marked oprcanhash.)
517 get_op_hash_functions(Oid opno,
518 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
524 /* Ensure output args are initialized on failure */
526 *lhs_procno = InvalidOid;
528 *rhs_procno = InvalidOid;
531 * Search pg_amop to see if the target operator is registered as the "="
532 * operator of any hash opfamily. If the operator is registered in
533 * multiple opfamilies, assume we can use any one.
535 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
537 for (i = 0; i < catlist->n_members; i++)
539 HeapTuple tuple = &catlist->members[i]->tuple;
540 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
542 if (aform->amopmethod == HASH_AM_OID &&
543 aform->amopstrategy == HTEqualStrategyNumber)
546 * Get the matching support function(s). Failure probably
547 * shouldn't happen --- it implies a bogus opfamily --- but
548 * continue looking if so.
552 *lhs_procno = get_opfamily_proc(aform->amopfamily,
556 if (!OidIsValid(*lhs_procno))
558 /* Matching LHS found, done if caller doesn't want RHS */
564 /* Only one lookup needed if given operator is single-type */
565 if (aform->amoplefttype == aform->amoprighttype)
567 *rhs_procno = *lhs_procno;
574 *rhs_procno = get_opfamily_proc(aform->amopfamily,
575 aform->amoprighttype,
576 aform->amoprighttype,
578 if (!OidIsValid(*rhs_procno))
580 /* Forget any LHS function from this opfamily */
582 *lhs_procno = InvalidOid;
585 /* Matching RHS found, so done */
592 ReleaseSysCacheList(catlist);
598 * get_op_btree_interpretation
599 * Given an operator's OID, find out which btree opfamilies it belongs to,
600 * and what strategy number it has within each one. The results are
601 * returned as an OID list and a parallel integer list.
603 * In addition to the normal btree operators, we consider a <> operator to be
604 * a "member" of an opfamily if its negator is an equality operator of the
605 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
608 get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
618 * Find all the pg_amop entries containing the operator.
620 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
623 * If we can't find any opfamily containing the op, perhaps it is a <>
624 * operator. See if it has a negator that is in an opfamily.
627 if (catlist->n_members == 0)
629 Oid op_negator = get_negator(opno);
631 if (OidIsValid(op_negator))
634 ReleaseSysCacheList(catlist);
635 catlist = SearchSysCacheList1(AMOPOPID,
636 ObjectIdGetDatum(op_negator));
640 /* Now search the opfamilies */
641 for (i = 0; i < catlist->n_members; i++)
643 HeapTuple op_tuple = &catlist->members[i]->tuple;
644 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
646 StrategyNumber op_strategy;
649 if (op_form->amopmethod != BTREE_AM_OID)
652 /* Get the operator's btree strategy number */
653 opfamily_id = op_form->amopfamily;
654 op_strategy = (StrategyNumber) op_form->amopstrategy;
655 Assert(op_strategy >= 1 && op_strategy <= 5);
659 /* Only consider negators that are = */
660 if (op_strategy != BTEqualStrategyNumber)
662 op_strategy = ROWCOMPARE_NE;
665 *opfamilies = lappend_oid(*opfamilies, opfamily_id);
666 *opstrats = lappend_int(*opstrats, op_strategy);
669 ReleaseSysCacheList(catlist);
673 * equality_ops_are_compatible
674 * Return TRUE if the two given equality operators have compatible
677 * This is trivially true if they are the same operator. Otherwise,
678 * we look to see if they can be found in the same btree or hash opfamily.
679 * Either finding allows us to assume that they have compatible notions
680 * of equality. (The reason we need to do these pushups is that one might
681 * be a cross-type operator; for instance int24eq vs int4eq.)
684 equality_ops_are_compatible(Oid opno1, Oid opno2)
690 /* Easy if they're the same operator */
695 * We search through all the pg_amop entries for opno1.
697 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
700 for (i = 0; i < catlist->n_members; i++)
702 HeapTuple op_tuple = &catlist->members[i]->tuple;
703 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
705 /* must be btree or hash */
706 if (op_form->amopmethod == BTREE_AM_OID ||
707 op_form->amopmethod == HASH_AM_OID)
709 if (op_in_opfamily(opno2, op_form->amopfamily))
717 ReleaseSysCacheList(catlist);
723 /* ---------- AMPROC CACHES ---------- */
727 * Get the OID of the specified support function
728 * for the specified opfamily and datatypes.
730 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
733 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
736 Form_pg_amproc amproc_tup;
739 tp = SearchSysCache4(AMPROCNUM,
740 ObjectIdGetDatum(opfamily),
741 ObjectIdGetDatum(lefttype),
742 ObjectIdGetDatum(righttype),
743 Int16GetDatum(procnum));
744 if (!HeapTupleIsValid(tp))
746 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
747 result = amproc_tup->amproc;
753 /* ---------- ATTRIBUTE CACHES ---------- */
757 * Given the relation id and the attribute number,
758 * return the "attname" field from the attribute relation.
760 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
763 get_attname(Oid relid, AttrNumber attnum)
767 tp = SearchSysCache2(ATTNUM,
768 ObjectIdGetDatum(relid),
769 Int16GetDatum(attnum));
770 if (HeapTupleIsValid(tp))
772 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
775 result = pstrdup(NameStr(att_tup->attname));
784 * get_relid_attribute_name
786 * Same as above routine get_attname(), except that error
787 * is handled by elog() instead of returning NULL.
790 get_relid_attribute_name(Oid relid, AttrNumber attnum)
794 attname = get_attname(relid, attnum);
796 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
804 * Given the relation id and the attribute name,
805 * return the "attnum" field from the attribute relation.
807 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
810 get_attnum(Oid relid, const char *attname)
814 tp = SearchSysCacheAttName(relid, attname);
815 if (HeapTupleIsValid(tp))
817 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
820 result = att_tup->attnum;
825 return InvalidAttrNumber;
831 * Given the relation OID and the attribute number with the relation,
832 * return the attribute type OID.
835 get_atttype(Oid relid, AttrNumber attnum)
839 tp = SearchSysCache2(ATTNUM,
840 ObjectIdGetDatum(relid),
841 Int16GetDatum(attnum));
842 if (HeapTupleIsValid(tp))
844 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
847 result = att_tup->atttypid;
858 * Given the relation id and the attribute number,
859 * return the "atttypmod" field from the attribute relation.
862 get_atttypmod(Oid relid, AttrNumber attnum)
866 tp = SearchSysCache2(ATTNUM,
867 ObjectIdGetDatum(relid),
868 Int16GetDatum(attnum));
869 if (HeapTupleIsValid(tp))
871 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
874 result = att_tup->atttypmod;
885 * A two-fer: given the relation id and the attribute number,
886 * fetch both type OID and atttypmod in a single cache lookup.
888 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
889 * raises an error if it can't obtain the information.
892 get_atttypetypmod(Oid relid, AttrNumber attnum,
893 Oid *typid, int32 *typmod)
896 Form_pg_attribute att_tup;
898 tp = SearchSysCache2(ATTNUM,
899 ObjectIdGetDatum(relid),
900 Int16GetDatum(attnum));
901 if (!HeapTupleIsValid(tp))
902 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
904 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
906 *typid = att_tup->atttypid;
907 *typmod = att_tup->atttypmod;
911 /* ---------- CONSTRAINT CACHE ---------- */
914 * get_constraint_name
915 * Returns the name of a given pg_constraint entry.
917 * Returns a palloc'd copy of the string, or NULL if no such constraint.
919 * NOTE: since constraint name is not unique, be wary of code that uses this
920 * for anything except preparing error messages.
923 get_constraint_name(Oid conoid)
927 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
928 if (HeapTupleIsValid(tp))
930 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
933 result = pstrdup(NameStr(contup->conname));
941 /* ---------- OPCLASS CACHE ---------- */
946 * Returns the OID of the operator family the opclass belongs to.
949 get_opclass_family(Oid opclass)
952 Form_pg_opclass cla_tup;
955 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
956 if (!HeapTupleIsValid(tp))
957 elog(ERROR, "cache lookup failed for opclass %u", opclass);
958 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
960 result = cla_tup->opcfamily;
966 * get_opclass_input_type
968 * Returns the OID of the datatype the opclass indexes.
971 get_opclass_input_type(Oid opclass)
974 Form_pg_opclass cla_tup;
977 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
978 if (!HeapTupleIsValid(tp))
979 elog(ERROR, "cache lookup failed for opclass %u", opclass);
980 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
982 result = cla_tup->opcintype;
987 /* ---------- OPERATOR CACHE ---------- */
992 * Returns the regproc id of the routine used to implement an
993 * operator given the operator oid.
1000 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1001 if (HeapTupleIsValid(tp))
1003 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1004 RegProcedure result;
1006 result = optup->oprcode;
1007 ReleaseSysCache(tp);
1011 return (RegProcedure) InvalidOid;
1016 * returns the name of the operator with the given opno
1018 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1021 get_opname(Oid opno)
1025 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1026 if (HeapTupleIsValid(tp))
1028 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1031 result = pstrdup(NameStr(optup->oprname));
1032 ReleaseSysCache(tp);
1042 * Returns the left and right input datatypes for an operator
1043 * (InvalidOid if not relevant).
1046 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1049 Form_pg_operator optup;
1051 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1052 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1053 elog(ERROR, "cache lookup failed for operator %u", opno);
1054 optup = (Form_pg_operator) GETSTRUCT(tp);
1055 *lefttype = optup->oprleft;
1056 *righttype = optup->oprright;
1057 ReleaseSysCache(tp);
1063 * Returns true if the operator is potentially mergejoinable. (The planner
1064 * will fail to find any mergejoin plans unless there are suitable btree
1065 * opfamily entries for this operator and associated sortops. The pg_operator
1066 * flag is just a hint to tell the planner whether to bother looking.)
1068 * In some cases (currently only array_eq), mergejoinability depends on the
1069 * specific input data type the operator is invoked for, so that must be
1070 * passed as well. We currently assume that only one input's type is needed
1071 * to check this --- by convention, pass the left input's data type.
1074 op_mergejoinable(Oid opno, Oid inputtype)
1077 bool result = false;
1079 if (opno == ARRAY_EQ_OP)
1082 * For array_eq, can sort if element type has a default btree opclass.
1083 * We could use GetDefaultOpClass, but that's fairly expensive and not
1084 * cached, so let's use the typcache instead.
1086 Oid elem_type = get_base_element_type(inputtype);
1088 if (OidIsValid(elem_type))
1090 TypeCacheEntry *typentry;
1092 typentry = lookup_type_cache(elem_type, TYPECACHE_BTREE_OPFAMILY);
1093 if (OidIsValid(typentry->btree_opf))
1099 /* For all other operators, rely on pg_operator.oprcanmerge */
1100 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1101 if (HeapTupleIsValid(tp))
1103 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1105 result = optup->oprcanmerge;
1106 ReleaseSysCache(tp);
1115 * Returns true if the operator is hashjoinable. (There must be a suitable
1116 * hash opfamily entry for this operator if it is so marked.)
1118 * In some cases (currently only array_eq), hashjoinability depends on the
1119 * specific input data type the operator is invoked for, so that must be
1120 * passed as well. We currently assume that only one input's type is needed
1121 * to check this --- by convention, pass the left input's data type.
1124 op_hashjoinable(Oid opno, Oid inputtype)
1127 bool result = false;
1129 if (opno == ARRAY_EQ_OP)
1131 /* For array_eq, can hash if element type has a default hash opclass */
1132 Oid elem_type = get_base_element_type(inputtype);
1134 if (OidIsValid(elem_type))
1136 TypeCacheEntry *typentry;
1138 typentry = lookup_type_cache(elem_type, TYPECACHE_HASH_OPFAMILY);
1139 if (OidIsValid(typentry->hash_opf))
1145 /* For all other operators, rely on pg_operator.oprcanhash */
1146 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1147 if (HeapTupleIsValid(tp))
1149 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1151 result = optup->oprcanhash;
1152 ReleaseSysCache(tp);
1161 * Get the proisstrict flag for the operator's underlying function.
1166 RegProcedure funcid = get_opcode(opno);
1168 if (funcid == (RegProcedure) InvalidOid)
1169 elog(ERROR, "operator %u does not exist", opno);
1171 return func_strict((Oid) funcid);
1177 * Get the provolatile flag for the operator's underlying function.
1180 op_volatile(Oid opno)
1182 RegProcedure funcid = get_opcode(opno);
1184 if (funcid == (RegProcedure) InvalidOid)
1185 elog(ERROR, "operator %u does not exist", opno);
1187 return func_volatile((Oid) funcid);
1193 * Returns the corresponding commutator of an operator.
1196 get_commutator(Oid opno)
1200 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1201 if (HeapTupleIsValid(tp))
1203 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1206 result = optup->oprcom;
1207 ReleaseSysCache(tp);
1217 * Returns the corresponding negator of an operator.
1220 get_negator(Oid opno)
1224 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1225 if (HeapTupleIsValid(tp))
1227 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1230 result = optup->oprnegate;
1231 ReleaseSysCache(tp);
1241 * Returns procedure id for computing selectivity of an operator.
1244 get_oprrest(Oid opno)
1248 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1249 if (HeapTupleIsValid(tp))
1251 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1252 RegProcedure result;
1254 result = optup->oprrest;
1255 ReleaseSysCache(tp);
1259 return (RegProcedure) InvalidOid;
1265 * Returns procedure id for computing selectivity of a join.
1268 get_oprjoin(Oid opno)
1272 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1273 if (HeapTupleIsValid(tp))
1275 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1276 RegProcedure result;
1278 result = optup->oprjoin;
1279 ReleaseSysCache(tp);
1283 return (RegProcedure) InvalidOid;
1286 /* ---------- FUNCTION CACHE ---------- */
1290 * returns the name of the function with the given funcid
1292 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1295 get_func_name(Oid funcid)
1299 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1300 if (HeapTupleIsValid(tp))
1302 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1305 result = pstrdup(NameStr(functup->proname));
1306 ReleaseSysCache(tp);
1314 * get_func_namespace
1316 * Returns the pg_namespace OID associated with a given function.
1319 get_func_namespace(Oid funcid)
1323 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1324 if (HeapTupleIsValid(tp))
1326 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1329 result = functup->pronamespace;
1330 ReleaseSysCache(tp);
1339 * Given procedure id, return the function's result type.
1342 get_func_rettype(Oid funcid)
1347 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1348 if (!HeapTupleIsValid(tp))
1349 elog(ERROR, "cache lookup failed for function %u", funcid);
1351 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1352 ReleaseSysCache(tp);
1358 * Given procedure id, return the number of arguments.
1361 get_func_nargs(Oid funcid)
1366 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1367 if (!HeapTupleIsValid(tp))
1368 elog(ERROR, "cache lookup failed for function %u", funcid);
1370 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1371 ReleaseSysCache(tp);
1376 * get_func_signature
1377 * Given procedure id, return the function's argument and result types.
1378 * (The return value is the result type.)
1380 * The arguments are returned as a palloc'd array.
1383 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1386 Form_pg_proc procstruct;
1389 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1390 if (!HeapTupleIsValid(tp))
1391 elog(ERROR, "cache lookup failed for function %u", funcid);
1393 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1395 result = procstruct->prorettype;
1396 *nargs = (int) procstruct->pronargs;
1397 Assert(*nargs == procstruct->proargtypes.dim1);
1398 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1399 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1401 ReleaseSysCache(tp);
1407 * Given procedure id, return the function's proretset flag.
1410 get_func_retset(Oid funcid)
1415 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1416 if (!HeapTupleIsValid(tp))
1417 elog(ERROR, "cache lookup failed for function %u", funcid);
1419 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1420 ReleaseSysCache(tp);
1426 * Given procedure id, return the function's proisstrict flag.
1429 func_strict(Oid funcid)
1434 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1435 if (!HeapTupleIsValid(tp))
1436 elog(ERROR, "cache lookup failed for function %u", funcid);
1438 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1439 ReleaseSysCache(tp);
1445 * Given procedure id, return the function's provolatile flag.
1448 func_volatile(Oid funcid)
1453 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1454 if (!HeapTupleIsValid(tp))
1455 elog(ERROR, "cache lookup failed for function %u", funcid);
1457 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1458 ReleaseSysCache(tp);
1464 * Given procedure id, return the function's procost field.
1467 get_func_cost(Oid funcid)
1472 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1473 if (!HeapTupleIsValid(tp))
1474 elog(ERROR, "cache lookup failed for function %u", funcid);
1476 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1477 ReleaseSysCache(tp);
1483 * Given procedure id, return the function's prorows field.
1486 get_func_rows(Oid funcid)
1491 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1492 if (!HeapTupleIsValid(tp))
1493 elog(ERROR, "cache lookup failed for function %u", funcid);
1495 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1496 ReleaseSysCache(tp);
1500 /* ---------- RELATION CACHE ---------- */
1504 * Given name and namespace of a relation, look up the OID.
1506 * Returns InvalidOid if there is no such relation.
1509 get_relname_relid(const char *relname, Oid relnamespace)
1511 return GetSysCacheOid2(RELNAMENSP,
1512 PointerGetDatum(relname),
1513 ObjectIdGetDatum(relnamespace));
1520 * Returns the number of attributes for a given relation.
1523 get_relnatts(Oid relid)
1527 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1528 if (HeapTupleIsValid(tp))
1530 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1533 result = reltup->relnatts;
1534 ReleaseSysCache(tp);
1538 return InvalidAttrNumber;
1544 * Returns the name of a given relation.
1546 * Returns a palloc'd copy of the string, or NULL if no such relation.
1548 * NOTE: since relation name is not unique, be wary of code that uses this
1549 * for anything except preparing error messages.
1552 get_rel_name(Oid relid)
1556 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1557 if (HeapTupleIsValid(tp))
1559 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1562 result = pstrdup(NameStr(reltup->relname));
1563 ReleaseSysCache(tp);
1573 * Returns the pg_namespace OID associated with a given relation.
1576 get_rel_namespace(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->relnamespace;
1587 ReleaseSysCache(tp);
1597 * Returns the pg_type OID associated with a given relation.
1599 * Note: not all pg_class entries have associated pg_type OIDs; so be
1600 * careful to check for InvalidOid result.
1603 get_rel_type_id(Oid relid)
1607 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1608 if (HeapTupleIsValid(tp))
1610 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1613 result = reltup->reltype;
1614 ReleaseSysCache(tp);
1624 * Returns the relkind associated with a given relation.
1627 get_rel_relkind(Oid relid)
1631 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1632 if (HeapTupleIsValid(tp))
1634 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1637 result = reltup->relkind;
1638 ReleaseSysCache(tp);
1646 * get_rel_tablespace
1648 * Returns the pg_tablespace OID associated with a given relation.
1650 * Note: InvalidOid might mean either that we couldn't find the relation,
1651 * or that it is in the database's default tablespace.
1654 get_rel_tablespace(Oid relid)
1658 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1659 if (HeapTupleIsValid(tp))
1661 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1664 result = reltup->reltablespace;
1665 ReleaseSysCache(tp);
1673 /* ---------- TYPE CACHE ---------- */
1678 * Given the type OID, determine whether the type is defined
1679 * (if not, it's only a shell).
1682 get_typisdefined(Oid typid)
1686 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1687 if (HeapTupleIsValid(tp))
1689 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1692 result = typtup->typisdefined;
1693 ReleaseSysCache(tp);
1703 * Given the type OID, return the length of the type.
1706 get_typlen(Oid typid)
1710 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1711 if (HeapTupleIsValid(tp))
1713 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1716 result = typtup->typlen;
1717 ReleaseSysCache(tp);
1727 * Given the type OID, determine whether the type is returned by value or
1728 * not. Returns true if by value, false if by reference.
1731 get_typbyval(Oid typid)
1735 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1736 if (HeapTupleIsValid(tp))
1738 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1741 result = typtup->typbyval;
1742 ReleaseSysCache(tp);
1752 * A two-fer: given the type OID, return both typlen and typbyval.
1754 * Since both pieces of info are needed to know how to copy a Datum,
1755 * many places need both. Might as well get them with one cache lookup
1756 * instead of two. Also, this routine raises an error instead of
1757 * returning a bogus value when given a bad type OID.
1760 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1763 Form_pg_type typtup;
1765 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1766 if (!HeapTupleIsValid(tp))
1767 elog(ERROR, "cache lookup failed for type %u", typid);
1768 typtup = (Form_pg_type) GETSTRUCT(tp);
1769 *typlen = typtup->typlen;
1770 *typbyval = typtup->typbyval;
1771 ReleaseSysCache(tp);
1775 * get_typlenbyvalalign
1777 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1780 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1784 Form_pg_type typtup;
1786 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1787 if (!HeapTupleIsValid(tp))
1788 elog(ERROR, "cache lookup failed for type %u", typid);
1789 typtup = (Form_pg_type) GETSTRUCT(tp);
1790 *typlen = typtup->typlen;
1791 *typbyval = typtup->typbyval;
1792 *typalign = typtup->typalign;
1793 ReleaseSysCache(tp);
1798 * Given a pg_type row, select the type OID to pass to I/O functions
1800 * Formerly, all I/O functions were passed pg_type.typelem as their second
1801 * parameter, but we now have a more complex rule about what to pass.
1802 * This knowledge is intended to be centralized here --- direct references
1803 * to typelem elsewhere in the code are wrong, if they are associated with
1804 * I/O calls and not with actual subscripting operations! (But see
1805 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1807 * As of PostgreSQL 8.1, output functions receive only the value itself
1808 * and not any auxiliary parameters, so the name of this routine is now
1809 * a bit of a misnomer ... it should be getTypeInputParam.
1812 getTypeIOParam(HeapTuple typeTuple)
1814 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1817 * Array types get their typelem as parameter; everybody else gets their
1818 * own type OID as parameter. (As of 8.2, domains must get their own OID
1819 * even if their base type is an array.)
1821 if (typeStruct->typtype == TYPTYPE_BASE && OidIsValid(typeStruct->typelem))
1822 return typeStruct->typelem;
1824 return HeapTupleGetOid(typeTuple);
1830 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1831 * typdelim, typioparam, and IO function OID. The IO function
1832 * returned is controlled by IOFuncSelector
1835 get_type_io_data(Oid typid,
1836 IOFuncSelector which_func,
1844 HeapTuple typeTuple;
1845 Form_pg_type typeStruct;
1848 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1849 * use array_in and array_out during bootstrap.
1851 if (IsBootstrapProcessingMode())
1856 boot_get_type_io_data(typid,
1873 elog(ERROR, "binary I/O not supported during bootstrap");
1879 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1880 if (!HeapTupleIsValid(typeTuple))
1881 elog(ERROR, "cache lookup failed for type %u", typid);
1882 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1884 *typlen = typeStruct->typlen;
1885 *typbyval = typeStruct->typbyval;
1886 *typalign = typeStruct->typalign;
1887 *typdelim = typeStruct->typdelim;
1888 *typioparam = getTypeIOParam(typeTuple);
1892 *func = typeStruct->typinput;
1895 *func = typeStruct->typoutput;
1897 case IOFunc_receive:
1898 *func = typeStruct->typreceive;
1901 *func = typeStruct->typsend;
1904 ReleaseSysCache(typeTuple);
1909 get_typalign(Oid typid)
1913 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1914 if (HeapTupleIsValid(tp))
1916 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1919 result = typtup->typalign;
1920 ReleaseSysCache(tp);
1929 get_typstorage(Oid typid)
1933 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1934 if (HeapTupleIsValid(tp))
1936 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1939 result = typtup->typstorage;
1940 ReleaseSysCache(tp);
1949 * Given a type OID, return the type's default value, if any.
1951 * The result is a palloc'd expression node tree, or NULL if there
1952 * is no defined default for the datatype.
1954 * NB: caller should be prepared to coerce result to correct datatype;
1955 * the returned expression tree might produce something of the wrong type.
1958 get_typdefault(Oid typid)
1960 HeapTuple typeTuple;
1966 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1967 if (!HeapTupleIsValid(typeTuple))
1968 elog(ERROR, "cache lookup failed for type %u", typid);
1969 type = (Form_pg_type) GETSTRUCT(typeTuple);
1972 * typdefault and typdefaultbin are potentially null, so don't try to
1973 * access 'em as struct fields. Must do it the hard way with
1976 datum = SysCacheGetAttr(TYPEOID,
1978 Anum_pg_type_typdefaultbin,
1983 /* We have an expression default */
1984 expr = stringToNode(TextDatumGetCString(datum));
1988 /* Perhaps we have a plain literal default */
1989 datum = SysCacheGetAttr(TYPEOID,
1991 Anum_pg_type_typdefault,
1996 char *strDefaultVal;
1998 /* Convert text datum to C string */
1999 strDefaultVal = TextDatumGetCString(datum);
2000 /* Convert C string to a value of the given type */
2001 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2002 getTypeIOParam(typeTuple), -1);
2003 /* Build a Const node containing the value */
2004 expr = (Node *) makeConst(typid,
2010 pfree(strDefaultVal);
2019 ReleaseSysCache(typeTuple);
2026 * If the given type is a domain, return its base type;
2027 * otherwise return the type's own OID.
2030 getBaseType(Oid typid)
2034 return getBaseTypeAndTypmod(typid, &typmod);
2038 * getBaseTypeAndTypmod
2039 * If the given type is a domain, return its base type and typmod;
2040 * otherwise return the type's own OID, and leave *typmod unchanged.
2042 * Note that the "applied typmod" should be -1 for every domain level
2043 * above the bottommost; therefore, if the passed-in typid is indeed
2044 * a domain, *typmod should be -1.
2047 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2050 * We loop to find the bottom base type in a stack of domains.
2055 Form_pg_type typTup;
2057 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2058 if (!HeapTupleIsValid(tup))
2059 elog(ERROR, "cache lookup failed for type %u", typid);
2060 typTup = (Form_pg_type) GETSTRUCT(tup);
2061 if (typTup->typtype != TYPTYPE_DOMAIN)
2063 /* Not a domain, so done */
2064 ReleaseSysCache(tup);
2068 Assert(*typmod == -1);
2069 typid = typTup->typbasetype;
2070 *typmod = typTup->typtypmod;
2072 ReleaseSysCache(tup);
2081 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2082 * estimate the average width of values of the type. This is used by
2083 * the planner, which doesn't require absolutely correct results;
2084 * it's OK (and expected) to guess if we don't know for sure.
2087 get_typavgwidth(Oid typid, int32 typmod)
2089 int typlen = get_typlen(typid);
2093 * Easy if it's a fixed-width type
2099 * type_maximum_size knows the encoding of typmod for some datatypes;
2100 * don't duplicate that knowledge here.
2102 maxwidth = type_maximum_size(typid, typmod);
2106 * For BPCHAR, the max width is also the only width. Otherwise we
2107 * need to guess about the typical data width given the max. A sliding
2108 * scale for percentage of max width seems reasonable.
2110 if (typid == BPCHAROID)
2113 return maxwidth; /* assume full width */
2114 if (maxwidth < 1000)
2115 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2118 * Beyond 1000, assume we're looking at something like
2119 * "varchar(10000)" where the limit isn't actually reached often, and
2120 * use a fixed estimate.
2122 return 32 + (1000 - 32) / 2;
2126 * Ooops, we have no idea ... wild guess time.
2134 * Given the type OID, find if it is a basic type, a complex type, etc.
2135 * It returns the null char if the cache lookup fails...
2138 get_typtype(Oid typid)
2142 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2143 if (HeapTupleIsValid(tp))
2145 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2148 result = typtup->typtype;
2149 ReleaseSysCache(tp);
2159 * Convenience function to determine whether a type OID represents
2160 * a "rowtype" type --- either RECORD or a named composite type.
2163 type_is_rowtype(Oid typid)
2165 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2170 * Returns true if the given type is an enum type.
2173 type_is_enum(Oid typid)
2175 return (get_typtype(typid) == TYPTYPE_ENUM);
2179 * get_type_category_preferred
2181 * Given the type OID, fetch its category and preferred-type status.
2182 * Throws error on failure.
2185 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2188 Form_pg_type typtup;
2190 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2191 if (!HeapTupleIsValid(tp))
2192 elog(ERROR, "cache lookup failed for type %u", typid);
2193 typtup = (Form_pg_type) GETSTRUCT(tp);
2194 *typcategory = typtup->typcategory;
2195 *typispreferred = typtup->typispreferred;
2196 ReleaseSysCache(tp);
2202 * Given the type OID, get the typrelid (InvalidOid if not a complex
2206 get_typ_typrelid(Oid typid)
2210 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2211 if (HeapTupleIsValid(tp))
2213 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2216 result = typtup->typrelid;
2217 ReleaseSysCache(tp);
2227 * Given the type OID, get the typelem (InvalidOid if not an array type).
2229 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2230 * returned if the input is a fixed-length array type.
2233 get_element_type(Oid typid)
2237 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2238 if (HeapTupleIsValid(tp))
2240 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2243 if (typtup->typlen == -1)
2244 result = typtup->typelem;
2246 result = InvalidOid;
2247 ReleaseSysCache(tp);
2257 * Given the type OID, get the corresponding "true" array type.
2258 * Returns InvalidOid if no array type can be found.
2261 get_array_type(Oid typid)
2264 Oid result = InvalidOid;
2266 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2267 if (HeapTupleIsValid(tp))
2269 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2270 ReleaseSysCache(tp);
2276 * get_base_element_type
2277 * Given the type OID, get the typelem, looking "through" any domain
2278 * to its underlying array type.
2280 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2281 * an extra cache lookup. Note that it fails to provide any information
2282 * about the typmod of the array.
2285 get_base_element_type(Oid typid)
2288 * We loop to find the bottom base type in a stack of domains.
2293 Form_pg_type typTup;
2295 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2296 if (!HeapTupleIsValid(tup))
2298 typTup = (Form_pg_type) GETSTRUCT(tup);
2299 if (typTup->typtype != TYPTYPE_DOMAIN)
2301 /* Not a domain, so stop descending */
2304 /* This test must match get_element_type */
2305 if (typTup->typlen == -1)
2306 result = typTup->typelem;
2308 result = InvalidOid;
2309 ReleaseSysCache(tup);
2313 typid = typTup->typbasetype;
2314 ReleaseSysCache(tup);
2317 /* Like get_element_type, silently return InvalidOid for bogus input */
2324 * Get info needed for converting values of a type to internal form
2327 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2329 HeapTuple typeTuple;
2332 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2333 if (!HeapTupleIsValid(typeTuple))
2334 elog(ERROR, "cache lookup failed for type %u", type);
2335 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2337 if (!pt->typisdefined)
2339 (errcode(ERRCODE_UNDEFINED_OBJECT),
2340 errmsg("type %s is only a shell",
2341 format_type_be(type))));
2342 if (!OidIsValid(pt->typinput))
2344 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2345 errmsg("no input function available for type %s",
2346 format_type_be(type))));
2348 *typInput = pt->typinput;
2349 *typIOParam = getTypeIOParam(typeTuple);
2351 ReleaseSysCache(typeTuple);
2357 * Get info needed for printing values of a type
2360 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2362 HeapTuple typeTuple;
2365 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2366 if (!HeapTupleIsValid(typeTuple))
2367 elog(ERROR, "cache lookup failed for type %u", type);
2368 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2370 if (!pt->typisdefined)
2372 (errcode(ERRCODE_UNDEFINED_OBJECT),
2373 errmsg("type %s is only a shell",
2374 format_type_be(type))));
2375 if (!OidIsValid(pt->typoutput))
2377 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2378 errmsg("no output function available for type %s",
2379 format_type_be(type))));
2381 *typOutput = pt->typoutput;
2382 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2384 ReleaseSysCache(typeTuple);
2388 * getTypeBinaryInputInfo
2390 * Get info needed for binary input of values of a type
2393 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2395 HeapTuple typeTuple;
2398 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2399 if (!HeapTupleIsValid(typeTuple))
2400 elog(ERROR, "cache lookup failed for type %u", type);
2401 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2403 if (!pt->typisdefined)
2405 (errcode(ERRCODE_UNDEFINED_OBJECT),
2406 errmsg("type %s is only a shell",
2407 format_type_be(type))));
2408 if (!OidIsValid(pt->typreceive))
2410 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2411 errmsg("no binary input function available for type %s",
2412 format_type_be(type))));
2414 *typReceive = pt->typreceive;
2415 *typIOParam = getTypeIOParam(typeTuple);
2417 ReleaseSysCache(typeTuple);
2421 * getTypeBinaryOutputInfo
2423 * Get info needed for binary output of values of a type
2426 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2428 HeapTuple typeTuple;
2431 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2432 if (!HeapTupleIsValid(typeTuple))
2433 elog(ERROR, "cache lookup failed for type %u", type);
2434 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2436 if (!pt->typisdefined)
2438 (errcode(ERRCODE_UNDEFINED_OBJECT),
2439 errmsg("type %s is only a shell",
2440 format_type_be(type))));
2441 if (!OidIsValid(pt->typsend))
2443 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2444 errmsg("no binary output function available for type %s",
2445 format_type_be(type))));
2447 *typSend = pt->typsend;
2448 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2450 ReleaseSysCache(typeTuple);
2456 * Given the type OID, return the type's typmodin procedure, if any.
2459 get_typmodin(Oid typid)
2463 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2464 if (HeapTupleIsValid(tp))
2466 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2469 result = typtup->typmodin;
2470 ReleaseSysCache(tp);
2481 * Given the type OID, return the type's typmodout procedure, if any.
2484 get_typmodout(Oid typid)
2488 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2489 if (HeapTupleIsValid(tp))
2491 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2494 result = typtup->typmodout;
2495 ReleaseSysCache(tp);
2501 #endif /* NOT_USED */
2504 /* ---------- STATISTICS CACHE ---------- */
2509 * Given the table and attribute number of a column, get the average
2510 * width of entries in the column. Return zero if no data available.
2512 * Currently this is only consulted for individual tables, not for inheritance
2513 * trees, so we don't need an "inh" parameter.
2515 * Calling a hook at this point looks somewhat strange, but is required
2516 * because the optimizer calls this function without any other way for
2517 * plug-ins to control the result.
2520 get_attavgwidth(Oid relid, AttrNumber attnum)
2525 if (get_attavgwidth_hook)
2527 stawidth = (*get_attavgwidth_hook) (relid, attnum);
2531 tp = SearchSysCache3(STATRELATTINH,
2532 ObjectIdGetDatum(relid),
2533 Int16GetDatum(attnum),
2534 BoolGetDatum(false));
2535 if (HeapTupleIsValid(tp))
2537 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2538 ReleaseSysCache(tp);
2548 * Extract the contents of a "slot" of a pg_statistic tuple.
2549 * Returns TRUE if requested slot type was found, else FALSE.
2551 * Unlike other routines in this file, this takes a pointer to an
2552 * already-looked-up tuple in the pg_statistic cache. We do this since
2553 * most callers will want to extract more than one value from the cache
2554 * entry, and we don't want to repeat the cache lookup unnecessarily.
2555 * Also, this API allows this routine to be used with statistics tuples
2556 * that have been provided by a stats hook and didn't really come from
2559 * statstuple: pg_statistics tuple to be examined.
2560 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2561 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2562 * reqkind: STAKIND code for desired statistics slot kind.
2563 * reqop: STAOP value wanted, or InvalidOid if don't care.
2564 * actualop: if not NULL, *actualop receives the actual STAOP value.
2565 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2566 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2568 * If assigned, values and numbers are set to point to palloc'd arrays.
2569 * If the attribute type is pass-by-reference, the values referenced by
2570 * the values array are themselves palloc'd. The palloc'd stuff can be
2571 * freed by calling free_attstatsslot.
2573 * Note: at present, atttype/atttypmod aren't actually used here at all.
2574 * But the caller must have the correct (or at least binary-compatible)
2575 * type ID to pass to free_attstatsslot later.
2578 get_attstatsslot(HeapTuple statstuple,
2579 Oid atttype, int32 atttypmod,
2580 int reqkind, Oid reqop,
2582 Datum **values, int *nvalues,
2583 float4 **numbers, int *nnumbers)
2585 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2590 ArrayType *statarray;
2593 HeapTuple typeTuple;
2594 Form_pg_type typeForm;
2596 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2598 if ((&stats->stakind1)[i] == reqkind &&
2599 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2602 if (i >= STATISTIC_NUM_SLOTS)
2603 return false; /* not there */
2606 *actualop = (&stats->staop1)[i];
2610 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2611 Anum_pg_statistic_stavalues1 + i,
2614 elog(ERROR, "stavalues is null");
2615 statarray = DatumGetArrayTypeP(val);
2618 * Need to get info about the array element type. We look at the
2619 * actual element type embedded in the array, which might be only
2620 * binary-compatible with the passed-in atttype. The info we
2621 * extract here should be the same either way, but deconstruct_array
2622 * is picky about having an exact type OID match.
2624 arrayelemtype = ARR_ELEMTYPE(statarray);
2625 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
2626 if (!HeapTupleIsValid(typeTuple))
2627 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
2628 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2630 /* Deconstruct array into Datum elements; NULLs not expected */
2631 deconstruct_array(statarray,
2636 values, NULL, nvalues);
2639 * If the element type is pass-by-reference, we now have a bunch of
2640 * Datums that are pointers into the syscache value. Copy them to
2641 * avoid problems if syscache decides to drop the entry.
2643 if (!typeForm->typbyval)
2645 for (j = 0; j < *nvalues; j++)
2647 (*values)[j] = datumCopy((*values)[j],
2653 ReleaseSysCache(typeTuple);
2656 * Free statarray if it's a detoasted copy.
2658 if ((Pointer) statarray != DatumGetPointer(val))
2664 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2665 Anum_pg_statistic_stanumbers1 + i,
2668 elog(ERROR, "stanumbers is null");
2669 statarray = DatumGetArrayTypeP(val);
2672 * We expect the array to be a 1-D float4 array; verify that. We don't
2673 * need to use deconstruct_array() since the array data is just going
2674 * to look like a C array of float4 values.
2676 narrayelem = ARR_DIMS(statarray)[0];
2677 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2678 ARR_HASNULL(statarray) ||
2679 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2680 elog(ERROR, "stanumbers is not a 1-D float4 array");
2681 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2682 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2683 *nnumbers = narrayelem;
2686 * Free statarray if it's a detoasted copy.
2688 if ((Pointer) statarray != DatumGetPointer(val))
2697 * Free data allocated by get_attstatsslot
2699 * atttype need be valid only if values != NULL.
2702 free_attstatsslot(Oid atttype,
2703 Datum *values, int nvalues,
2704 float4 *numbers, int nnumbers)
2708 if (!get_typbyval(atttype))
2712 for (i = 0; i < nvalues; i++)
2713 pfree(DatumGetPointer(values[i]));
2721 /* ---------- PG_NAMESPACE CACHE ---------- */
2724 * get_namespace_name
2725 * Returns the name of a given namespace
2727 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2730 get_namespace_name(Oid nspid)
2734 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
2735 if (HeapTupleIsValid(tp))
2737 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2740 result = pstrdup(NameStr(nsptup->nspname));
2741 ReleaseSysCache(tp);