1 /*-------------------------------------------------------------------------
4 * Convenience routines for common queries in the system catalog cache.
6 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/utils/cache/lsyscache.c
13 * Eventually, the index information should go through here, too.
14 *-------------------------------------------------------------------------
18 #include "access/hash.h"
19 #include "access/nbtree.h"
20 #include "bootstrap/bootstrap.h"
21 #include "catalog/pg_amop.h"
22 #include "catalog/pg_amproc.h"
23 #include "catalog/pg_collation.h"
24 #include "catalog/pg_constraint.h"
25 #include "catalog/pg_namespace.h"
26 #include "catalog/pg_opclass.h"
27 #include "catalog/pg_operator.h"
28 #include "catalog/pg_proc.h"
29 #include "catalog/pg_range.h"
30 #include "catalog/pg_statistic.h"
31 #include "catalog/pg_type.h"
32 #include "miscadmin.h"
33 #include "nodes/makefuncs.h"
34 #include "utils/array.h"
35 #include "utils/builtins.h"
36 #include "utils/datum.h"
37 #include "utils/fmgroids.h"
38 #include "utils/lsyscache.h"
39 #include "utils/rel.h"
40 #include "utils/syscache.h"
41 #include "utils/typcache.h"
43 /* Hook for plugins to get control in get_attavgwidth() */
44 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
47 /* ---------- AMOP CACHES ---------- */
52 * Return t iff operator 'opno' is in operator family 'opfamily'.
54 * This function only considers search operators, not ordering operators.
57 op_in_opfamily(Oid opno, Oid opfamily)
59 return SearchSysCacheExists3(AMOPOPID,
60 ObjectIdGetDatum(opno),
61 CharGetDatum(AMOP_SEARCH),
62 ObjectIdGetDatum(opfamily));
66 * get_op_opfamily_strategy
68 * Get the operator's strategy number within the specified opfamily,
69 * or 0 if it's not a member of the opfamily.
71 * This function only considers search operators, not ordering operators.
74 get_op_opfamily_strategy(Oid opno, Oid opfamily)
77 Form_pg_amop amop_tup;
80 tp = SearchSysCache3(AMOPOPID,
81 ObjectIdGetDatum(opno),
82 CharGetDatum(AMOP_SEARCH),
83 ObjectIdGetDatum(opfamily));
84 if (!HeapTupleIsValid(tp))
86 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
87 result = amop_tup->amopstrategy;
93 * get_op_opfamily_sortfamily
95 * If the operator is an ordering operator within the specified opfamily,
96 * return its amopsortfamily OID; else return InvalidOid.
99 get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
102 Form_pg_amop amop_tup;
105 tp = SearchSysCache3(AMOPOPID,
106 ObjectIdGetDatum(opno),
107 CharGetDatum(AMOP_ORDER),
108 ObjectIdGetDatum(opfamily));
109 if (!HeapTupleIsValid(tp))
111 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
112 result = amop_tup->amopsortfamily;
118 * get_op_opfamily_properties
120 * Get the operator's strategy number and declared input data types
121 * within the specified opfamily.
123 * Caller should already have verified that opno is a member of opfamily,
124 * therefore we raise an error if the tuple is not found.
127 get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
133 Form_pg_amop amop_tup;
135 tp = SearchSysCache3(AMOPOPID,
136 ObjectIdGetDatum(opno),
137 CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
138 ObjectIdGetDatum(opfamily));
139 if (!HeapTupleIsValid(tp))
140 elog(ERROR, "operator %u is not a member of opfamily %u",
142 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
143 *strategy = amop_tup->amopstrategy;
144 *lefttype = amop_tup->amoplefttype;
145 *righttype = amop_tup->amoprighttype;
150 * get_opfamily_member
151 * Get the OID of the operator that implements the specified strategy
152 * with the specified datatypes for the specified opfamily.
154 * Returns InvalidOid if there is no pg_amop entry for the given keys.
157 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
161 Form_pg_amop amop_tup;
164 tp = SearchSysCache4(AMOPSTRATEGY,
165 ObjectIdGetDatum(opfamily),
166 ObjectIdGetDatum(lefttype),
167 ObjectIdGetDatum(righttype),
168 Int16GetDatum(strategy));
169 if (!HeapTupleIsValid(tp))
171 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
172 result = amop_tup->amopopr;
178 * get_ordering_op_properties
179 * Given the OID of an ordering operator (a btree "<" or ">" operator),
180 * determine its opfamily, its declared input datatype, and its
181 * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
183 * Returns TRUE if successful, FALSE if no matching pg_amop entry exists.
184 * (This indicates that the operator is not a valid ordering operator.)
186 * Note: the operator could be registered in multiple families, for example
187 * if someone were to build a "reverse sort" opfamily. This would result in
188 * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
189 * or NULLS LAST, as well as inefficient planning due to failure to match up
190 * pathkeys that should be the same. So we want a determinate result here.
191 * Because of the way the syscache search works, we'll use the interpretation
192 * associated with the opfamily with smallest OID, which is probably
193 * determinate enough. Since there is no longer any particularly good reason
194 * to build reverse-sort opfamilies, it doesn't seem worth expending any
195 * additional effort on ensuring consistency.
198 get_ordering_op_properties(Oid opno,
199 Oid *opfamily, Oid *opcintype, int16 *strategy)
205 /* ensure outputs are initialized on failure */
206 *opfamily = InvalidOid;
207 *opcintype = InvalidOid;
211 * Search pg_amop to see if the target operator is registered as the "<"
212 * or ">" operator of any btree opfamily.
214 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
216 for (i = 0; i < catlist->n_members; i++)
218 HeapTuple tuple = &catlist->members[i]->tuple;
219 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
222 if (aform->amopmethod != BTREE_AM_OID)
225 if (aform->amopstrategy == BTLessStrategyNumber ||
226 aform->amopstrategy == BTGreaterStrategyNumber)
228 /* Found it ... should have consistent input types */
229 if (aform->amoplefttype == aform->amoprighttype)
231 /* Found a suitable opfamily, return info */
232 *opfamily = aform->amopfamily;
233 *opcintype = aform->amoplefttype;
234 *strategy = aform->amopstrategy;
241 ReleaseSysCacheList(catlist);
247 * get_compare_function_for_ordering_op
248 * Get the OID of the datatype-specific btree comparison function
249 * associated with an ordering operator (a "<" or ">" operator).
251 * *cmpfunc receives the comparison function OID.
252 * *reverse is set FALSE if the operator is "<", TRUE if it's ">"
253 * (indicating the comparison result must be negated before use).
255 * Returns TRUE if successful, FALSE if no btree function can be found.
256 * (This indicates that the operator is not a valid ordering operator.)
259 get_compare_function_for_ordering_op(Oid opno, Oid *cmpfunc, bool *reverse)
265 /* Find the operator in pg_amop */
266 if (get_ordering_op_properties(opno,
267 &opfamily, &opcintype, &strategy))
269 /* Found a suitable opfamily, get matching support function */
270 *cmpfunc = get_opfamily_proc(opfamily,
275 if (!OidIsValid(*cmpfunc)) /* should not happen */
276 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
277 BTORDER_PROC, opcintype, opcintype, opfamily);
278 *reverse = (strategy == BTGreaterStrategyNumber);
282 /* ensure outputs are set on failure */
283 *cmpfunc = InvalidOid;
290 * get_equality_op_for_ordering_op
291 * Get the OID of the datatype-specific btree equality operator
292 * associated with an ordering operator (a "<" or ">" operator).
294 * If "reverse" isn't NULL, also set *reverse to FALSE if the operator is "<",
297 * Returns InvalidOid if no matching equality operator can be found.
298 * (This indicates that the operator is not a valid ordering operator.)
301 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
303 Oid result = InvalidOid;
308 /* Find the operator in pg_amop */
309 if (get_ordering_op_properties(opno,
310 &opfamily, &opcintype, &strategy))
312 /* Found a suitable opfamily, get matching equality operator */
313 result = get_opfamily_member(opfamily,
316 BTEqualStrategyNumber);
318 *reverse = (strategy == BTGreaterStrategyNumber);
325 * get_ordering_op_for_equality_op
326 * Get the OID of a datatype-specific btree ordering operator
327 * associated with an equality operator. (If there are multiple
328 * possibilities, assume any one will do.)
330 * This function is used when we have to sort data before unique-ifying,
331 * and don't much care which sorting op is used as long as it's compatible
332 * with the intended equality operator. Since we need a sorting operator,
333 * it should be single-data-type even if the given operator is cross-type.
334 * The caller specifies whether to find an op for the LHS or RHS data type.
336 * Returns InvalidOid if no matching ordering operator can be found.
339 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
341 Oid result = InvalidOid;
346 * Search pg_amop to see if the target operator is registered as the "="
347 * operator of any btree opfamily.
349 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
351 for (i = 0; i < catlist->n_members; i++)
353 HeapTuple tuple = &catlist->members[i]->tuple;
354 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
357 if (aform->amopmethod != BTREE_AM_OID)
360 if (aform->amopstrategy == BTEqualStrategyNumber)
362 /* Found a suitable opfamily, get matching ordering operator */
365 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
366 result = get_opfamily_member(aform->amopfamily,
368 BTLessStrategyNumber);
369 if (OidIsValid(result))
371 /* failure probably shouldn't happen, but keep looking if so */
375 ReleaseSysCacheList(catlist);
381 * get_mergejoin_opfamilies
382 * Given a putatively mergejoinable operator, return a list of the OIDs
383 * of the btree opfamilies in which it represents equality.
385 * It is possible (though at present unusual) for an operator to be equality
386 * in more than one opfamily, hence the result is a list. This also lets us
387 * return NIL if the operator is not found in any opfamilies.
389 * The planner currently uses simple equal() tests to compare the lists
390 * returned by this function, which makes the list order relevant, though
391 * strictly speaking it should not be. Because of the way syscache list
392 * searches are handled, in normal operation the result will be sorted by OID
393 * so everything works fine. If running with system index usage disabled,
394 * the result ordering is unspecified and hence the planner might fail to
395 * recognize optimization opportunities ... but that's hardly a scenario in
396 * which performance is good anyway, so there's no point in expending code
397 * or cycles here to guarantee the ordering in that case.
400 get_mergejoin_opfamilies(Oid opno)
407 * Search pg_amop to see if the target operator is registered as the "="
408 * operator of any btree opfamily.
410 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
412 for (i = 0; i < catlist->n_members; i++)
414 HeapTuple tuple = &catlist->members[i]->tuple;
415 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
417 /* must be btree equality */
418 if (aform->amopmethod == BTREE_AM_OID &&
419 aform->amopstrategy == BTEqualStrategyNumber)
420 result = lappend_oid(result, aform->amopfamily);
423 ReleaseSysCacheList(catlist);
429 * get_compatible_hash_operators
430 * Get the OID(s) of hash equality operator(s) compatible with the given
431 * operator, but operating on its LHS and/or RHS datatype.
433 * An operator for the LHS type is sought and returned into *lhs_opno if
434 * lhs_opno isn't NULL. Similarly, an operator for the RHS type is sought
435 * and returned into *rhs_opno if rhs_opno isn't NULL.
437 * If the given operator is not cross-type, the results should be the same
438 * operator, but in cross-type situations they will be different.
440 * Returns true if able to find the requested operator(s), false if not.
441 * (This indicates that the operator should not have been marked oprcanhash.)
444 get_compatible_hash_operators(Oid opno,
445 Oid *lhs_opno, Oid *rhs_opno)
451 /* Ensure output args are initialized on failure */
453 *lhs_opno = InvalidOid;
455 *rhs_opno = InvalidOid;
458 * Search pg_amop to see if the target operator is registered as the "="
459 * operator of any hash opfamily. If the operator is registered in
460 * multiple opfamilies, assume we can use any one.
462 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
464 for (i = 0; i < catlist->n_members; i++)
466 HeapTuple tuple = &catlist->members[i]->tuple;
467 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
469 if (aform->amopmethod == HASH_AM_OID &&
470 aform->amopstrategy == HTEqualStrategyNumber)
472 /* No extra lookup needed if given operator is single-type */
473 if (aform->amoplefttype == aform->amoprighttype)
484 * Get the matching single-type operator(s). Failure probably
485 * shouldn't happen --- it implies a bogus opfamily --- but
486 * continue looking if so.
490 *lhs_opno = get_opfamily_member(aform->amopfamily,
493 HTEqualStrategyNumber);
494 if (!OidIsValid(*lhs_opno))
496 /* Matching LHS found, done if caller doesn't want RHS */
505 *rhs_opno = get_opfamily_member(aform->amopfamily,
506 aform->amoprighttype,
507 aform->amoprighttype,
508 HTEqualStrategyNumber);
509 if (!OidIsValid(*rhs_opno))
511 /* Forget any LHS operator from this opfamily */
513 *lhs_opno = InvalidOid;
516 /* Matching RHS found, so done */
523 ReleaseSysCacheList(catlist);
529 * get_op_hash_functions
530 * Get the OID(s) of hash support function(s) compatible with the given
531 * operator, operating on its LHS and/or RHS datatype as required.
533 * A function for the LHS type is sought and returned into *lhs_procno if
534 * lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
535 * and returned into *rhs_procno if rhs_procno isn't NULL.
537 * If the given operator is not cross-type, the results should be the same
538 * function, but in cross-type situations they will be different.
540 * Returns true if able to find the requested function(s), false if not.
541 * (This indicates that the operator should not have been marked oprcanhash.)
544 get_op_hash_functions(Oid opno,
545 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
551 /* Ensure output args are initialized on failure */
553 *lhs_procno = InvalidOid;
555 *rhs_procno = InvalidOid;
558 * Search pg_amop to see if the target operator is registered as the "="
559 * operator of any hash opfamily. If the operator is registered in
560 * multiple opfamilies, assume we can use any one.
562 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
564 for (i = 0; i < catlist->n_members; i++)
566 HeapTuple tuple = &catlist->members[i]->tuple;
567 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
569 if (aform->amopmethod == HASH_AM_OID &&
570 aform->amopstrategy == HTEqualStrategyNumber)
573 * Get the matching support function(s). Failure probably
574 * shouldn't happen --- it implies a bogus opfamily --- but
575 * continue looking if so.
579 *lhs_procno = get_opfamily_proc(aform->amopfamily,
583 if (!OidIsValid(*lhs_procno))
585 /* Matching LHS found, done if caller doesn't want RHS */
591 /* Only one lookup needed if given operator is single-type */
592 if (aform->amoplefttype == aform->amoprighttype)
594 *rhs_procno = *lhs_procno;
601 *rhs_procno = get_opfamily_proc(aform->amopfamily,
602 aform->amoprighttype,
603 aform->amoprighttype,
605 if (!OidIsValid(*rhs_procno))
607 /* Forget any LHS function from this opfamily */
609 *lhs_procno = InvalidOid;
612 /* Matching RHS found, so done */
619 ReleaseSysCacheList(catlist);
625 * get_op_btree_interpretation
626 * Given an operator's OID, find out which btree opfamilies it belongs to,
627 * and what properties it has within each one. The results are returned
628 * as a palloc'd list of OpBtreeInterpretation structs.
630 * In addition to the normal btree operators, we consider a <> operator to be
631 * a "member" of an opfamily if its negator is an equality operator of the
632 * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case.
635 get_op_btree_interpretation(Oid opno)
638 OpBtreeInterpretation *thisresult;
643 * Find all the pg_amop entries containing the operator.
645 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
647 for (i = 0; i < catlist->n_members; i++)
649 HeapTuple op_tuple = &catlist->members[i]->tuple;
650 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
651 StrategyNumber op_strategy;
654 if (op_form->amopmethod != BTREE_AM_OID)
657 /* Get the operator's btree strategy number */
658 op_strategy = (StrategyNumber) op_form->amopstrategy;
659 Assert(op_strategy >= 1 && op_strategy <= 5);
661 thisresult = (OpBtreeInterpretation *)
662 palloc(sizeof(OpBtreeInterpretation));
663 thisresult->opfamily_id = op_form->amopfamily;
664 thisresult->strategy = op_strategy;
665 thisresult->oplefttype = op_form->amoplefttype;
666 thisresult->oprighttype = op_form->amoprighttype;
667 result = lappend(result, thisresult);
670 ReleaseSysCacheList(catlist);
673 * If we didn't find any btree opfamily containing the operator, perhaps
674 * it is a <> operator. See if it has a negator that is in an opfamily.
678 Oid op_negator = get_negator(opno);
680 if (OidIsValid(op_negator))
682 catlist = SearchSysCacheList1(AMOPOPID,
683 ObjectIdGetDatum(op_negator));
685 for (i = 0; i < catlist->n_members; i++)
687 HeapTuple op_tuple = &catlist->members[i]->tuple;
688 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
689 StrategyNumber op_strategy;
692 if (op_form->amopmethod != BTREE_AM_OID)
695 /* Get the operator's btree strategy number */
696 op_strategy = (StrategyNumber) op_form->amopstrategy;
697 Assert(op_strategy >= 1 && op_strategy <= 5);
699 /* Only consider negators that are = */
700 if (op_strategy != BTEqualStrategyNumber)
703 /* OK, report it with "strategy" ROWCOMPARE_NE */
704 thisresult = (OpBtreeInterpretation *)
705 palloc(sizeof(OpBtreeInterpretation));
706 thisresult->opfamily_id = op_form->amopfamily;
707 thisresult->strategy = ROWCOMPARE_NE;
708 thisresult->oplefttype = op_form->amoplefttype;
709 thisresult->oprighttype = op_form->amoprighttype;
710 result = lappend(result, thisresult);
713 ReleaseSysCacheList(catlist);
721 * equality_ops_are_compatible
722 * Return TRUE if the two given equality operators have compatible
725 * This is trivially true if they are the same operator. Otherwise,
726 * we look to see if they can be found in the same btree or hash opfamily.
727 * Either finding allows us to assume that they have compatible notions
728 * of equality. (The reason we need to do these pushups is that one might
729 * be a cross-type operator; for instance int24eq vs int4eq.)
732 equality_ops_are_compatible(Oid opno1, Oid opno2)
738 /* Easy if they're the same operator */
743 * We search through all the pg_amop entries for opno1.
745 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
748 for (i = 0; i < catlist->n_members; i++)
750 HeapTuple op_tuple = &catlist->members[i]->tuple;
751 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
753 /* must be btree or hash */
754 if (op_form->amopmethod == BTREE_AM_OID ||
755 op_form->amopmethod == HASH_AM_OID)
757 if (op_in_opfamily(opno2, op_form->amopfamily))
765 ReleaseSysCacheList(catlist);
771 /* ---------- AMPROC CACHES ---------- */
775 * Get the OID of the specified support function
776 * for the specified opfamily and datatypes.
778 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
781 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
784 Form_pg_amproc amproc_tup;
787 tp = SearchSysCache4(AMPROCNUM,
788 ObjectIdGetDatum(opfamily),
789 ObjectIdGetDatum(lefttype),
790 ObjectIdGetDatum(righttype),
791 Int16GetDatum(procnum));
792 if (!HeapTupleIsValid(tp))
794 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
795 result = amproc_tup->amproc;
801 /* ---------- ATTRIBUTE CACHES ---------- */
805 * Given the relation id and the attribute number,
806 * return the "attname" field from the attribute relation.
808 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
811 get_attname(Oid relid, AttrNumber attnum)
815 tp = SearchSysCache2(ATTNUM,
816 ObjectIdGetDatum(relid),
817 Int16GetDatum(attnum));
818 if (HeapTupleIsValid(tp))
820 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
823 result = pstrdup(NameStr(att_tup->attname));
832 * get_relid_attribute_name
834 * Same as above routine get_attname(), except that error
835 * is handled by elog() instead of returning NULL.
838 get_relid_attribute_name(Oid relid, AttrNumber attnum)
842 attname = get_attname(relid, attnum);
844 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
852 * Given the relation id and the attribute name,
853 * return the "attnum" field from the attribute relation.
855 * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
858 get_attnum(Oid relid, const char *attname)
862 tp = SearchSysCacheAttName(relid, attname);
863 if (HeapTupleIsValid(tp))
865 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
868 result = att_tup->attnum;
873 return InvalidAttrNumber;
879 * Given the relation OID and the attribute number with the relation,
880 * return the attribute type OID.
883 get_atttype(Oid relid, AttrNumber attnum)
887 tp = SearchSysCache2(ATTNUM,
888 ObjectIdGetDatum(relid),
889 Int16GetDatum(attnum));
890 if (HeapTupleIsValid(tp))
892 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
895 result = att_tup->atttypid;
906 * Given the relation id and the attribute number,
907 * return the "atttypmod" field from the attribute relation.
910 get_atttypmod(Oid relid, AttrNumber attnum)
914 tp = SearchSysCache2(ATTNUM,
915 ObjectIdGetDatum(relid),
916 Int16GetDatum(attnum));
917 if (HeapTupleIsValid(tp))
919 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
922 result = att_tup->atttypmod;
931 * get_atttypetypmodcoll
933 * A three-fer: given the relation id and the attribute number,
934 * fetch atttypid, atttypmod, and attcollation in a single cache lookup.
936 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
937 * raises an error if it can't obtain the information.
940 get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
941 Oid *typid, int32 *typmod, Oid *collid)
944 Form_pg_attribute att_tup;
946 tp = SearchSysCache2(ATTNUM,
947 ObjectIdGetDatum(relid),
948 Int16GetDatum(attnum));
949 if (!HeapTupleIsValid(tp))
950 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
952 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
954 *typid = att_tup->atttypid;
955 *typmod = att_tup->atttypmod;
956 *collid = att_tup->attcollation;
960 /* ---------- COLLATION CACHE ---------- */
964 * Returns the name of a given pg_collation entry.
966 * Returns a palloc'd copy of the string, or NULL if no such constraint.
968 * NOTE: since collation name is not unique, be wary of code that uses this
969 * for anything except preparing error messages.
972 get_collation_name(Oid colloid)
976 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
977 if (HeapTupleIsValid(tp))
979 Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
982 result = pstrdup(NameStr(colltup->collname));
990 /* ---------- CONSTRAINT CACHE ---------- */
993 * get_constraint_name
994 * Returns the name of a given pg_constraint entry.
996 * Returns a palloc'd copy of the string, or NULL if no such constraint.
998 * NOTE: since constraint name is not unique, be wary of code that uses this
999 * for anything except preparing error messages.
1002 get_constraint_name(Oid conoid)
1006 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
1007 if (HeapTupleIsValid(tp))
1009 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
1012 result = pstrdup(NameStr(contup->conname));
1013 ReleaseSysCache(tp);
1020 /* ---------- OPCLASS CACHE ---------- */
1023 * get_opclass_family
1025 * Returns the OID of the operator family the opclass belongs to.
1028 get_opclass_family(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->opcfamily;
1040 ReleaseSysCache(tp);
1045 * get_opclass_input_type
1047 * Returns the OID of the datatype the opclass indexes.
1050 get_opclass_input_type(Oid opclass)
1053 Form_pg_opclass cla_tup;
1056 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1057 if (!HeapTupleIsValid(tp))
1058 elog(ERROR, "cache lookup failed for opclass %u", opclass);
1059 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
1061 result = cla_tup->opcintype;
1062 ReleaseSysCache(tp);
1066 /* ---------- OPERATOR CACHE ---------- */
1071 * Returns the regproc id of the routine used to implement an
1072 * operator given the operator oid.
1075 get_opcode(Oid opno)
1079 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1080 if (HeapTupleIsValid(tp))
1082 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1083 RegProcedure result;
1085 result = optup->oprcode;
1086 ReleaseSysCache(tp);
1090 return (RegProcedure) InvalidOid;
1095 * returns the name of the operator with the given opno
1097 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
1100 get_opname(Oid opno)
1104 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1105 if (HeapTupleIsValid(tp))
1107 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1110 result = pstrdup(NameStr(optup->oprname));
1111 ReleaseSysCache(tp);
1121 * Returns the left and right input datatypes for an operator
1122 * (InvalidOid if not relevant).
1125 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
1128 Form_pg_operator optup;
1130 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1131 if (!HeapTupleIsValid(tp)) /* shouldn't happen */
1132 elog(ERROR, "cache lookup failed for operator %u", opno);
1133 optup = (Form_pg_operator) GETSTRUCT(tp);
1134 *lefttype = optup->oprleft;
1135 *righttype = optup->oprright;
1136 ReleaseSysCache(tp);
1142 * Returns true if the operator is potentially mergejoinable. (The planner
1143 * will fail to find any mergejoin plans unless there are suitable btree
1144 * opfamily entries for this operator and associated sortops. The pg_operator
1145 * flag is just a hint to tell the planner whether to bother looking.)
1147 * In some cases (currently only array_eq and record_eq), mergejoinability
1148 * depends on the specific input data type the operator is invoked for, so
1149 * that must be passed as well. We currently assume that only one input's type
1150 * is needed to check this --- by convention, pass the left input's data type.
1153 op_mergejoinable(Oid opno, Oid inputtype)
1155 bool result = false;
1157 TypeCacheEntry *typentry;
1160 * For array_eq or record_eq, we can sort if the element or field types
1161 * are all sortable. We could implement all the checks for that here, but
1162 * the typcache already does that and caches the results too, so let's
1163 * rely on the typcache.
1165 if (opno == ARRAY_EQ_OP)
1167 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1168 if (typentry->cmp_proc == F_BTARRAYCMP)
1171 else if (opno == RECORD_EQ_OP)
1173 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
1174 if (typentry->cmp_proc == F_BTRECORDCMP)
1179 /* For all other operators, rely on pg_operator.oprcanmerge */
1180 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1181 if (HeapTupleIsValid(tp))
1183 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1185 result = optup->oprcanmerge;
1186 ReleaseSysCache(tp);
1195 * Returns true if the operator is hashjoinable. (There must be a suitable
1196 * hash opfamily entry for this operator if it is so marked.)
1198 * In some cases (currently only array_eq), hashjoinability depends on the
1199 * specific input data type the operator is invoked for, so that must be
1200 * passed as well. We currently assume that only one input's type is needed
1201 * to check this --- by convention, pass the left input's data type.
1204 op_hashjoinable(Oid opno, Oid inputtype)
1206 bool result = false;
1208 TypeCacheEntry *typentry;
1210 /* As in op_mergejoinable, let the typcache handle the hard cases */
1211 /* Eventually we'll need a similar case for record_eq ... */
1212 if (opno == ARRAY_EQ_OP)
1214 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
1215 if (typentry->hash_proc == F_HASH_ARRAY)
1220 /* For all other operators, rely on pg_operator.oprcanhash */
1221 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1222 if (HeapTupleIsValid(tp))
1224 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1226 result = optup->oprcanhash;
1227 ReleaseSysCache(tp);
1236 * Get the proisstrict flag for the operator's underlying function.
1241 RegProcedure funcid = get_opcode(opno);
1243 if (funcid == (RegProcedure) InvalidOid)
1244 elog(ERROR, "operator %u does not exist", opno);
1246 return func_strict((Oid) funcid);
1252 * Get the provolatile flag for the operator's underlying function.
1255 op_volatile(Oid opno)
1257 RegProcedure funcid = get_opcode(opno);
1259 if (funcid == (RegProcedure) InvalidOid)
1260 elog(ERROR, "operator %u does not exist", opno);
1262 return func_volatile((Oid) funcid);
1268 * Returns the corresponding commutator of an operator.
1271 get_commutator(Oid opno)
1275 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1276 if (HeapTupleIsValid(tp))
1278 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1281 result = optup->oprcom;
1282 ReleaseSysCache(tp);
1292 * Returns the corresponding negator of an operator.
1295 get_negator(Oid opno)
1299 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1300 if (HeapTupleIsValid(tp))
1302 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1305 result = optup->oprnegate;
1306 ReleaseSysCache(tp);
1316 * Returns procedure id for computing selectivity of an operator.
1319 get_oprrest(Oid opno)
1323 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1324 if (HeapTupleIsValid(tp))
1326 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1327 RegProcedure result;
1329 result = optup->oprrest;
1330 ReleaseSysCache(tp);
1334 return (RegProcedure) InvalidOid;
1340 * Returns procedure id for computing selectivity of a join.
1343 get_oprjoin(Oid opno)
1347 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
1348 if (HeapTupleIsValid(tp))
1350 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
1351 RegProcedure result;
1353 result = optup->oprjoin;
1354 ReleaseSysCache(tp);
1358 return (RegProcedure) InvalidOid;
1361 /* ---------- FUNCTION CACHE ---------- */
1365 * returns the name of the function with the given funcid
1367 * Note: returns a palloc'd copy of the string, or NULL if no such function.
1370 get_func_name(Oid funcid)
1374 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1375 if (HeapTupleIsValid(tp))
1377 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1380 result = pstrdup(NameStr(functup->proname));
1381 ReleaseSysCache(tp);
1389 * get_func_namespace
1391 * Returns the pg_namespace OID associated with a given function.
1394 get_func_namespace(Oid funcid)
1398 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1399 if (HeapTupleIsValid(tp))
1401 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
1404 result = functup->pronamespace;
1405 ReleaseSysCache(tp);
1414 * Given procedure id, return the function's result type.
1417 get_func_rettype(Oid funcid)
1422 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1423 if (!HeapTupleIsValid(tp))
1424 elog(ERROR, "cache lookup failed for function %u", funcid);
1426 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
1427 ReleaseSysCache(tp);
1433 * Given procedure id, return the number of arguments.
1436 get_func_nargs(Oid funcid)
1441 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1442 if (!HeapTupleIsValid(tp))
1443 elog(ERROR, "cache lookup failed for function %u", funcid);
1445 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
1446 ReleaseSysCache(tp);
1451 * get_func_signature
1452 * Given procedure id, return the function's argument and result types.
1453 * (The return value is the result type.)
1455 * The arguments are returned as a palloc'd array.
1458 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
1461 Form_pg_proc procstruct;
1464 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1465 if (!HeapTupleIsValid(tp))
1466 elog(ERROR, "cache lookup failed for function %u", funcid);
1468 procstruct = (Form_pg_proc) GETSTRUCT(tp);
1470 result = procstruct->prorettype;
1471 *nargs = (int) procstruct->pronargs;
1472 Assert(*nargs == procstruct->proargtypes.dim1);
1473 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
1474 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
1476 ReleaseSysCache(tp);
1482 * Given procedure id, return the function's proretset flag.
1485 get_func_retset(Oid funcid)
1490 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1491 if (!HeapTupleIsValid(tp))
1492 elog(ERROR, "cache lookup failed for function %u", funcid);
1494 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
1495 ReleaseSysCache(tp);
1501 * Given procedure id, return the function's proisstrict flag.
1504 func_strict(Oid funcid)
1509 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1510 if (!HeapTupleIsValid(tp))
1511 elog(ERROR, "cache lookup failed for function %u", funcid);
1513 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
1514 ReleaseSysCache(tp);
1520 * Given procedure id, return the function's provolatile flag.
1523 func_volatile(Oid funcid)
1528 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1529 if (!HeapTupleIsValid(tp))
1530 elog(ERROR, "cache lookup failed for function %u", funcid);
1532 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
1533 ReleaseSysCache(tp);
1539 * Given procedure id, return the function's procost field.
1542 get_func_cost(Oid funcid)
1547 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1548 if (!HeapTupleIsValid(tp))
1549 elog(ERROR, "cache lookup failed for function %u", funcid);
1551 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
1552 ReleaseSysCache(tp);
1558 * Given procedure id, return the function's prorows field.
1561 get_func_rows(Oid funcid)
1566 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1567 if (!HeapTupleIsValid(tp))
1568 elog(ERROR, "cache lookup failed for function %u", funcid);
1570 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
1571 ReleaseSysCache(tp);
1575 /* ---------- RELATION CACHE ---------- */
1579 * Given name and namespace of a relation, look up the OID.
1581 * Returns InvalidOid if there is no such relation.
1584 get_relname_relid(const char *relname, Oid relnamespace)
1586 return GetSysCacheOid2(RELNAMENSP,
1587 PointerGetDatum(relname),
1588 ObjectIdGetDatum(relnamespace));
1595 * Returns the number of attributes for a given relation.
1598 get_relnatts(Oid relid)
1602 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1603 if (HeapTupleIsValid(tp))
1605 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1608 result = reltup->relnatts;
1609 ReleaseSysCache(tp);
1613 return InvalidAttrNumber;
1619 * Returns the name of a given relation.
1621 * Returns a palloc'd copy of the string, or NULL if no such relation.
1623 * NOTE: since relation name is not unique, be wary of code that uses this
1624 * for anything except preparing error messages.
1627 get_rel_name(Oid relid)
1631 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1632 if (HeapTupleIsValid(tp))
1634 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1637 result = pstrdup(NameStr(reltup->relname));
1638 ReleaseSysCache(tp);
1648 * Returns the pg_namespace OID associated with a given relation.
1651 get_rel_namespace(Oid relid)
1655 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1656 if (HeapTupleIsValid(tp))
1658 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1661 result = reltup->relnamespace;
1662 ReleaseSysCache(tp);
1672 * Returns the pg_type OID associated with a given relation.
1674 * Note: not all pg_class entries have associated pg_type OIDs; so be
1675 * careful to check for InvalidOid result.
1678 get_rel_type_id(Oid relid)
1682 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1683 if (HeapTupleIsValid(tp))
1685 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1688 result = reltup->reltype;
1689 ReleaseSysCache(tp);
1699 * Returns the relkind associated with a given relation.
1702 get_rel_relkind(Oid relid)
1706 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1707 if (HeapTupleIsValid(tp))
1709 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1712 result = reltup->relkind;
1713 ReleaseSysCache(tp);
1721 * get_rel_tablespace
1723 * Returns the pg_tablespace OID associated with a given relation.
1725 * Note: InvalidOid might mean either that we couldn't find the relation,
1726 * or that it is in the database's default tablespace.
1729 get_rel_tablespace(Oid relid)
1733 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1734 if (HeapTupleIsValid(tp))
1736 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
1739 result = reltup->reltablespace;
1740 ReleaseSysCache(tp);
1748 /* ---------- TYPE CACHE ---------- */
1753 * Given the type OID, determine whether the type is defined
1754 * (if not, it's only a shell).
1757 get_typisdefined(Oid typid)
1761 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1762 if (HeapTupleIsValid(tp))
1764 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1767 result = typtup->typisdefined;
1768 ReleaseSysCache(tp);
1778 * Given the type OID, return the length of the type.
1781 get_typlen(Oid typid)
1785 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1786 if (HeapTupleIsValid(tp))
1788 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1791 result = typtup->typlen;
1792 ReleaseSysCache(tp);
1802 * Given the type OID, determine whether the type is returned by value or
1803 * not. Returns true if by value, false if by reference.
1806 get_typbyval(Oid typid)
1810 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1811 if (HeapTupleIsValid(tp))
1813 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1816 result = typtup->typbyval;
1817 ReleaseSysCache(tp);
1827 * A two-fer: given the type OID, return both typlen and typbyval.
1829 * Since both pieces of info are needed to know how to copy a Datum,
1830 * many places need both. Might as well get them with one cache lookup
1831 * instead of two. Also, this routine raises an error instead of
1832 * returning a bogus value when given a bad type OID.
1835 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
1838 Form_pg_type typtup;
1840 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1841 if (!HeapTupleIsValid(tp))
1842 elog(ERROR, "cache lookup failed for type %u", typid);
1843 typtup = (Form_pg_type) GETSTRUCT(tp);
1844 *typlen = typtup->typlen;
1845 *typbyval = typtup->typbyval;
1846 ReleaseSysCache(tp);
1850 * get_typlenbyvalalign
1852 * A three-fer: given the type OID, return typlen, typbyval, typalign.
1855 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
1859 Form_pg_type typtup;
1861 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1862 if (!HeapTupleIsValid(tp))
1863 elog(ERROR, "cache lookup failed for type %u", typid);
1864 typtup = (Form_pg_type) GETSTRUCT(tp);
1865 *typlen = typtup->typlen;
1866 *typbyval = typtup->typbyval;
1867 *typalign = typtup->typalign;
1868 ReleaseSysCache(tp);
1873 * Given a pg_type row, select the type OID to pass to I/O functions
1875 * Formerly, all I/O functions were passed pg_type.typelem as their second
1876 * parameter, but we now have a more complex rule about what to pass.
1877 * This knowledge is intended to be centralized here --- direct references
1878 * to typelem elsewhere in the code are wrong, if they are associated with
1879 * I/O calls and not with actual subscripting operations! (But see
1880 * bootstrap.c's boot_get_type_io_data() if you need to change this.)
1882 * As of PostgreSQL 8.1, output functions receive only the value itself
1883 * and not any auxiliary parameters, so the name of this routine is now
1884 * a bit of a misnomer ... it should be getTypeInputParam.
1887 getTypeIOParam(HeapTuple typeTuple)
1889 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1892 * Array types get their typelem as parameter; everybody else gets their
1893 * own type OID as parameter.
1895 if (OidIsValid(typeStruct->typelem))
1896 return typeStruct->typelem;
1898 return HeapTupleGetOid(typeTuple);
1904 * A six-fer: given the type OID, return typlen, typbyval, typalign,
1905 * typdelim, typioparam, and IO function OID. The IO function
1906 * returned is controlled by IOFuncSelector
1909 get_type_io_data(Oid typid,
1910 IOFuncSelector which_func,
1918 HeapTuple typeTuple;
1919 Form_pg_type typeStruct;
1922 * In bootstrap mode, pass it off to bootstrap.c. This hack allows us to
1923 * use array_in and array_out during bootstrap.
1925 if (IsBootstrapProcessingMode())
1930 boot_get_type_io_data(typid,
1947 elog(ERROR, "binary I/O not supported during bootstrap");
1953 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1954 if (!HeapTupleIsValid(typeTuple))
1955 elog(ERROR, "cache lookup failed for type %u", typid);
1956 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1958 *typlen = typeStruct->typlen;
1959 *typbyval = typeStruct->typbyval;
1960 *typalign = typeStruct->typalign;
1961 *typdelim = typeStruct->typdelim;
1962 *typioparam = getTypeIOParam(typeTuple);
1966 *func = typeStruct->typinput;
1969 *func = typeStruct->typoutput;
1971 case IOFunc_receive:
1972 *func = typeStruct->typreceive;
1975 *func = typeStruct->typsend;
1978 ReleaseSysCache(typeTuple);
1983 get_typalign(Oid typid)
1987 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
1988 if (HeapTupleIsValid(tp))
1990 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
1993 result = typtup->typalign;
1994 ReleaseSysCache(tp);
2003 get_typstorage(Oid typid)
2007 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2008 if (HeapTupleIsValid(tp))
2010 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2013 result = typtup->typstorage;
2014 ReleaseSysCache(tp);
2023 * Given a type OID, return the type's default value, if any.
2025 * The result is a palloc'd expression node tree, or NULL if there
2026 * is no defined default for the datatype.
2028 * NB: caller should be prepared to coerce result to correct datatype;
2029 * the returned expression tree might produce something of the wrong type.
2032 get_typdefault(Oid typid)
2034 HeapTuple typeTuple;
2040 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2041 if (!HeapTupleIsValid(typeTuple))
2042 elog(ERROR, "cache lookup failed for type %u", typid);
2043 type = (Form_pg_type) GETSTRUCT(typeTuple);
2046 * typdefault and typdefaultbin are potentially null, so don't try to
2047 * access 'em as struct fields. Must do it the hard way with
2050 datum = SysCacheGetAttr(TYPEOID,
2052 Anum_pg_type_typdefaultbin,
2057 /* We have an expression default */
2058 expr = stringToNode(TextDatumGetCString(datum));
2062 /* Perhaps we have a plain literal default */
2063 datum = SysCacheGetAttr(TYPEOID,
2065 Anum_pg_type_typdefault,
2070 char *strDefaultVal;
2072 /* Convert text datum to C string */
2073 strDefaultVal = TextDatumGetCString(datum);
2074 /* Convert C string to a value of the given type */
2075 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
2076 getTypeIOParam(typeTuple), -1);
2077 /* Build a Const node containing the value */
2078 expr = (Node *) makeConst(typid,
2085 pfree(strDefaultVal);
2094 ReleaseSysCache(typeTuple);
2101 * If the given type is a domain, return its base type;
2102 * otherwise return the type's own OID.
2105 getBaseType(Oid typid)
2109 return getBaseTypeAndTypmod(typid, &typmod);
2113 * getBaseTypeAndTypmod
2114 * If the given type is a domain, return its base type and typmod;
2115 * otherwise return the type's own OID, and leave *typmod unchanged.
2117 * Note that the "applied typmod" should be -1 for every domain level
2118 * above the bottommost; therefore, if the passed-in typid is indeed
2119 * a domain, *typmod should be -1.
2122 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
2125 * We loop to find the bottom base type in a stack of domains.
2130 Form_pg_type typTup;
2132 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2133 if (!HeapTupleIsValid(tup))
2134 elog(ERROR, "cache lookup failed for type %u", typid);
2135 typTup = (Form_pg_type) GETSTRUCT(tup);
2136 if (typTup->typtype != TYPTYPE_DOMAIN)
2138 /* Not a domain, so done */
2139 ReleaseSysCache(tup);
2143 Assert(*typmod == -1);
2144 typid = typTup->typbasetype;
2145 *typmod = typTup->typtypmod;
2147 ReleaseSysCache(tup);
2156 * Given a type OID and a typmod value (pass -1 if typmod is unknown),
2157 * estimate the average width of values of the type. This is used by
2158 * the planner, which doesn't require absolutely correct results;
2159 * it's OK (and expected) to guess if we don't know for sure.
2162 get_typavgwidth(Oid typid, int32 typmod)
2164 int typlen = get_typlen(typid);
2168 * Easy if it's a fixed-width type
2174 * type_maximum_size knows the encoding of typmod for some datatypes;
2175 * don't duplicate that knowledge here.
2177 maxwidth = type_maximum_size(typid, typmod);
2181 * For BPCHAR, the max width is also the only width. Otherwise we
2182 * need to guess about the typical data width given the max. A sliding
2183 * scale for percentage of max width seems reasonable.
2185 if (typid == BPCHAROID)
2188 return maxwidth; /* assume full width */
2189 if (maxwidth < 1000)
2190 return 32 + (maxwidth - 32) / 2; /* assume 50% */
2193 * Beyond 1000, assume we're looking at something like
2194 * "varchar(10000)" where the limit isn't actually reached often, and
2195 * use a fixed estimate.
2197 return 32 + (1000 - 32) / 2;
2201 * Ooops, we have no idea ... wild guess time.
2209 * Given the type OID, find if it is a basic type, a complex type, etc.
2210 * It returns the null char if the cache lookup fails...
2213 get_typtype(Oid typid)
2217 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2218 if (HeapTupleIsValid(tp))
2220 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2223 result = typtup->typtype;
2224 ReleaseSysCache(tp);
2234 * Convenience function to determine whether a type OID represents
2235 * a "rowtype" type --- either RECORD or a named composite type.
2238 type_is_rowtype(Oid typid)
2240 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
2245 * Returns true if the given type is an enum type.
2248 type_is_enum(Oid typid)
2250 return (get_typtype(typid) == TYPTYPE_ENUM);
2255 * Returns true if the given type is a range type.
2258 type_is_range(Oid typid)
2260 return (get_typtype(typid) == TYPTYPE_RANGE);
2264 * get_type_category_preferred
2266 * Given the type OID, fetch its category and preferred-type status.
2267 * Throws error on failure.
2270 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
2273 Form_pg_type typtup;
2275 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2276 if (!HeapTupleIsValid(tp))
2277 elog(ERROR, "cache lookup failed for type %u", typid);
2278 typtup = (Form_pg_type) GETSTRUCT(tp);
2279 *typcategory = typtup->typcategory;
2280 *typispreferred = typtup->typispreferred;
2281 ReleaseSysCache(tp);
2287 * Given the type OID, get the typrelid (InvalidOid if not a complex
2291 get_typ_typrelid(Oid typid)
2295 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2296 if (HeapTupleIsValid(tp))
2298 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2301 result = typtup->typrelid;
2302 ReleaseSysCache(tp);
2312 * Given the type OID, get the typelem (InvalidOid if not an array type).
2314 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
2315 * returned if the input is a fixed-length array type.
2318 get_element_type(Oid typid)
2322 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2323 if (HeapTupleIsValid(tp))
2325 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2328 if (typtup->typlen == -1)
2329 result = typtup->typelem;
2331 result = InvalidOid;
2332 ReleaseSysCache(tp);
2342 * Given the type OID, get the corresponding "true" array type.
2343 * Returns InvalidOid if no array type can be found.
2346 get_array_type(Oid typid)
2349 Oid result = InvalidOid;
2351 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2352 if (HeapTupleIsValid(tp))
2354 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
2355 ReleaseSysCache(tp);
2361 * get_base_element_type
2362 * Given the type OID, get the typelem, looking "through" any domain
2363 * to its underlying array type.
2365 * This is equivalent to get_element_type(getBaseType(typid)), but avoids
2366 * an extra cache lookup. Note that it fails to provide any information
2367 * about the typmod of the array.
2370 get_base_element_type(Oid typid)
2373 * We loop to find the bottom base type in a stack of domains.
2378 Form_pg_type typTup;
2380 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2381 if (!HeapTupleIsValid(tup))
2383 typTup = (Form_pg_type) GETSTRUCT(tup);
2384 if (typTup->typtype != TYPTYPE_DOMAIN)
2386 /* Not a domain, so stop descending */
2389 /* This test must match get_element_type */
2390 if (typTup->typlen == -1)
2391 result = typTup->typelem;
2393 result = InvalidOid;
2394 ReleaseSysCache(tup);
2398 typid = typTup->typbasetype;
2399 ReleaseSysCache(tup);
2402 /* Like get_element_type, silently return InvalidOid for bogus input */
2409 * Get info needed for converting values of a type to internal form
2412 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
2414 HeapTuple typeTuple;
2417 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2418 if (!HeapTupleIsValid(typeTuple))
2419 elog(ERROR, "cache lookup failed for type %u", type);
2420 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2422 if (!pt->typisdefined)
2424 (errcode(ERRCODE_UNDEFINED_OBJECT),
2425 errmsg("type %s is only a shell",
2426 format_type_be(type))));
2427 if (!OidIsValid(pt->typinput))
2429 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2430 errmsg("no input function available for type %s",
2431 format_type_be(type))));
2433 *typInput = pt->typinput;
2434 *typIOParam = getTypeIOParam(typeTuple);
2436 ReleaseSysCache(typeTuple);
2442 * Get info needed for printing values of a type
2445 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
2447 HeapTuple typeTuple;
2450 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2451 if (!HeapTupleIsValid(typeTuple))
2452 elog(ERROR, "cache lookup failed for type %u", type);
2453 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2455 if (!pt->typisdefined)
2457 (errcode(ERRCODE_UNDEFINED_OBJECT),
2458 errmsg("type %s is only a shell",
2459 format_type_be(type))));
2460 if (!OidIsValid(pt->typoutput))
2462 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2463 errmsg("no output function available for type %s",
2464 format_type_be(type))));
2466 *typOutput = pt->typoutput;
2467 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2469 ReleaseSysCache(typeTuple);
2473 * getTypeBinaryInputInfo
2475 * Get info needed for binary input of values of a type
2478 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
2480 HeapTuple typeTuple;
2483 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2484 if (!HeapTupleIsValid(typeTuple))
2485 elog(ERROR, "cache lookup failed for type %u", type);
2486 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2488 if (!pt->typisdefined)
2490 (errcode(ERRCODE_UNDEFINED_OBJECT),
2491 errmsg("type %s is only a shell",
2492 format_type_be(type))));
2493 if (!OidIsValid(pt->typreceive))
2495 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2496 errmsg("no binary input function available for type %s",
2497 format_type_be(type))));
2499 *typReceive = pt->typreceive;
2500 *typIOParam = getTypeIOParam(typeTuple);
2502 ReleaseSysCache(typeTuple);
2506 * getTypeBinaryOutputInfo
2508 * Get info needed for binary output of values of a type
2511 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
2513 HeapTuple typeTuple;
2516 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2517 if (!HeapTupleIsValid(typeTuple))
2518 elog(ERROR, "cache lookup failed for type %u", type);
2519 pt = (Form_pg_type) GETSTRUCT(typeTuple);
2521 if (!pt->typisdefined)
2523 (errcode(ERRCODE_UNDEFINED_OBJECT),
2524 errmsg("type %s is only a shell",
2525 format_type_be(type))));
2526 if (!OidIsValid(pt->typsend))
2528 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2529 errmsg("no binary output function available for type %s",
2530 format_type_be(type))));
2532 *typSend = pt->typsend;
2533 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
2535 ReleaseSysCache(typeTuple);
2541 * Given the type OID, return the type's typmodin procedure, if any.
2544 get_typmodin(Oid typid)
2548 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2549 if (HeapTupleIsValid(tp))
2551 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2554 result = typtup->typmodin;
2555 ReleaseSysCache(tp);
2566 * Given the type OID, return the type's typmodout procedure, if any.
2569 get_typmodout(Oid typid)
2573 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2574 if (HeapTupleIsValid(tp))
2576 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2579 result = typtup->typmodout;
2580 ReleaseSysCache(tp);
2586 #endif /* NOT_USED */
2591 * Given the type OID, return the type's typcollation attribute.
2594 get_typcollation(Oid typid)
2598 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2599 if (HeapTupleIsValid(tp))
2601 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
2604 result = typtup->typcollation;
2605 ReleaseSysCache(tp);
2614 * type_is_collatable
2616 * Return whether the type cares about collations
2619 type_is_collatable(Oid typid)
2621 return OidIsValid(get_typcollation(typid));
2625 /* ---------- STATISTICS CACHE ---------- */
2630 * Given the table and attribute number of a column, get the average
2631 * width of entries in the column. Return zero if no data available.
2633 * Currently this is only consulted for individual tables, not for inheritance
2634 * trees, so we don't need an "inh" parameter.
2636 * Calling a hook at this point looks somewhat strange, but is required
2637 * because the optimizer calls this function without any other way for
2638 * plug-ins to control the result.
2641 get_attavgwidth(Oid relid, AttrNumber attnum)
2646 if (get_attavgwidth_hook)
2648 stawidth = (*get_attavgwidth_hook) (relid, attnum);
2652 tp = SearchSysCache3(STATRELATTINH,
2653 ObjectIdGetDatum(relid),
2654 Int16GetDatum(attnum),
2655 BoolGetDatum(false));
2656 if (HeapTupleIsValid(tp))
2658 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
2659 ReleaseSysCache(tp);
2669 * Extract the contents of a "slot" of a pg_statistic tuple.
2670 * Returns TRUE if requested slot type was found, else FALSE.
2672 * Unlike other routines in this file, this takes a pointer to an
2673 * already-looked-up tuple in the pg_statistic cache. We do this since
2674 * most callers will want to extract more than one value from the cache
2675 * entry, and we don't want to repeat the cache lookup unnecessarily.
2676 * Also, this API allows this routine to be used with statistics tuples
2677 * that have been provided by a stats hook and didn't really come from
2680 * statstuple: pg_statistics tuple to be examined.
2681 * atttype: type OID of attribute (can be InvalidOid if values == NULL).
2682 * atttypmod: typmod of attribute (can be 0 if values == NULL).
2683 * reqkind: STAKIND code for desired statistics slot kind.
2684 * reqop: STAOP value wanted, or InvalidOid if don't care.
2685 * actualop: if not NULL, *actualop receives the actual STAOP value.
2686 * values, nvalues: if not NULL, the slot's stavalues are extracted.
2687 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
2689 * If assigned, values and numbers are set to point to palloc'd arrays.
2690 * If the attribute type is pass-by-reference, the values referenced by
2691 * the values array are themselves palloc'd. The palloc'd stuff can be
2692 * freed by calling free_attstatsslot.
2694 * Note: at present, atttype/atttypmod aren't actually used here at all.
2695 * But the caller must have the correct (or at least binary-compatible)
2696 * type ID to pass to free_attstatsslot later.
2699 get_attstatsslot(HeapTuple statstuple,
2700 Oid atttype, int32 atttypmod,
2701 int reqkind, Oid reqop,
2703 Datum **values, int *nvalues,
2704 float4 **numbers, int *nnumbers)
2706 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
2711 ArrayType *statarray;
2714 HeapTuple typeTuple;
2715 Form_pg_type typeForm;
2717 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
2719 if ((&stats->stakind1)[i] == reqkind &&
2720 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
2723 if (i >= STATISTIC_NUM_SLOTS)
2724 return false; /* not there */
2727 *actualop = (&stats->staop1)[i];
2731 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2732 Anum_pg_statistic_stavalues1 + i,
2735 elog(ERROR, "stavalues is null");
2736 statarray = DatumGetArrayTypeP(val);
2739 * Need to get info about the array element type. We look at the
2740 * actual element type embedded in the array, which might be only
2741 * binary-compatible with the passed-in atttype. The info we extract
2742 * here should be the same either way, but deconstruct_array is picky
2743 * about having an exact type OID match.
2745 arrayelemtype = ARR_ELEMTYPE(statarray);
2746 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
2747 if (!HeapTupleIsValid(typeTuple))
2748 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
2749 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
2751 /* Deconstruct array into Datum elements; NULLs not expected */
2752 deconstruct_array(statarray,
2757 values, NULL, nvalues);
2760 * If the element type is pass-by-reference, we now have a bunch of
2761 * Datums that are pointers into the syscache value. Copy them to
2762 * avoid problems if syscache decides to drop the entry.
2764 if (!typeForm->typbyval)
2766 for (j = 0; j < *nvalues; j++)
2768 (*values)[j] = datumCopy((*values)[j],
2774 ReleaseSysCache(typeTuple);
2777 * Free statarray if it's a detoasted copy.
2779 if ((Pointer) statarray != DatumGetPointer(val))
2785 val = SysCacheGetAttr(STATRELATTINH, statstuple,
2786 Anum_pg_statistic_stanumbers1 + i,
2789 elog(ERROR, "stanumbers is null");
2790 statarray = DatumGetArrayTypeP(val);
2793 * We expect the array to be a 1-D float4 array; verify that. We don't
2794 * need to use deconstruct_array() since the array data is just going
2795 * to look like a C array of float4 values.
2797 narrayelem = ARR_DIMS(statarray)[0];
2798 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
2799 ARR_HASNULL(statarray) ||
2800 ARR_ELEMTYPE(statarray) != FLOAT4OID)
2801 elog(ERROR, "stanumbers is not a 1-D float4 array");
2802 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
2803 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
2804 *nnumbers = narrayelem;
2807 * Free statarray if it's a detoasted copy.
2809 if ((Pointer) statarray != DatumGetPointer(val))
2818 * Free data allocated by get_attstatsslot
2820 * atttype need be valid only if values != NULL.
2823 free_attstatsslot(Oid atttype,
2824 Datum *values, int nvalues,
2825 float4 *numbers, int nnumbers)
2829 if (!get_typbyval(atttype))
2833 for (i = 0; i < nvalues; i++)
2834 pfree(DatumGetPointer(values[i]));
2842 /* ---------- PG_NAMESPACE CACHE ---------- */
2845 * get_namespace_name
2846 * Returns the name of a given namespace
2848 * Returns a palloc'd copy of the string, or NULL if no such namespace.
2851 get_namespace_name(Oid nspid)
2855 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
2856 if (HeapTupleIsValid(tp))
2858 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
2861 result = pstrdup(NameStr(nsptup->nspname));
2862 ReleaseSysCache(tp);
2869 /* ---------- PG_RANGE CACHE ---------- */
2873 * Returns the subtype of a given range type
2875 * Returns InvalidOid if the type is not a range type.
2878 get_range_subtype(Oid rangeOid)
2882 tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
2883 if (HeapTupleIsValid(tp))
2885 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
2888 result = rngtup->rngsubtype;
2889 ReleaseSysCache(tp);