LCOV - code coverage report
Current view: top level - src/backend/utils/cache - lsyscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 900 1036 86.9 %
Date: 2020-05-29 01:06:25 Functions: 101 103 98.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * lsyscache.c
       4             :  *    Convenience routines for common queries in the system catalog cache.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/backend/utils/cache/lsyscache.c
      11             :  *
      12             :  * NOTES
      13             :  *    Eventually, the index information should go through here, too.
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : #include "postgres.h"
      17             : 
      18             : #include "access/hash.h"
      19             : #include "access/htup_details.h"
      20             : #include "access/nbtree.h"
      21             : #include "bootstrap/bootstrap.h"
      22             : #include "catalog/namespace.h"
      23             : #include "catalog/pg_am.h"
      24             : #include "catalog/pg_amop.h"
      25             : #include "catalog/pg_amproc.h"
      26             : #include "catalog/pg_cast.h"
      27             : #include "catalog/pg_collation.h"
      28             : #include "catalog/pg_constraint.h"
      29             : #include "catalog/pg_language.h"
      30             : #include "catalog/pg_namespace.h"
      31             : #include "catalog/pg_opclass.h"
      32             : #include "catalog/pg_operator.h"
      33             : #include "catalog/pg_proc.h"
      34             : #include "catalog/pg_range.h"
      35             : #include "catalog/pg_statistic.h"
      36             : #include "catalog/pg_transform.h"
      37             : #include "catalog/pg_type.h"
      38             : #include "miscadmin.h"
      39             : #include "nodes/makefuncs.h"
      40             : #include "utils/array.h"
      41             : #include "utils/builtins.h"
      42             : #include "utils/catcache.h"
      43             : #include "utils/datum.h"
      44             : #include "utils/fmgroids.h"
      45             : #include "utils/lsyscache.h"
      46             : #include "utils/rel.h"
      47             : #include "utils/syscache.h"
      48             : #include "utils/typcache.h"
      49             : 
      50             : /* Hook for plugins to get control in get_attavgwidth() */
      51             : get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
      52             : 
      53             : 
      54             : /*              ---------- AMOP CACHES ----------                        */
      55             : 
      56             : /*
      57             :  * op_in_opfamily
      58             :  *
      59             :  *      Return t iff operator 'opno' is in operator family 'opfamily'.
      60             :  *
      61             :  * This function only considers search operators, not ordering operators.
      62             :  */
      63             : bool
      64      243524 : op_in_opfamily(Oid opno, Oid opfamily)
      65             : {
      66      243524 :     return SearchSysCacheExists3(AMOPOPID,
      67             :                                  ObjectIdGetDatum(opno),
      68             :                                  CharGetDatum(AMOP_SEARCH),
      69             :                                  ObjectIdGetDatum(opfamily));
      70             : }
      71             : 
      72             : /*
      73             :  * get_op_opfamily_strategy
      74             :  *
      75             :  *      Get the operator's strategy number within the specified opfamily,
      76             :  *      or 0 if it's not a member of the opfamily.
      77             :  *
      78             :  * This function only considers search operators, not ordering operators.
      79             :  */
      80             : int
      81      386992 : get_op_opfamily_strategy(Oid opno, Oid opfamily)
      82             : {
      83             :     HeapTuple   tp;
      84             :     Form_pg_amop amop_tup;
      85             :     int         result;
      86             : 
      87      386992 :     tp = SearchSysCache3(AMOPOPID,
      88             :                          ObjectIdGetDatum(opno),
      89             :                          CharGetDatum(AMOP_SEARCH),
      90             :                          ObjectIdGetDatum(opfamily));
      91      386992 :     if (!HeapTupleIsValid(tp))
      92           0 :         return 0;
      93      386992 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
      94      386992 :     result = amop_tup->amopstrategy;
      95      386992 :     ReleaseSysCache(tp);
      96      386992 :     return result;
      97             : }
      98             : 
      99             : /*
     100             :  * get_op_opfamily_sortfamily
     101             :  *
     102             :  *      If the operator is an ordering operator within the specified opfamily,
     103             :  *      return its amopsortfamily OID; else return InvalidOid.
     104             :  */
     105             : Oid
     106         320 : get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
     107             : {
     108             :     HeapTuple   tp;
     109             :     Form_pg_amop amop_tup;
     110             :     Oid         result;
     111             : 
     112         320 :     tp = SearchSysCache3(AMOPOPID,
     113             :                          ObjectIdGetDatum(opno),
     114             :                          CharGetDatum(AMOP_ORDER),
     115             :                          ObjectIdGetDatum(opfamily));
     116         320 :     if (!HeapTupleIsValid(tp))
     117           0 :         return InvalidOid;
     118         320 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
     119         320 :     result = amop_tup->amopsortfamily;
     120         320 :     ReleaseSysCache(tp);
     121         320 :     return result;
     122             : }
     123             : 
     124             : /*
     125             :  * get_op_opfamily_properties
     126             :  *
     127             :  *      Get the operator's strategy number and declared input data types
     128             :  *      within the specified opfamily.
     129             :  *
     130             :  * Caller should already have verified that opno is a member of opfamily,
     131             :  * therefore we raise an error if the tuple is not found.
     132             :  */
     133             : void
     134      200666 : get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
     135             :                            int *strategy,
     136             :                            Oid *lefttype,
     137             :                            Oid *righttype)
     138             : {
     139             :     HeapTuple   tp;
     140             :     Form_pg_amop amop_tup;
     141             : 
     142      200666 :     tp = SearchSysCache3(AMOPOPID,
     143             :                          ObjectIdGetDatum(opno),
     144             :                          CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
     145             :                          ObjectIdGetDatum(opfamily));
     146      200666 :     if (!HeapTupleIsValid(tp))
     147           0 :         elog(ERROR, "operator %u is not a member of opfamily %u",
     148             :              opno, opfamily);
     149      200666 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
     150      200666 :     *strategy = amop_tup->amopstrategy;
     151      200666 :     *lefttype = amop_tup->amoplefttype;
     152      200666 :     *righttype = amop_tup->amoprighttype;
     153      200666 :     ReleaseSysCache(tp);
     154      200666 : }
     155             : 
     156             : /*
     157             :  * get_opfamily_member
     158             :  *      Get the OID of the operator that implements the specified strategy
     159             :  *      with the specified datatypes for the specified opfamily.
     160             :  *
     161             :  * Returns InvalidOid if there is no pg_amop entry for the given keys.
     162             :  */
     163             : Oid
     164     1557086 : get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
     165             :                     int16 strategy)
     166             : {
     167             :     HeapTuple   tp;
     168             :     Form_pg_amop amop_tup;
     169             :     Oid         result;
     170             : 
     171     1557086 :     tp = SearchSysCache4(AMOPSTRATEGY,
     172             :                          ObjectIdGetDatum(opfamily),
     173             :                          ObjectIdGetDatum(lefttype),
     174             :                          ObjectIdGetDatum(righttype),
     175             :                          Int16GetDatum(strategy));
     176     1557086 :     if (!HeapTupleIsValid(tp))
     177         244 :         return InvalidOid;
     178     1556842 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
     179     1556842 :     result = amop_tup->amopopr;
     180     1556842 :     ReleaseSysCache(tp);
     181     1556842 :     return result;
     182             : }
     183             : 
     184             : /*
     185             :  * get_ordering_op_properties
     186             :  *      Given the OID of an ordering operator (a btree "<" or ">" operator),
     187             :  *      determine its opfamily, its declared input datatype, and its
     188             :  *      strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber).
     189             :  *
     190             :  * Returns true if successful, false if no matching pg_amop entry exists.
     191             :  * (This indicates that the operator is not a valid ordering operator.)
     192             :  *
     193             :  * Note: the operator could be registered in multiple families, for example
     194             :  * if someone were to build a "reverse sort" opfamily.  This would result in
     195             :  * uncertainty as to whether "ORDER BY USING op" would default to NULLS FIRST
     196             :  * or NULLS LAST, as well as inefficient planning due to failure to match up
     197             :  * pathkeys that should be the same.  So we want a determinate result here.
     198             :  * Because of the way the syscache search works, we'll use the interpretation
     199             :  * associated with the opfamily with smallest OID, which is probably
     200             :  * determinate enough.  Since there is no longer any particularly good reason
     201             :  * to build reverse-sort opfamilies, it doesn't seem worth expending any
     202             :  * additional effort on ensuring consistency.
     203             :  */
     204             : bool
     205     1458198 : get_ordering_op_properties(Oid opno,
     206             :                            Oid *opfamily, Oid *opcintype, int16 *strategy)
     207             : {
     208     1458198 :     bool        result = false;
     209             :     CatCList   *catlist;
     210             :     int         i;
     211             : 
     212             :     /* ensure outputs are initialized on failure */
     213     1458198 :     *opfamily = InvalidOid;
     214     1458198 :     *opcintype = InvalidOid;
     215     1458198 :     *strategy = 0;
     216             : 
     217             :     /*
     218             :      * Search pg_amop to see if the target operator is registered as the "<"
     219             :      * or ">" operator of any btree opfamily.
     220             :      */
     221     1458198 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     222             : 
     223     1458198 :     for (i = 0; i < catlist->n_members; i++)
     224             :     {
     225     1458198 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     226     1458198 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     227             : 
     228             :         /* must be btree */
     229     1458198 :         if (aform->amopmethod != BTREE_AM_OID)
     230           0 :             continue;
     231             : 
     232     1458198 :         if (aform->amopstrategy == BTLessStrategyNumber ||
     233        4332 :             aform->amopstrategy == BTGreaterStrategyNumber)
     234             :         {
     235             :             /* Found it ... should have consistent input types */
     236     1458198 :             if (aform->amoplefttype == aform->amoprighttype)
     237             :             {
     238             :                 /* Found a suitable opfamily, return info */
     239     1458198 :                 *opfamily = aform->amopfamily;
     240     1458198 :                 *opcintype = aform->amoplefttype;
     241     1458198 :                 *strategy = aform->amopstrategy;
     242     1458198 :                 result = true;
     243     1458198 :                 break;
     244             :             }
     245             :         }
     246             :     }
     247             : 
     248     1458198 :     ReleaseSysCacheList(catlist);
     249             : 
     250     1458198 :     return result;
     251             : }
     252             : 
     253             : /*
     254             :  * get_equality_op_for_ordering_op
     255             :  *      Get the OID of the datatype-specific btree equality operator
     256             :  *      associated with an ordering operator (a "<" or ">" operator).
     257             :  *
     258             :  * If "reverse" isn't NULL, also set *reverse to false if the operator is "<",
     259             :  * true if it's ">"
     260             :  *
     261             :  * Returns InvalidOid if no matching equality operator can be found.
     262             :  * (This indicates that the operator is not a valid ordering operator.)
     263             :  */
     264             : Oid
     265         888 : get_equality_op_for_ordering_op(Oid opno, bool *reverse)
     266             : {
     267         888 :     Oid         result = InvalidOid;
     268             :     Oid         opfamily;
     269             :     Oid         opcintype;
     270             :     int16       strategy;
     271             : 
     272             :     /* Find the operator in pg_amop */
     273         888 :     if (get_ordering_op_properties(opno,
     274             :                                    &opfamily, &opcintype, &strategy))
     275             :     {
     276             :         /* Found a suitable opfamily, get matching equality operator */
     277         888 :         result = get_opfamily_member(opfamily,
     278             :                                      opcintype,
     279             :                                      opcintype,
     280             :                                      BTEqualStrategyNumber);
     281         888 :         if (reverse)
     282         754 :             *reverse = (strategy == BTGreaterStrategyNumber);
     283             :     }
     284             : 
     285         888 :     return result;
     286             : }
     287             : 
     288             : /*
     289             :  * get_ordering_op_for_equality_op
     290             :  *      Get the OID of a datatype-specific btree ordering operator
     291             :  *      associated with an equality operator.  (If there are multiple
     292             :  *      possibilities, assume any one will do.)
     293             :  *
     294             :  * This function is used when we have to sort data before unique-ifying,
     295             :  * and don't much care which sorting op is used as long as it's compatible
     296             :  * with the intended equality operator.  Since we need a sorting operator,
     297             :  * it should be single-data-type even if the given operator is cross-type.
     298             :  * The caller specifies whether to find an op for the LHS or RHS data type.
     299             :  *
     300             :  * Returns InvalidOid if no matching ordering operator can be found.
     301             :  */
     302             : Oid
     303           2 : get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
     304             : {
     305           2 :     Oid         result = InvalidOid;
     306             :     CatCList   *catlist;
     307             :     int         i;
     308             : 
     309             :     /*
     310             :      * Search pg_amop to see if the target operator is registered as the "="
     311             :      * operator of any btree opfamily.
     312             :      */
     313           2 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     314             : 
     315           2 :     for (i = 0; i < catlist->n_members; i++)
     316             :     {
     317           2 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     318           2 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     319             : 
     320             :         /* must be btree */
     321           2 :         if (aform->amopmethod != BTREE_AM_OID)
     322           0 :             continue;
     323             : 
     324           2 :         if (aform->amopstrategy == BTEqualStrategyNumber)
     325             :         {
     326             :             /* Found a suitable opfamily, get matching ordering operator */
     327             :             Oid         typid;
     328             : 
     329           2 :             typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
     330           2 :             result = get_opfamily_member(aform->amopfamily,
     331             :                                          typid, typid,
     332             :                                          BTLessStrategyNumber);
     333           2 :             if (OidIsValid(result))
     334           2 :                 break;
     335             :             /* failure probably shouldn't happen, but keep looking if so */
     336             :         }
     337             :     }
     338             : 
     339           2 :     ReleaseSysCacheList(catlist);
     340             : 
     341           2 :     return result;
     342             : }
     343             : 
     344             : /*
     345             :  * get_mergejoin_opfamilies
     346             :  *      Given a putatively mergejoinable operator, return a list of the OIDs
     347             :  *      of the btree opfamilies in which it represents equality.
     348             :  *
     349             :  * It is possible (though at present unusual) for an operator to be equality
     350             :  * in more than one opfamily, hence the result is a list.  This also lets us
     351             :  * return NIL if the operator is not found in any opfamilies.
     352             :  *
     353             :  * The planner currently uses simple equal() tests to compare the lists
     354             :  * returned by this function, which makes the list order relevant, though
     355             :  * strictly speaking it should not be.  Because of the way syscache list
     356             :  * searches are handled, in normal operation the result will be sorted by OID
     357             :  * so everything works fine.  If running with system index usage disabled,
     358             :  * the result ordering is unspecified and hence the planner might fail to
     359             :  * recognize optimization opportunities ... but that's hardly a scenario in
     360             :  * which performance is good anyway, so there's no point in expending code
     361             :  * or cycles here to guarantee the ordering in that case.
     362             :  */
     363             : List *
     364     1109818 : get_mergejoin_opfamilies(Oid opno)
     365             : {
     366     1109818 :     List       *result = NIL;
     367             :     CatCList   *catlist;
     368             :     int         i;
     369             : 
     370             :     /*
     371             :      * Search pg_amop to see if the target operator is registered as the "="
     372             :      * operator of any btree opfamily.
     373             :      */
     374     1109818 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     375             : 
     376     4613476 :     for (i = 0; i < catlist->n_members; i++)
     377             :     {
     378     3503658 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     379     3503658 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     380             : 
     381             :         /* must be btree equality */
     382     3503658 :         if (aform->amopmethod == BTREE_AM_OID &&
     383     1134928 :             aform->amopstrategy == BTEqualStrategyNumber)
     384     1134928 :             result = lappend_oid(result, aform->amopfamily);
     385             :     }
     386             : 
     387     1109818 :     ReleaseSysCacheList(catlist);
     388             : 
     389     1109818 :     return result;
     390             : }
     391             : 
     392             : /*
     393             :  * get_compatible_hash_operators
     394             :  *      Get the OID(s) of hash equality operator(s) compatible with the given
     395             :  *      operator, but operating on its LHS and/or RHS datatype.
     396             :  *
     397             :  * An operator for the LHS type is sought and returned into *lhs_opno if
     398             :  * lhs_opno isn't NULL.  Similarly, an operator for the RHS type is sought
     399             :  * and returned into *rhs_opno if rhs_opno isn't NULL.
     400             :  *
     401             :  * If the given operator is not cross-type, the results should be the same
     402             :  * operator, but in cross-type situations they will be different.
     403             :  *
     404             :  * Returns true if able to find the requested operator(s), false if not.
     405             :  * (This indicates that the operator should not have been marked oprcanhash.)
     406             :  */
     407             : bool
     408        2184 : get_compatible_hash_operators(Oid opno,
     409             :                               Oid *lhs_opno, Oid *rhs_opno)
     410             : {
     411        2184 :     bool        result = false;
     412             :     CatCList   *catlist;
     413             :     int         i;
     414             : 
     415             :     /* Ensure output args are initialized on failure */
     416        2184 :     if (lhs_opno)
     417           0 :         *lhs_opno = InvalidOid;
     418        2184 :     if (rhs_opno)
     419        2184 :         *rhs_opno = InvalidOid;
     420             : 
     421             :     /*
     422             :      * Search pg_amop to see if the target operator is registered as the "="
     423             :      * operator of any hash opfamily.  If the operator is registered in
     424             :      * multiple opfamilies, assume we can use any one.
     425             :      */
     426        2184 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     427             : 
     428        4368 :     for (i = 0; i < catlist->n_members; i++)
     429             :     {
     430        4368 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     431        4368 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     432             : 
     433        4368 :         if (aform->amopmethod == HASH_AM_OID &&
     434        2184 :             aform->amopstrategy == HTEqualStrategyNumber)
     435             :         {
     436             :             /* No extra lookup needed if given operator is single-type */
     437        2184 :             if (aform->amoplefttype == aform->amoprighttype)
     438             :             {
     439        2140 :                 if (lhs_opno)
     440           0 :                     *lhs_opno = opno;
     441        2140 :                 if (rhs_opno)
     442        2140 :                     *rhs_opno = opno;
     443        2140 :                 result = true;
     444        2140 :                 break;
     445             :             }
     446             : 
     447             :             /*
     448             :              * Get the matching single-type operator(s).  Failure probably
     449             :              * shouldn't happen --- it implies a bogus opfamily --- but
     450             :              * continue looking if so.
     451             :              */
     452          44 :             if (lhs_opno)
     453             :             {
     454           0 :                 *lhs_opno = get_opfamily_member(aform->amopfamily,
     455             :                                                 aform->amoplefttype,
     456             :                                                 aform->amoplefttype,
     457             :                                                 HTEqualStrategyNumber);
     458           0 :                 if (!OidIsValid(*lhs_opno))
     459           0 :                     continue;
     460             :                 /* Matching LHS found, done if caller doesn't want RHS */
     461           0 :                 if (!rhs_opno)
     462             :                 {
     463           0 :                     result = true;
     464           0 :                     break;
     465             :                 }
     466             :             }
     467          44 :             if (rhs_opno)
     468             :             {
     469          44 :                 *rhs_opno = get_opfamily_member(aform->amopfamily,
     470             :                                                 aform->amoprighttype,
     471             :                                                 aform->amoprighttype,
     472             :                                                 HTEqualStrategyNumber);
     473          44 :                 if (!OidIsValid(*rhs_opno))
     474             :                 {
     475             :                     /* Forget any LHS operator from this opfamily */
     476           0 :                     if (lhs_opno)
     477           0 :                         *lhs_opno = InvalidOid;
     478           0 :                     continue;
     479             :                 }
     480             :                 /* Matching RHS found, so done */
     481          44 :                 result = true;
     482          44 :                 break;
     483             :             }
     484             :         }
     485             :     }
     486             : 
     487        2184 :     ReleaseSysCacheList(catlist);
     488             : 
     489        2184 :     return result;
     490             : }
     491             : 
     492             : /*
     493             :  * get_op_hash_functions
     494             :  *      Get the OID(s) of the standard hash support function(s) compatible with
     495             :  *      the given operator, operating on its LHS and/or RHS datatype as required.
     496             :  *
     497             :  * A function for the LHS type is sought and returned into *lhs_procno if
     498             :  * lhs_procno isn't NULL.  Similarly, a function for the RHS type is sought
     499             :  * and returned into *rhs_procno if rhs_procno isn't NULL.
     500             :  *
     501             :  * If the given operator is not cross-type, the results should be the same
     502             :  * function, but in cross-type situations they will be different.
     503             :  *
     504             :  * Returns true if able to find the requested function(s), false if not.
     505             :  * (This indicates that the operator should not have been marked oprcanhash.)
     506             :  */
     507             : bool
     508      275646 : get_op_hash_functions(Oid opno,
     509             :                       RegProcedure *lhs_procno, RegProcedure *rhs_procno)
     510             : {
     511      275646 :     bool        result = false;
     512             :     CatCList   *catlist;
     513             :     int         i;
     514             : 
     515             :     /* Ensure output args are initialized on failure */
     516      275646 :     if (lhs_procno)
     517      275646 :         *lhs_procno = InvalidOid;
     518      275646 :     if (rhs_procno)
     519      275646 :         *rhs_procno = InvalidOid;
     520             : 
     521             :     /*
     522             :      * Search pg_amop to see if the target operator is registered as the "="
     523             :      * operator of any hash opfamily.  If the operator is registered in
     524             :      * multiple opfamilies, assume we can use any one.
     525             :      */
     526      275646 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     527             : 
     528      299510 :     for (i = 0; i < catlist->n_members; i++)
     529             :     {
     530      299510 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     531      299510 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     532             : 
     533      299510 :         if (aform->amopmethod == HASH_AM_OID &&
     534      275646 :             aform->amopstrategy == HTEqualStrategyNumber)
     535             :         {
     536             :             /*
     537             :              * Get the matching support function(s).  Failure probably
     538             :              * shouldn't happen --- it implies a bogus opfamily --- but
     539             :              * continue looking if so.
     540             :              */
     541      275646 :             if (lhs_procno)
     542             :             {
     543      275646 :                 *lhs_procno = get_opfamily_proc(aform->amopfamily,
     544             :                                                 aform->amoplefttype,
     545             :                                                 aform->amoplefttype,
     546             :                                                 HASHSTANDARD_PROC);
     547      275646 :                 if (!OidIsValid(*lhs_procno))
     548           0 :                     continue;
     549             :                 /* Matching LHS found, done if caller doesn't want RHS */
     550      275646 :                 if (!rhs_procno)
     551             :                 {
     552           0 :                     result = true;
     553           0 :                     break;
     554             :                 }
     555             :                 /* Only one lookup needed if given operator is single-type */
     556      275646 :                 if (aform->amoplefttype == aform->amoprighttype)
     557             :                 {
     558      275110 :                     *rhs_procno = *lhs_procno;
     559      275110 :                     result = true;
     560      275110 :                     break;
     561             :                 }
     562             :             }
     563         536 :             if (rhs_procno)
     564             :             {
     565         536 :                 *rhs_procno = get_opfamily_proc(aform->amopfamily,
     566             :                                                 aform->amoprighttype,
     567             :                                                 aform->amoprighttype,
     568             :                                                 HASHSTANDARD_PROC);
     569         536 :                 if (!OidIsValid(*rhs_procno))
     570             :                 {
     571             :                     /* Forget any LHS function from this opfamily */
     572           0 :                     if (lhs_procno)
     573           0 :                         *lhs_procno = InvalidOid;
     574           0 :                     continue;
     575             :                 }
     576             :                 /* Matching RHS found, so done */
     577         536 :                 result = true;
     578         536 :                 break;
     579             :             }
     580             :         }
     581             :     }
     582             : 
     583      275646 :     ReleaseSysCacheList(catlist);
     584             : 
     585      275646 :     return result;
     586             : }
     587             : 
     588             : /*
     589             :  * get_op_btree_interpretation
     590             :  *      Given an operator's OID, find out which btree opfamilies it belongs to,
     591             :  *      and what properties it has within each one.  The results are returned
     592             :  *      as a palloc'd list of OpBtreeInterpretation structs.
     593             :  *
     594             :  * In addition to the normal btree operators, we consider a <> operator to be
     595             :  * a "member" of an opfamily if its negator is an equality operator of the
     596             :  * opfamily.  ROWCOMPARE_NE is returned as the strategy number for this case.
     597             :  */
     598             : List *
     599        7052 : get_op_btree_interpretation(Oid opno)
     600             : {
     601        7052 :     List       *result = NIL;
     602             :     OpBtreeInterpretation *thisresult;
     603             :     CatCList   *catlist;
     604             :     int         i;
     605             : 
     606             :     /*
     607             :      * Find all the pg_amop entries containing the operator.
     608             :      */
     609        7052 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     610             : 
     611       19068 :     for (i = 0; i < catlist->n_members; i++)
     612             :     {
     613       12016 :         HeapTuple   op_tuple = &catlist->members[i]->tuple;
     614       12016 :         Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
     615             :         StrategyNumber op_strategy;
     616             : 
     617             :         /* must be btree */
     618       12016 :         if (op_form->amopmethod != BTREE_AM_OID)
     619        7714 :             continue;
     620             : 
     621             :         /* Get the operator's btree strategy number */
     622        4302 :         op_strategy = (StrategyNumber) op_form->amopstrategy;
     623             :         Assert(op_strategy >= 1 && op_strategy <= 5);
     624             : 
     625             :         thisresult = (OpBtreeInterpretation *)
     626        4302 :             palloc(sizeof(OpBtreeInterpretation));
     627        4302 :         thisresult->opfamily_id = op_form->amopfamily;
     628        4302 :         thisresult->strategy = op_strategy;
     629        4302 :         thisresult->oplefttype = op_form->amoplefttype;
     630        4302 :         thisresult->oprighttype = op_form->amoprighttype;
     631        4302 :         result = lappend(result, thisresult);
     632             :     }
     633             : 
     634        7052 :     ReleaseSysCacheList(catlist);
     635             : 
     636             :     /*
     637             :      * If we didn't find any btree opfamily containing the operator, perhaps
     638             :      * it is a <> operator.  See if it has a negator that is in an opfamily.
     639             :      */
     640        7052 :     if (result == NIL)
     641             :     {
     642        3212 :         Oid         op_negator = get_negator(opno);
     643             : 
     644        3212 :         if (OidIsValid(op_negator))
     645             :         {
     646        3196 :             catlist = SearchSysCacheList1(AMOPOPID,
     647             :                                           ObjectIdGetDatum(op_negator));
     648             : 
     649       12196 :             for (i = 0; i < catlist->n_members; i++)
     650             :             {
     651        9000 :                 HeapTuple   op_tuple = &catlist->members[i]->tuple;
     652        9000 :                 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
     653             :                 StrategyNumber op_strategy;
     654             : 
     655             :                 /* must be btree */
     656        9000 :                 if (op_form->amopmethod != BTREE_AM_OID)
     657        6020 :                     continue;
     658             : 
     659             :                 /* Get the operator's btree strategy number */
     660        2980 :                 op_strategy = (StrategyNumber) op_form->amopstrategy;
     661             :                 Assert(op_strategy >= 1 && op_strategy <= 5);
     662             : 
     663             :                 /* Only consider negators that are = */
     664        2980 :                 if (op_strategy != BTEqualStrategyNumber)
     665           0 :                     continue;
     666             : 
     667             :                 /* OK, report it with "strategy" ROWCOMPARE_NE */
     668             :                 thisresult = (OpBtreeInterpretation *)
     669        2980 :                     palloc(sizeof(OpBtreeInterpretation));
     670        2980 :                 thisresult->opfamily_id = op_form->amopfamily;
     671        2980 :                 thisresult->strategy = ROWCOMPARE_NE;
     672        2980 :                 thisresult->oplefttype = op_form->amoplefttype;
     673        2980 :                 thisresult->oprighttype = op_form->amoprighttype;
     674        2980 :                 result = lappend(result, thisresult);
     675             :             }
     676             : 
     677        3196 :             ReleaseSysCacheList(catlist);
     678             :         }
     679             :     }
     680             : 
     681        7052 :     return result;
     682             : }
     683             : 
     684             : /*
     685             :  * equality_ops_are_compatible
     686             :  *      Return true if the two given equality operators have compatible
     687             :  *      semantics.
     688             :  *
     689             :  * This is trivially true if they are the same operator.  Otherwise,
     690             :  * we look to see if they can be found in the same btree or hash opfamily.
     691             :  * Either finding allows us to assume that they have compatible notions
     692             :  * of equality.  (The reason we need to do these pushups is that one might
     693             :  * be a cross-type operator; for instance int24eq vs int4eq.)
     694             :  */
     695             : bool
     696          88 : equality_ops_are_compatible(Oid opno1, Oid opno2)
     697             : {
     698             :     bool        result;
     699             :     CatCList   *catlist;
     700             :     int         i;
     701             : 
     702             :     /* Easy if they're the same operator */
     703          88 :     if (opno1 == opno2)
     704          84 :         return true;
     705             : 
     706             :     /*
     707             :      * We search through all the pg_amop entries for opno1.
     708             :      */
     709           4 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
     710             : 
     711           4 :     result = false;
     712           4 :     for (i = 0; i < catlist->n_members; i++)
     713             :     {
     714           4 :         HeapTuple   op_tuple = &catlist->members[i]->tuple;
     715           4 :         Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
     716             : 
     717             :         /* must be btree or hash */
     718           4 :         if (op_form->amopmethod == BTREE_AM_OID ||
     719           0 :             op_form->amopmethod == HASH_AM_OID)
     720             :         {
     721           4 :             if (op_in_opfamily(opno2, op_form->amopfamily))
     722             :             {
     723           4 :                 result = true;
     724           4 :                 break;
     725             :             }
     726             :         }
     727             :     }
     728             : 
     729           4 :     ReleaseSysCacheList(catlist);
     730             : 
     731           4 :     return result;
     732             : }
     733             : 
     734             : 
     735             : /*              ---------- AMPROC CACHES ----------                      */
     736             : 
     737             : /*
     738             :  * get_opfamily_proc
     739             :  *      Get the OID of the specified support function
     740             :  *      for the specified opfamily and datatypes.
     741             :  *
     742             :  * Returns InvalidOid if there is no pg_amproc entry for the given keys.
     743             :  */
     744             : Oid
     745     2026274 : get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
     746             : {
     747             :     HeapTuple   tp;
     748             :     Form_pg_amproc amproc_tup;
     749             :     RegProcedure result;
     750             : 
     751     2026274 :     tp = SearchSysCache4(AMPROCNUM,
     752             :                          ObjectIdGetDatum(opfamily),
     753             :                          ObjectIdGetDatum(lefttype),
     754             :                          ObjectIdGetDatum(righttype),
     755             :                          Int16GetDatum(procnum));
     756     2026274 :     if (!HeapTupleIsValid(tp))
     757       64450 :         return InvalidOid;
     758     1961824 :     amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
     759     1961824 :     result = amproc_tup->amproc;
     760     1961824 :     ReleaseSysCache(tp);
     761     1961824 :     return result;
     762             : }
     763             : 
     764             : 
     765             : /*              ---------- ATTRIBUTE CACHES ----------                   */
     766             : 
     767             : /*
     768             :  * get_attname
     769             :  *      Given the relation id and the attribute number, return the "attname"
     770             :  *      field from the attribute relation as a palloc'ed string.
     771             :  *
     772             :  * If no such attribute exists and missing_ok is true, NULL is returned;
     773             :  * otherwise a not-intended-for-user-consumption error is thrown.
     774             :  */
     775             : char *
     776       33364 : get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
     777             : {
     778             :     HeapTuple   tp;
     779             : 
     780       33364 :     tp = SearchSysCache2(ATTNUM,
     781             :                          ObjectIdGetDatum(relid), Int16GetDatum(attnum));
     782       33364 :     if (HeapTupleIsValid(tp))
     783             :     {
     784       33360 :         Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     785             :         char       *result;
     786             : 
     787       33360 :         result = pstrdup(NameStr(att_tup->attname));
     788       33360 :         ReleaseSysCache(tp);
     789       33360 :         return result;
     790             :     }
     791             : 
     792           4 :     if (!missing_ok)
     793           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     794             :              attnum, relid);
     795           4 :     return NULL;
     796             : }
     797             : 
     798             : /*
     799             :  * get_attnum
     800             :  *
     801             :  *      Given the relation id and the attribute name,
     802             :  *      return the "attnum" field from the attribute relation.
     803             :  *
     804             :  *      Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
     805             :  */
     806             : AttrNumber
     807        4782 : get_attnum(Oid relid, const char *attname)
     808             : {
     809             :     HeapTuple   tp;
     810             : 
     811        4782 :     tp = SearchSysCacheAttName(relid, attname);
     812        4782 :     if (HeapTupleIsValid(tp))
     813             :     {
     814        4746 :         Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     815             :         AttrNumber  result;
     816             : 
     817        4746 :         result = att_tup->attnum;
     818        4746 :         ReleaseSysCache(tp);
     819        4746 :         return result;
     820             :     }
     821             :     else
     822          36 :         return InvalidAttrNumber;
     823             : }
     824             : 
     825             : /*
     826             :  * get_attgenerated
     827             :  *
     828             :  *      Given the relation id and the attribute name,
     829             :  *      return the "attgenerated" field from the attribute relation.
     830             :  *
     831             :  *      Errors if not found.
     832             :  *
     833             :  *      Since not generated is represented by '\0', this can also be used as a
     834             :  *      Boolean test.
     835             :  */
     836             : char
     837         266 : get_attgenerated(Oid relid, AttrNumber attnum)
     838             : {
     839             :     HeapTuple   tp;
     840             :     Form_pg_attribute att_tup;
     841             :     char        result;
     842             : 
     843         266 :     tp = SearchSysCache2(ATTNUM,
     844             :                          ObjectIdGetDatum(relid),
     845             :                          Int16GetDatum(attnum));
     846         266 :     if (!HeapTupleIsValid(tp))
     847           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     848             :              attnum, relid);
     849         266 :     att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     850         266 :     result = att_tup->attgenerated;
     851         266 :     ReleaseSysCache(tp);
     852         266 :     return result;
     853             : }
     854             : 
     855             : /*
     856             :  * get_atttype
     857             :  *
     858             :  *      Given the relation OID and the attribute number with the relation,
     859             :  *      return the attribute type OID.
     860             :  */
     861             : Oid
     862         836 : get_atttype(Oid relid, AttrNumber attnum)
     863             : {
     864             :     HeapTuple   tp;
     865             : 
     866         836 :     tp = SearchSysCache2(ATTNUM,
     867             :                          ObjectIdGetDatum(relid),
     868             :                          Int16GetDatum(attnum));
     869         836 :     if (HeapTupleIsValid(tp))
     870             :     {
     871         836 :         Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     872             :         Oid         result;
     873             : 
     874         836 :         result = att_tup->atttypid;
     875         836 :         ReleaseSysCache(tp);
     876         836 :         return result;
     877             :     }
     878             :     else
     879           0 :         return InvalidOid;
     880             : }
     881             : 
     882             : /*
     883             :  * get_atttypetypmodcoll
     884             :  *
     885             :  *      A three-fer: given the relation id and the attribute number,
     886             :  *      fetch atttypid, atttypmod, and attcollation in a single cache lookup.
     887             :  *
     888             :  * Unlike the otherwise-similar get_atttype, this routine
     889             :  * raises an error if it can't obtain the information.
     890             :  */
     891             : void
     892        6138 : get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
     893             :                       Oid *typid, int32 *typmod, Oid *collid)
     894             : {
     895             :     HeapTuple   tp;
     896             :     Form_pg_attribute att_tup;
     897             : 
     898        6138 :     tp = SearchSysCache2(ATTNUM,
     899             :                          ObjectIdGetDatum(relid),
     900             :                          Int16GetDatum(attnum));
     901        6138 :     if (!HeapTupleIsValid(tp))
     902           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     903             :              attnum, relid);
     904        6138 :     att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     905             : 
     906        6138 :     *typid = att_tup->atttypid;
     907        6138 :     *typmod = att_tup->atttypmod;
     908        6138 :     *collid = att_tup->attcollation;
     909        6138 :     ReleaseSysCache(tp);
     910        6138 : }
     911             : 
     912             : /*
     913             :  * get_attoptions
     914             :  *
     915             :  *      Given the relation id and the attribute number,
     916             :  *      return the attribute options text[] datum, if any.
     917             :  */
     918             : Datum
     919      447268 : get_attoptions(Oid relid, int16 attnum)
     920             : {
     921             :     HeapTuple   tuple;
     922             :     Datum       attopts;
     923             :     Datum       result;
     924             :     bool        isnull;
     925             : 
     926      447268 :     tuple = SearchSysCache2(ATTNUM,
     927             :                             ObjectIdGetDatum(relid),
     928             :                             Int16GetDatum(attnum));
     929             : 
     930      447268 :     if (!HeapTupleIsValid(tuple))
     931           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     932             :              attnum, relid);
     933             : 
     934      447268 :     attopts = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
     935             :                               &isnull);
     936             : 
     937      447268 :     if (isnull)
     938      447172 :         result = (Datum) 0;
     939             :     else
     940          96 :         result = datumCopy(attopts, false, -1); /* text[] */
     941             : 
     942      447268 :     ReleaseSysCache(tuple);
     943             : 
     944      447268 :     return result;
     945             : }
     946             : 
     947             : /*              ---------- PG_CAST CACHE ----------                  */
     948             : 
     949             : /*
     950             :  * get_cast_oid - given two type OIDs, look up a cast OID
     951             :  *
     952             :  * If missing_ok is false, throw an error if the cast is not found.  If
     953             :  * true, just return InvalidOid.
     954             :  */
     955             : Oid
     956          48 : get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
     957             : {
     958             :     Oid         oid;
     959             : 
     960          48 :     oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
     961             :                           ObjectIdGetDatum(sourcetypeid),
     962             :                           ObjectIdGetDatum(targettypeid));
     963          48 :     if (!OidIsValid(oid) && !missing_ok)
     964           4 :         ereport(ERROR,
     965             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
     966             :                  errmsg("cast from type %s to type %s does not exist",
     967             :                         format_type_be(sourcetypeid),
     968             :                         format_type_be(targettypeid))));
     969          44 :     return oid;
     970             : }
     971             : 
     972             : /*              ---------- COLLATION CACHE ----------                    */
     973             : 
     974             : /*
     975             :  * get_collation_name
     976             :  *      Returns the name of a given pg_collation entry.
     977             :  *
     978             :  * Returns a palloc'd copy of the string, or NULL if no such collation.
     979             :  *
     980             :  * NOTE: since collation name is not unique, be wary of code that uses this
     981             :  * for anything except preparing error messages.
     982             :  */
     983             : char *
     984         106 : get_collation_name(Oid colloid)
     985             : {
     986             :     HeapTuple   tp;
     987             : 
     988         106 :     tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
     989         106 :     if (HeapTupleIsValid(tp))
     990             :     {
     991         106 :         Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
     992             :         char       *result;
     993             : 
     994         106 :         result = pstrdup(NameStr(colltup->collname));
     995         106 :         ReleaseSysCache(tp);
     996         106 :         return result;
     997             :     }
     998             :     else
     999           0 :         return NULL;
    1000             : }
    1001             : 
    1002             : bool
    1003        3512 : get_collation_isdeterministic(Oid colloid)
    1004             : {
    1005             :     HeapTuple   tp;
    1006             :     Form_pg_collation colltup;
    1007             :     bool        result;
    1008             : 
    1009        3512 :     tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
    1010        3512 :     if (!HeapTupleIsValid(tp))
    1011           0 :         elog(ERROR, "cache lookup failed for collation %u", colloid);
    1012        3512 :     colltup = (Form_pg_collation) GETSTRUCT(tp);
    1013        3512 :     result = colltup->collisdeterministic;
    1014        3512 :     ReleaseSysCache(tp);
    1015        3512 :     return result;
    1016             : }
    1017             : 
    1018             : /*              ---------- CONSTRAINT CACHE ----------                   */
    1019             : 
    1020             : /*
    1021             :  * get_constraint_name
    1022             :  *      Returns the name of a given pg_constraint entry.
    1023             :  *
    1024             :  * Returns a palloc'd copy of the string, or NULL if no such constraint.
    1025             :  *
    1026             :  * NOTE: since constraint name is not unique, be wary of code that uses this
    1027             :  * for anything except preparing error messages.
    1028             :  */
    1029             : char *
    1030         356 : get_constraint_name(Oid conoid)
    1031             : {
    1032             :     HeapTuple   tp;
    1033             : 
    1034         356 :     tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
    1035         356 :     if (HeapTupleIsValid(tp))
    1036             :     {
    1037         356 :         Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
    1038             :         char       *result;
    1039             : 
    1040         356 :         result = pstrdup(NameStr(contup->conname));
    1041         356 :         ReleaseSysCache(tp);
    1042         356 :         return result;
    1043             :     }
    1044             :     else
    1045           0 :         return NULL;
    1046             : }
    1047             : 
    1048             : /*              ---------- LANGUAGE CACHE ----------                     */
    1049             : 
    1050             : char *
    1051          92 : get_language_name(Oid langoid, bool missing_ok)
    1052             : {
    1053             :     HeapTuple   tp;
    1054             : 
    1055          92 :     tp = SearchSysCache1(LANGOID, ObjectIdGetDatum(langoid));
    1056          92 :     if (HeapTupleIsValid(tp))
    1057             :     {
    1058          92 :         Form_pg_language lantup = (Form_pg_language) GETSTRUCT(tp);
    1059             :         char       *result;
    1060             : 
    1061          92 :         result = pstrdup(NameStr(lantup->lanname));
    1062          92 :         ReleaseSysCache(tp);
    1063          92 :         return result;
    1064             :     }
    1065             : 
    1066           0 :     if (!missing_ok)
    1067           0 :         elog(ERROR, "cache lookup failed for language %u",
    1068             :              langoid);
    1069           0 :     return NULL;
    1070             : }
    1071             : 
    1072             : /*              ---------- OPCLASS CACHE ----------                      */
    1073             : 
    1074             : /*
    1075             :  * get_opclass_family
    1076             :  *
    1077             :  *      Returns the OID of the operator family the opclass belongs to.
    1078             :  */
    1079             : Oid
    1080       29060 : get_opclass_family(Oid opclass)
    1081             : {
    1082             :     HeapTuple   tp;
    1083             :     Form_pg_opclass cla_tup;
    1084             :     Oid         result;
    1085             : 
    1086       29060 :     tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    1087       29060 :     if (!HeapTupleIsValid(tp))
    1088           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
    1089       29060 :     cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
    1090             : 
    1091       29060 :     result = cla_tup->opcfamily;
    1092       29060 :     ReleaseSysCache(tp);
    1093       29060 :     return result;
    1094             : }
    1095             : 
    1096             : /*
    1097             :  * get_opclass_input_type
    1098             :  *
    1099             :  *      Returns the OID of the datatype the opclass indexes.
    1100             :  */
    1101             : Oid
    1102       28762 : get_opclass_input_type(Oid opclass)
    1103             : {
    1104             :     HeapTuple   tp;
    1105             :     Form_pg_opclass cla_tup;
    1106             :     Oid         result;
    1107             : 
    1108       28762 :     tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    1109       28762 :     if (!HeapTupleIsValid(tp))
    1110           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
    1111       28762 :     cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
    1112             : 
    1113       28762 :     result = cla_tup->opcintype;
    1114       28762 :     ReleaseSysCache(tp);
    1115       28762 :     return result;
    1116             : }
    1117             : 
    1118             : /*
    1119             :  * get_opclass_opfamily_and_input_type
    1120             :  *
    1121             :  *      Returns the OID of the operator family the opclass belongs to,
    1122             :  *              the OID of the datatype the opclass indexes
    1123             :  */
    1124             : bool
    1125         496 : get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
    1126             : {
    1127             :     HeapTuple   tp;
    1128             :     Form_pg_opclass cla_tup;
    1129             : 
    1130         496 :     tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    1131         496 :     if (!HeapTupleIsValid(tp))
    1132           0 :         return false;
    1133             : 
    1134         496 :     cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
    1135             : 
    1136         496 :     *opfamily = cla_tup->opcfamily;
    1137         496 :     *opcintype = cla_tup->opcintype;
    1138             : 
    1139         496 :     ReleaseSysCache(tp);
    1140             : 
    1141         496 :     return true;
    1142             : }
    1143             : 
    1144             : /*              ---------- OPERATOR CACHE ----------                     */
    1145             : 
    1146             : /*
    1147             :  * get_opcode
    1148             :  *
    1149             :  *      Returns the regproc id of the routine used to implement an
    1150             :  *      operator given the operator oid.
    1151             :  */
    1152             : RegProcedure
    1153     1200310 : get_opcode(Oid opno)
    1154             : {
    1155             :     HeapTuple   tp;
    1156             : 
    1157     1200310 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1158     1200310 :     if (HeapTupleIsValid(tp))
    1159             :     {
    1160     1200310 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1161             :         RegProcedure result;
    1162             : 
    1163     1200310 :         result = optup->oprcode;
    1164     1200310 :         ReleaseSysCache(tp);
    1165     1200310 :         return result;
    1166             :     }
    1167             :     else
    1168           0 :         return (RegProcedure) InvalidOid;
    1169             : }
    1170             : 
    1171             : /*
    1172             :  * get_opname
    1173             :  *    returns the name of the operator with the given opno
    1174             :  *
    1175             :  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
    1176             :  */
    1177             : char *
    1178           8 : get_opname(Oid opno)
    1179             : {
    1180             :     HeapTuple   tp;
    1181             : 
    1182           8 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1183           8 :     if (HeapTupleIsValid(tp))
    1184             :     {
    1185           8 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1186             :         char       *result;
    1187             : 
    1188           8 :         result = pstrdup(NameStr(optup->oprname));
    1189           8 :         ReleaseSysCache(tp);
    1190           8 :         return result;
    1191             :     }
    1192             :     else
    1193           0 :         return NULL;
    1194             : }
    1195             : 
    1196             : /*
    1197             :  * get_op_rettype
    1198             :  *      Given operator oid, return the operator's result type.
    1199             :  */
    1200             : Oid
    1201          74 : get_op_rettype(Oid opno)
    1202             : {
    1203             :     HeapTuple   tp;
    1204             : 
    1205          74 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1206          74 :     if (HeapTupleIsValid(tp))
    1207             :     {
    1208          74 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1209             :         Oid         result;
    1210             : 
    1211          74 :         result = optup->oprresult;
    1212          74 :         ReleaseSysCache(tp);
    1213          74 :         return result;
    1214             :     }
    1215             :     else
    1216           0 :         return InvalidOid;
    1217             : }
    1218             : 
    1219             : /*
    1220             :  * op_input_types
    1221             :  *
    1222             :  *      Returns the left and right input datatypes for an operator
    1223             :  *      (InvalidOid if not relevant).
    1224             :  */
    1225             : void
    1226      269484 : op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
    1227             : {
    1228             :     HeapTuple   tp;
    1229             :     Form_pg_operator optup;
    1230             : 
    1231      269484 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1232      269484 :     if (!HeapTupleIsValid(tp))  /* shouldn't happen */
    1233           0 :         elog(ERROR, "cache lookup failed for operator %u", opno);
    1234      269484 :     optup = (Form_pg_operator) GETSTRUCT(tp);
    1235      269484 :     *lefttype = optup->oprleft;
    1236      269484 :     *righttype = optup->oprright;
    1237      269484 :     ReleaseSysCache(tp);
    1238      269484 : }
    1239             : 
    1240             : /*
    1241             :  * op_mergejoinable
    1242             :  *
    1243             :  * Returns true if the operator is potentially mergejoinable.  (The planner
    1244             :  * will fail to find any mergejoin plans unless there are suitable btree
    1245             :  * opfamily entries for this operator and associated sortops.  The pg_operator
    1246             :  * flag is just a hint to tell the planner whether to bother looking.)
    1247             :  *
    1248             :  * In some cases (currently only array_eq and record_eq), mergejoinability
    1249             :  * depends on the specific input data type the operator is invoked for, so
    1250             :  * that must be passed as well. We currently assume that only one input's type
    1251             :  * is needed to check this --- by convention, pass the left input's data type.
    1252             :  */
    1253             : bool
    1254      320994 : op_mergejoinable(Oid opno, Oid inputtype)
    1255             : {
    1256      320994 :     bool        result = false;
    1257             :     HeapTuple   tp;
    1258             :     TypeCacheEntry *typentry;
    1259             : 
    1260             :     /*
    1261             :      * For array_eq or record_eq, we can sort if the element or field types
    1262             :      * are all sortable.  We could implement all the checks for that here, but
    1263             :      * the typcache already does that and caches the results too, so let's
    1264             :      * rely on the typcache.
    1265             :      */
    1266      320994 :     if (opno == ARRAY_EQ_OP)
    1267             :     {
    1268         108 :         typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
    1269         108 :         if (typentry->cmp_proc == F_BTARRAYCMP)
    1270         108 :             result = true;
    1271             :     }
    1272      320886 :     else if (opno == RECORD_EQ_OP)
    1273             :     {
    1274          52 :         typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
    1275          52 :         if (typentry->cmp_proc == F_BTRECORDCMP)
    1276          52 :             result = true;
    1277             :     }
    1278             :     else
    1279             :     {
    1280             :         /* For all other operators, rely on pg_operator.oprcanmerge */
    1281      320834 :         tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1282      320834 :         if (HeapTupleIsValid(tp))
    1283             :         {
    1284      320834 :             Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1285             : 
    1286      320834 :             result = optup->oprcanmerge;
    1287      320834 :             ReleaseSysCache(tp);
    1288             :         }
    1289             :     }
    1290      320994 :     return result;
    1291             : }
    1292             : 
    1293             : /*
    1294             :  * op_hashjoinable
    1295             :  *
    1296             :  * Returns true if the operator is hashjoinable.  (There must be a suitable
    1297             :  * hash opfamily entry for this operator if it is so marked.)
    1298             :  *
    1299             :  * In some cases (currently only array_eq), hashjoinability depends on the
    1300             :  * specific input data type the operator is invoked for, so that must be
    1301             :  * passed as well.  We currently assume that only one input's type is needed
    1302             :  * to check this --- by convention, pass the left input's data type.
    1303             :  */
    1304             : bool
    1305      217558 : op_hashjoinable(Oid opno, Oid inputtype)
    1306             : {
    1307      217558 :     bool        result = false;
    1308             :     HeapTuple   tp;
    1309             :     TypeCacheEntry *typentry;
    1310             : 
    1311             :     /* As in op_mergejoinable, let the typcache handle the hard cases */
    1312             :     /* Eventually we'll need a similar case for record_eq ... */
    1313      217558 :     if (opno == ARRAY_EQ_OP)
    1314             :     {
    1315           0 :         typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
    1316           0 :         if (typentry->hash_proc == F_HASH_ARRAY)
    1317           0 :             result = true;
    1318             :     }
    1319             :     else
    1320             :     {
    1321             :         /* For all other operators, rely on pg_operator.oprcanhash */
    1322      217558 :         tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1323      217558 :         if (HeapTupleIsValid(tp))
    1324             :         {
    1325      217558 :             Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1326             : 
    1327      217558 :             result = optup->oprcanhash;
    1328      217558 :             ReleaseSysCache(tp);
    1329             :         }
    1330             :     }
    1331      217558 :     return result;
    1332             : }
    1333             : 
    1334             : /*
    1335             :  * op_strict
    1336             :  *
    1337             :  * Get the proisstrict flag for the operator's underlying function.
    1338             :  */
    1339             : bool
    1340      284860 : op_strict(Oid opno)
    1341             : {
    1342      284860 :     RegProcedure funcid = get_opcode(opno);
    1343             : 
    1344      284860 :     if (funcid == (RegProcedure) InvalidOid)
    1345           0 :         elog(ERROR, "operator %u does not exist", opno);
    1346             : 
    1347      284860 :     return func_strict((Oid) funcid);
    1348             : }
    1349             : 
    1350             : /*
    1351             :  * op_volatile
    1352             :  *
    1353             :  * Get the provolatile flag for the operator's underlying function.
    1354             :  */
    1355             : char
    1356       12508 : op_volatile(Oid opno)
    1357             : {
    1358       12508 :     RegProcedure funcid = get_opcode(opno);
    1359             : 
    1360       12508 :     if (funcid == (RegProcedure) InvalidOid)
    1361           0 :         elog(ERROR, "operator %u does not exist", opno);
    1362             : 
    1363       12508 :     return func_volatile((Oid) funcid);
    1364             : }
    1365             : 
    1366             : /*
    1367             :  * get_commutator
    1368             :  *
    1369             :  *      Returns the corresponding commutator of an operator.
    1370             :  */
    1371             : Oid
    1372       39472 : get_commutator(Oid opno)
    1373             : {
    1374             :     HeapTuple   tp;
    1375             : 
    1376       39472 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1377       39472 :     if (HeapTupleIsValid(tp))
    1378             :     {
    1379       39472 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1380             :         Oid         result;
    1381             : 
    1382       39472 :         result = optup->oprcom;
    1383       39472 :         ReleaseSysCache(tp);
    1384       39472 :         return result;
    1385             :     }
    1386             :     else
    1387           0 :         return InvalidOid;
    1388             : }
    1389             : 
    1390             : /*
    1391             :  * get_negator
    1392             :  *
    1393             :  *      Returns the corresponding negator of an operator.
    1394             :  */
    1395             : Oid
    1396       28318 : get_negator(Oid opno)
    1397             : {
    1398             :     HeapTuple   tp;
    1399             : 
    1400       28318 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1401       28318 :     if (HeapTupleIsValid(tp))
    1402             :     {
    1403       28318 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1404             :         Oid         result;
    1405             : 
    1406       28318 :         result = optup->oprnegate;
    1407       28318 :         ReleaseSysCache(tp);
    1408       28318 :         return result;
    1409             :     }
    1410             :     else
    1411           0 :         return InvalidOid;
    1412             : }
    1413             : 
    1414             : /*
    1415             :  * get_oprrest
    1416             :  *
    1417             :  *      Returns procedure id for computing selectivity of an operator.
    1418             :  */
    1419             : RegProcedure
    1420      614414 : get_oprrest(Oid opno)
    1421             : {
    1422             :     HeapTuple   tp;
    1423             : 
    1424      614414 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1425      614414 :     if (HeapTupleIsValid(tp))
    1426             :     {
    1427      614414 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1428             :         RegProcedure result;
    1429             : 
    1430      614414 :         result = optup->oprrest;
    1431      614414 :         ReleaseSysCache(tp);
    1432      614414 :         return result;
    1433             :     }
    1434             :     else
    1435           0 :         return (RegProcedure) InvalidOid;
    1436             : }
    1437             : 
    1438             : /*
    1439             :  * get_oprjoin
    1440             :  *
    1441             :  *      Returns procedure id for computing selectivity of a join.
    1442             :  */
    1443             : RegProcedure
    1444      127704 : get_oprjoin(Oid opno)
    1445             : {
    1446             :     HeapTuple   tp;
    1447             : 
    1448      127704 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1449      127704 :     if (HeapTupleIsValid(tp))
    1450             :     {
    1451      127704 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1452             :         RegProcedure result;
    1453             : 
    1454      127704 :         result = optup->oprjoin;
    1455      127704 :         ReleaseSysCache(tp);
    1456      127704 :         return result;
    1457             :     }
    1458             :     else
    1459           0 :         return (RegProcedure) InvalidOid;
    1460             : }
    1461             : 
    1462             : /*              ---------- FUNCTION CACHE ----------                     */
    1463             : 
    1464             : /*
    1465             :  * get_func_name
    1466             :  *    returns the name of the function with the given funcid
    1467             :  *
    1468             :  * Note: returns a palloc'd copy of the string, or NULL if no such function.
    1469             :  */
    1470             : char *
    1471         282 : get_func_name(Oid funcid)
    1472             : {
    1473             :     HeapTuple   tp;
    1474             : 
    1475         282 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1476         282 :     if (HeapTupleIsValid(tp))
    1477             :     {
    1478         282 :         Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
    1479             :         char       *result;
    1480             : 
    1481         282 :         result = pstrdup(NameStr(functup->proname));
    1482         282 :         ReleaseSysCache(tp);
    1483         282 :         return result;
    1484             :     }
    1485             :     else
    1486           0 :         return NULL;
    1487             : }
    1488             : 
    1489             : /*
    1490             :  * get_func_namespace
    1491             :  *
    1492             :  *      Returns the pg_namespace OID associated with a given function.
    1493             :  */
    1494             : Oid
    1495          50 : get_func_namespace(Oid funcid)
    1496             : {
    1497             :     HeapTuple   tp;
    1498             : 
    1499          50 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1500          50 :     if (HeapTupleIsValid(tp))
    1501             :     {
    1502          50 :         Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
    1503             :         Oid         result;
    1504             : 
    1505          50 :         result = functup->pronamespace;
    1506          50 :         ReleaseSysCache(tp);
    1507          50 :         return result;
    1508             :     }
    1509             :     else
    1510           0 :         return InvalidOid;
    1511             : }
    1512             : 
    1513             : /*
    1514             :  * get_func_rettype
    1515             :  *      Given procedure id, return the function's result type.
    1516             :  */
    1517             : Oid
    1518       14914 : get_func_rettype(Oid funcid)
    1519             : {
    1520             :     HeapTuple   tp;
    1521             :     Oid         result;
    1522             : 
    1523       14914 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1524       14914 :     if (!HeapTupleIsValid(tp))
    1525           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1526             : 
    1527       14914 :     result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
    1528       14914 :     ReleaseSysCache(tp);
    1529       14914 :     return result;
    1530             : }
    1531             : 
    1532             : /*
    1533             :  * get_func_nargs
    1534             :  *      Given procedure id, return the number of arguments.
    1535             :  */
    1536             : int
    1537           0 : get_func_nargs(Oid funcid)
    1538             : {
    1539             :     HeapTuple   tp;
    1540             :     int         result;
    1541             : 
    1542           0 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1543           0 :     if (!HeapTupleIsValid(tp))
    1544           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1545             : 
    1546           0 :     result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
    1547           0 :     ReleaseSysCache(tp);
    1548           0 :     return result;
    1549             : }
    1550             : 
    1551             : /*
    1552             :  * get_func_signature
    1553             :  *      Given procedure id, return the function's argument and result types.
    1554             :  *      (The return value is the result type.)
    1555             :  *
    1556             :  * The arguments are returned as a palloc'd array.
    1557             :  */
    1558             : Oid
    1559         738 : get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
    1560             : {
    1561             :     HeapTuple   tp;
    1562             :     Form_pg_proc procstruct;
    1563             :     Oid         result;
    1564             : 
    1565         738 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1566         738 :     if (!HeapTupleIsValid(tp))
    1567           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1568             : 
    1569         738 :     procstruct = (Form_pg_proc) GETSTRUCT(tp);
    1570             : 
    1571         738 :     result = procstruct->prorettype;
    1572         738 :     *nargs = (int) procstruct->pronargs;
    1573             :     Assert(*nargs == procstruct->proargtypes.dim1);
    1574         738 :     *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
    1575         738 :     memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
    1576             : 
    1577         738 :     ReleaseSysCache(tp);
    1578         738 :     return result;
    1579             : }
    1580             : 
    1581             : /*
    1582             :  * get_func_variadictype
    1583             :  *      Given procedure id, return the function's provariadic field.
    1584             :  */
    1585             : Oid
    1586         190 : get_func_variadictype(Oid funcid)
    1587             : {
    1588             :     HeapTuple   tp;
    1589             :     Oid         result;
    1590             : 
    1591         190 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1592         190 :     if (!HeapTupleIsValid(tp))
    1593           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1594             : 
    1595         190 :     result = ((Form_pg_proc) GETSTRUCT(tp))->provariadic;
    1596         190 :     ReleaseSysCache(tp);
    1597         190 :     return result;
    1598             : }
    1599             : 
    1600             : /*
    1601             :  * get_func_retset
    1602             :  *      Given procedure id, return the function's proretset flag.
    1603             :  */
    1604             : bool
    1605      599322 : get_func_retset(Oid funcid)
    1606             : {
    1607             :     HeapTuple   tp;
    1608             :     bool        result;
    1609             : 
    1610      599322 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1611      599322 :     if (!HeapTupleIsValid(tp))
    1612           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1613             : 
    1614      599322 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
    1615      599322 :     ReleaseSysCache(tp);
    1616      599322 :     return result;
    1617             : }
    1618             : 
    1619             : /*
    1620             :  * func_strict
    1621             :  *      Given procedure id, return the function's proisstrict flag.
    1622             :  */
    1623             : bool
    1624      511408 : func_strict(Oid funcid)
    1625             : {
    1626             :     HeapTuple   tp;
    1627             :     bool        result;
    1628             : 
    1629      511408 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1630      511408 :     if (!HeapTupleIsValid(tp))
    1631           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1632             : 
    1633      511408 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
    1634      511408 :     ReleaseSysCache(tp);
    1635      511408 :     return result;
    1636             : }
    1637             : 
    1638             : /*
    1639             :  * func_volatile
    1640             :  *      Given procedure id, return the function's provolatile flag.
    1641             :  */
    1642             : char
    1643      663890 : func_volatile(Oid funcid)
    1644             : {
    1645             :     HeapTuple   tp;
    1646             :     char        result;
    1647             : 
    1648      663890 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1649      663890 :     if (!HeapTupleIsValid(tp))
    1650           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1651             : 
    1652      663890 :     result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
    1653      663890 :     ReleaseSysCache(tp);
    1654      663890 :     return result;
    1655             : }
    1656             : 
    1657             : /*
    1658             :  * func_parallel
    1659             :  *      Given procedure id, return the function's proparallel flag.
    1660             :  */
    1661             : char
    1662      929080 : func_parallel(Oid funcid)
    1663             : {
    1664             :     HeapTuple   tp;
    1665             :     char        result;
    1666             : 
    1667      929080 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1668      929080 :     if (!HeapTupleIsValid(tp))
    1669           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1670             : 
    1671      929080 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proparallel;
    1672      929080 :     ReleaseSysCache(tp);
    1673      929080 :     return result;
    1674             : }
    1675             : 
    1676             : /*
    1677             :  * get_func_prokind
    1678             :  *     Given procedure id, return the routine kind.
    1679             :  */
    1680             : char
    1681       23012 : get_func_prokind(Oid funcid)
    1682             : {
    1683             :     HeapTuple   tp;
    1684             :     char        result;
    1685             : 
    1686       23012 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1687       23012 :     if (!HeapTupleIsValid(tp))
    1688           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1689             : 
    1690       23012 :     result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
    1691       23012 :     ReleaseSysCache(tp);
    1692       23012 :     return result;
    1693             : }
    1694             : 
    1695             : /*
    1696             :  * get_func_leakproof
    1697             :  *     Given procedure id, return the function's leakproof field.
    1698             :  */
    1699             : bool
    1700        4324 : get_func_leakproof(Oid funcid)
    1701             : {
    1702             :     HeapTuple   tp;
    1703             :     bool        result;
    1704             : 
    1705        4324 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1706        4324 :     if (!HeapTupleIsValid(tp))
    1707           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1708             : 
    1709        4324 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
    1710        4324 :     ReleaseSysCache(tp);
    1711        4324 :     return result;
    1712             : }
    1713             : 
    1714             : /*
    1715             :  * get_func_support
    1716             :  *
    1717             :  *      Returns the support function OID associated with a given function,
    1718             :  *      or InvalidOid if there is none.
    1719             :  */
    1720             : RegProcedure
    1721       15124 : get_func_support(Oid funcid)
    1722             : {
    1723             :     HeapTuple   tp;
    1724             : 
    1725       15124 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1726       15124 :     if (HeapTupleIsValid(tp))
    1727             :     {
    1728       15124 :         Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
    1729             :         RegProcedure result;
    1730             : 
    1731       15124 :         result = functup->prosupport;
    1732       15124 :         ReleaseSysCache(tp);
    1733       15124 :         return result;
    1734             :     }
    1735             :     else
    1736           0 :         return (RegProcedure) InvalidOid;
    1737             : }
    1738             : 
    1739             : /*              ---------- RELATION CACHE ----------                     */
    1740             : 
    1741             : /*
    1742             :  * get_relname_relid
    1743             :  *      Given name and namespace of a relation, look up the OID.
    1744             :  *
    1745             :  * Returns InvalidOid if there is no such relation.
    1746             :  */
    1747             : Oid
    1748     1163902 : get_relname_relid(const char *relname, Oid relnamespace)
    1749             : {
    1750     1163902 :     return GetSysCacheOid2(RELNAMENSP, Anum_pg_class_oid,
    1751             :                            PointerGetDatum(relname),
    1752             :                            ObjectIdGetDatum(relnamespace));
    1753             : }
    1754             : 
    1755             : #ifdef NOT_USED
    1756             : /*
    1757             :  * get_relnatts
    1758             :  *
    1759             :  *      Returns the number of attributes for a given relation.
    1760             :  */
    1761             : int
    1762             : get_relnatts(Oid relid)
    1763             : {
    1764             :     HeapTuple   tp;
    1765             : 
    1766             :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1767             :     if (HeapTupleIsValid(tp))
    1768             :     {
    1769             :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1770             :         int         result;
    1771             : 
    1772             :         result = reltup->relnatts;
    1773             :         ReleaseSysCache(tp);
    1774             :         return result;
    1775             :     }
    1776             :     else
    1777             :         return InvalidAttrNumber;
    1778             : }
    1779             : #endif
    1780             : 
    1781             : /*
    1782             :  * get_rel_name
    1783             :  *      Returns the name of a given relation.
    1784             :  *
    1785             :  * Returns a palloc'd copy of the string, or NULL if no such relation.
    1786             :  *
    1787             :  * NOTE: since relation name is not unique, be wary of code that uses this
    1788             :  * for anything except preparing error messages.
    1789             :  */
    1790             : char *
    1791       47066 : get_rel_name(Oid relid)
    1792             : {
    1793             :     HeapTuple   tp;
    1794             : 
    1795       47066 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1796       47066 :     if (HeapTupleIsValid(tp))
    1797             :     {
    1798       47058 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1799             :         char       *result;
    1800             : 
    1801       47058 :         result = pstrdup(NameStr(reltup->relname));
    1802       47058 :         ReleaseSysCache(tp);
    1803       47058 :         return result;
    1804             :     }
    1805             :     else
    1806           8 :         return NULL;
    1807             : }
    1808             : 
    1809             : /*
    1810             :  * get_rel_namespace
    1811             :  *
    1812             :  *      Returns the pg_namespace OID associated with a given relation.
    1813             :  */
    1814             : Oid
    1815      300272 : get_rel_namespace(Oid relid)
    1816             : {
    1817             :     HeapTuple   tp;
    1818             : 
    1819      300272 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1820      300272 :     if (HeapTupleIsValid(tp))
    1821             :     {
    1822      300272 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1823             :         Oid         result;
    1824             : 
    1825      300272 :         result = reltup->relnamespace;
    1826      300272 :         ReleaseSysCache(tp);
    1827      300272 :         return result;
    1828             :     }
    1829             :     else
    1830           0 :         return InvalidOid;
    1831             : }
    1832             : 
    1833             : /*
    1834             :  * get_rel_type_id
    1835             :  *
    1836             :  *      Returns the pg_type OID associated with a given relation.
    1837             :  *
    1838             :  * Note: not all pg_class entries have associated pg_type OIDs; so be
    1839             :  * careful to check for InvalidOid result.
    1840             :  */
    1841             : Oid
    1842       21750 : get_rel_type_id(Oid relid)
    1843             : {
    1844             :     HeapTuple   tp;
    1845             : 
    1846       21750 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1847       21750 :     if (HeapTupleIsValid(tp))
    1848             :     {
    1849       21750 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1850             :         Oid         result;
    1851             : 
    1852       21750 :         result = reltup->reltype;
    1853       21750 :         ReleaseSysCache(tp);
    1854       21750 :         return result;
    1855             :     }
    1856             :     else
    1857           0 :         return InvalidOid;
    1858             : }
    1859             : 
    1860             : /*
    1861             :  * get_rel_relkind
    1862             :  *
    1863             :  *      Returns the relkind associated with a given relation.
    1864             :  */
    1865             : char
    1866       77462 : get_rel_relkind(Oid relid)
    1867             : {
    1868             :     HeapTuple   tp;
    1869             : 
    1870       77462 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1871       77462 :     if (HeapTupleIsValid(tp))
    1872             :     {
    1873       77462 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1874             :         char        result;
    1875             : 
    1876       77462 :         result = reltup->relkind;
    1877       77462 :         ReleaseSysCache(tp);
    1878       77462 :         return result;
    1879             :     }
    1880             :     else
    1881           0 :         return '\0';
    1882             : }
    1883             : 
    1884             : /*
    1885             :  * get_rel_relispartition
    1886             :  *
    1887             :  *      Returns the relispartition flag associated with a given relation.
    1888             :  */
    1889             : bool
    1890        5288 : get_rel_relispartition(Oid relid)
    1891             : {
    1892             :     HeapTuple   tp;
    1893             : 
    1894        5288 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1895        5288 :     if (HeapTupleIsValid(tp))
    1896             :     {
    1897        5288 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1898             :         bool        result;
    1899             : 
    1900        5288 :         result = reltup->relispartition;
    1901        5288 :         ReleaseSysCache(tp);
    1902        5288 :         return result;
    1903             :     }
    1904             :     else
    1905           0 :         return false;
    1906             : }
    1907             : 
    1908             : /*
    1909             :  * get_rel_tablespace
    1910             :  *
    1911             :  *      Returns the pg_tablespace OID associated with a given relation.
    1912             :  *
    1913             :  * Note: InvalidOid might mean either that we couldn't find the relation,
    1914             :  * or that it is in the database's default tablespace.
    1915             :  */
    1916             : Oid
    1917        4248 : get_rel_tablespace(Oid relid)
    1918             : {
    1919             :     HeapTuple   tp;
    1920             : 
    1921        4248 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1922        4248 :     if (HeapTupleIsValid(tp))
    1923             :     {
    1924        4248 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1925             :         Oid         result;
    1926             : 
    1927        4248 :         result = reltup->reltablespace;
    1928        4248 :         ReleaseSysCache(tp);
    1929        4248 :         return result;
    1930             :     }
    1931             :     else
    1932           0 :         return InvalidOid;
    1933             : }
    1934             : 
    1935             : /*
    1936             :  * get_rel_persistence
    1937             :  *
    1938             :  *      Returns the relpersistence associated with a given relation.
    1939             :  */
    1940             : char
    1941      195640 : get_rel_persistence(Oid relid)
    1942             : {
    1943             :     HeapTuple   tp;
    1944             :     Form_pg_class reltup;
    1945             :     char        result;
    1946             : 
    1947      195640 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1948      195640 :     if (!HeapTupleIsValid(tp))
    1949           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    1950      195640 :     reltup = (Form_pg_class) GETSTRUCT(tp);
    1951      195640 :     result = reltup->relpersistence;
    1952      195640 :     ReleaseSysCache(tp);
    1953             : 
    1954      195640 :     return result;
    1955             : }
    1956             : 
    1957             : 
    1958             : /*              ---------- TRANSFORM CACHE ----------                        */
    1959             : 
    1960             : Oid
    1961        1536 : get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
    1962             : {
    1963             :     HeapTuple   tup;
    1964             : 
    1965        1536 :     if (!list_member_oid(trftypes, typid))
    1966        1374 :         return InvalidOid;
    1967             : 
    1968         162 :     tup = SearchSysCache2(TRFTYPELANG, typid, langid);
    1969         162 :     if (HeapTupleIsValid(tup))
    1970             :     {
    1971             :         Oid         funcid;
    1972             : 
    1973         162 :         funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
    1974         162 :         ReleaseSysCache(tup);
    1975         162 :         return funcid;
    1976             :     }
    1977             :     else
    1978           0 :         return InvalidOid;
    1979             : }
    1980             : 
    1981             : Oid
    1982        2002 : get_transform_tosql(Oid typid, Oid langid, List *trftypes)
    1983             : {
    1984             :     HeapTuple   tup;
    1985             : 
    1986        2002 :     if (!list_member_oid(trftypes, typid))
    1987        1822 :         return InvalidOid;
    1988             : 
    1989         180 :     tup = SearchSysCache2(TRFTYPELANG, typid, langid);
    1990         180 :     if (HeapTupleIsValid(tup))
    1991             :     {
    1992             :         Oid         funcid;
    1993             : 
    1994         180 :         funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
    1995         180 :         ReleaseSysCache(tup);
    1996         180 :         return funcid;
    1997             :     }
    1998             :     else
    1999           0 :         return InvalidOid;
    2000             : }
    2001             : 
    2002             : 
    2003             : /*              ---------- TYPE CACHE ----------                         */
    2004             : 
    2005             : /*
    2006             :  * get_typisdefined
    2007             :  *
    2008             :  *      Given the type OID, determine whether the type is defined
    2009             :  *      (if not, it's only a shell).
    2010             :  */
    2011             : bool
    2012         194 : get_typisdefined(Oid typid)
    2013             : {
    2014             :     HeapTuple   tp;
    2015             : 
    2016         194 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2017         194 :     if (HeapTupleIsValid(tp))
    2018             :     {
    2019         194 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2020             :         bool        result;
    2021             : 
    2022         194 :         result = typtup->typisdefined;
    2023         194 :         ReleaseSysCache(tp);
    2024         194 :         return result;
    2025             :     }
    2026             :     else
    2027           0 :         return false;
    2028             : }
    2029             : 
    2030             : /*
    2031             :  * get_typlen
    2032             :  *
    2033             :  *      Given the type OID, return the length of the type.
    2034             :  */
    2035             : int16
    2036     1774442 : get_typlen(Oid typid)
    2037             : {
    2038             :     HeapTuple   tp;
    2039             : 
    2040     1774442 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2041     1774442 :     if (HeapTupleIsValid(tp))
    2042             :     {
    2043     1774442 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2044             :         int16       result;
    2045             : 
    2046     1774442 :         result = typtup->typlen;
    2047     1774442 :         ReleaseSysCache(tp);
    2048     1774442 :         return result;
    2049             :     }
    2050             :     else
    2051           0 :         return 0;
    2052             : }
    2053             : 
    2054             : /*
    2055             :  * get_typbyval
    2056             :  *
    2057             :  *      Given the type OID, determine whether the type is returned by value or
    2058             :  *      not.  Returns true if by value, false if by reference.
    2059             :  */
    2060             : bool
    2061       29524 : get_typbyval(Oid typid)
    2062             : {
    2063             :     HeapTuple   tp;
    2064             : 
    2065       29524 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2066       29524 :     if (HeapTupleIsValid(tp))
    2067             :     {
    2068       29524 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2069             :         bool        result;
    2070             : 
    2071       29524 :         result = typtup->typbyval;
    2072       29524 :         ReleaseSysCache(tp);
    2073       29524 :         return result;
    2074             :     }
    2075             :     else
    2076           0 :         return false;
    2077             : }
    2078             : 
    2079             : /*
    2080             :  * get_typlenbyval
    2081             :  *
    2082             :  *      A two-fer: given the type OID, return both typlen and typbyval.
    2083             :  *
    2084             :  *      Since both pieces of info are needed to know how to copy a Datum,
    2085             :  *      many places need both.  Might as well get them with one cache lookup
    2086             :  *      instead of two.  Also, this routine raises an error instead of
    2087             :  *      returning a bogus value when given a bad type OID.
    2088             :  */
    2089             : void
    2090      399288 : get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
    2091             : {
    2092             :     HeapTuple   tp;
    2093             :     Form_pg_type typtup;
    2094             : 
    2095      399288 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2096      399288 :     if (!HeapTupleIsValid(tp))
    2097           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2098      399288 :     typtup = (Form_pg_type) GETSTRUCT(tp);
    2099      399288 :     *typlen = typtup->typlen;
    2100      399288 :     *typbyval = typtup->typbyval;
    2101      399288 :     ReleaseSysCache(tp);
    2102      399288 : }
    2103             : 
    2104             : /*
    2105             :  * get_typlenbyvalalign
    2106             :  *
    2107             :  *      A three-fer: given the type OID, return typlen, typbyval, typalign.
    2108             :  */
    2109             : void
    2110     2511868 : get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
    2111             :                      char *typalign)
    2112             : {
    2113             :     HeapTuple   tp;
    2114             :     Form_pg_type typtup;
    2115             : 
    2116     2511868 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2117     2511868 :     if (!HeapTupleIsValid(tp))
    2118           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2119     2511868 :     typtup = (Form_pg_type) GETSTRUCT(tp);
    2120     2511868 :     *typlen = typtup->typlen;
    2121     2511868 :     *typbyval = typtup->typbyval;
    2122     2511868 :     *typalign = typtup->typalign;
    2123     2511868 :     ReleaseSysCache(tp);
    2124     2511868 : }
    2125             : 
    2126             : /*
    2127             :  * getTypeIOParam
    2128             :  *      Given a pg_type row, select the type OID to pass to I/O functions
    2129             :  *
    2130             :  * Formerly, all I/O functions were passed pg_type.typelem as their second
    2131             :  * parameter, but we now have a more complex rule about what to pass.
    2132             :  * This knowledge is intended to be centralized here --- direct references
    2133             :  * to typelem elsewhere in the code are wrong, if they are associated with
    2134             :  * I/O calls and not with actual subscripting operations!  (But see
    2135             :  * bootstrap.c's boot_get_type_io_data() if you need to change this.)
    2136             :  *
    2137             :  * As of PostgreSQL 8.1, output functions receive only the value itself
    2138             :  * and not any auxiliary parameters, so the name of this routine is now
    2139             :  * a bit of a misnomer ... it should be getTypeInputParam.
    2140             :  */
    2141             : Oid
    2142      908578 : getTypeIOParam(HeapTuple typeTuple)
    2143             : {
    2144      908578 :     Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
    2145             : 
    2146             :     /*
    2147             :      * Array types get their typelem as parameter; everybody else gets their
    2148             :      * own type OID as parameter.
    2149             :      */
    2150      908578 :     if (OidIsValid(typeStruct->typelem))
    2151      100708 :         return typeStruct->typelem;
    2152             :     else
    2153      807870 :         return typeStruct->oid;
    2154             : }
    2155             : 
    2156             : /*
    2157             :  * get_type_io_data
    2158             :  *
    2159             :  *      A six-fer:  given the type OID, return typlen, typbyval, typalign,
    2160             :  *                  typdelim, typioparam, and IO function OID. The IO function
    2161             :  *                  returned is controlled by IOFuncSelector
    2162             :  */
    2163             : void
    2164      141572 : get_type_io_data(Oid typid,
    2165             :                  IOFuncSelector which_func,
    2166             :                  int16 *typlen,
    2167             :                  bool *typbyval,
    2168             :                  char *typalign,
    2169             :                  char *typdelim,
    2170             :                  Oid *typioparam,
    2171             :                  Oid *func)
    2172             : {
    2173             :     HeapTuple   typeTuple;
    2174             :     Form_pg_type typeStruct;
    2175             : 
    2176             :     /*
    2177             :      * In bootstrap mode, pass it off to bootstrap.c.  This hack allows us to
    2178             :      * use array_in and array_out during bootstrap.
    2179             :      */
    2180      141572 :     if (IsBootstrapProcessingMode())
    2181             :     {
    2182             :         Oid         typinput;
    2183             :         Oid         typoutput;
    2184             : 
    2185      114202 :         boot_get_type_io_data(typid,
    2186             :                               typlen,
    2187             :                               typbyval,
    2188             :                               typalign,
    2189             :                               typdelim,
    2190             :                               typioparam,
    2191             :                               &typinput,
    2192             :                               &typoutput);
    2193      114202 :         switch (which_func)
    2194             :         {
    2195      114202 :             case IOFunc_input:
    2196      114202 :                 *func = typinput;
    2197      114202 :                 break;
    2198           0 :             case IOFunc_output:
    2199           0 :                 *func = typoutput;
    2200           0 :                 break;
    2201           0 :             default:
    2202           0 :                 elog(ERROR, "binary I/O not supported during bootstrap");
    2203             :                 break;
    2204             :         }
    2205      114202 :         return;
    2206             :     }
    2207             : 
    2208       27370 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2209       27370 :     if (!HeapTupleIsValid(typeTuple))
    2210           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2211       27370 :     typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
    2212             : 
    2213       27370 :     *typlen = typeStruct->typlen;
    2214       27370 :     *typbyval = typeStruct->typbyval;
    2215       27370 :     *typalign = typeStruct->typalign;
    2216       27370 :     *typdelim = typeStruct->typdelim;
    2217       27370 :     *typioparam = getTypeIOParam(typeTuple);
    2218       27370 :     switch (which_func)
    2219             :     {
    2220       16564 :         case IOFunc_input:
    2221       16564 :             *func = typeStruct->typinput;
    2222       16564 :             break;
    2223       10806 :         case IOFunc_output:
    2224       10806 :             *func = typeStruct->typoutput;
    2225       10806 :             break;
    2226           0 :         case IOFunc_receive:
    2227           0 :             *func = typeStruct->typreceive;
    2228           0 :             break;
    2229           0 :         case IOFunc_send:
    2230           0 :             *func = typeStruct->typsend;
    2231           0 :             break;
    2232             :     }
    2233       27370 :     ReleaseSysCache(typeTuple);
    2234             : }
    2235             : 
    2236             : #ifdef NOT_USED
    2237             : char
    2238             : get_typalign(Oid typid)
    2239             : {
    2240             :     HeapTuple   tp;
    2241             : 
    2242             :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2243             :     if (HeapTupleIsValid(tp))
    2244             :     {
    2245             :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2246             :         char        result;
    2247             : 
    2248             :         result = typtup->typalign;
    2249             :         ReleaseSysCache(tp);
    2250             :         return result;
    2251             :     }
    2252             :     else
    2253             :         return TYPALIGN_INT;
    2254             : }
    2255             : #endif
    2256             : 
    2257             : char
    2258       37184 : get_typstorage(Oid typid)
    2259             : {
    2260             :     HeapTuple   tp;
    2261             : 
    2262       37184 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2263       37184 :     if (HeapTupleIsValid(tp))
    2264             :     {
    2265       37184 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2266             :         char        result;
    2267             : 
    2268       37184 :         result = typtup->typstorage;
    2269       37184 :         ReleaseSysCache(tp);
    2270       37184 :         return result;
    2271             :     }
    2272             :     else
    2273           0 :         return TYPSTORAGE_PLAIN;
    2274             : }
    2275             : 
    2276             : /*
    2277             :  * get_typdefault
    2278             :  *    Given a type OID, return the type's default value, if any.
    2279             :  *
    2280             :  *    The result is a palloc'd expression node tree, or NULL if there
    2281             :  *    is no defined default for the datatype.
    2282             :  *
    2283             :  * NB: caller should be prepared to coerce result to correct datatype;
    2284             :  * the returned expression tree might produce something of the wrong type.
    2285             :  */
    2286             : Node *
    2287       15602 : get_typdefault(Oid typid)
    2288             : {
    2289             :     HeapTuple   typeTuple;
    2290             :     Form_pg_type type;
    2291             :     Datum       datum;
    2292             :     bool        isNull;
    2293             :     Node       *expr;
    2294             : 
    2295       15602 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2296       15602 :     if (!HeapTupleIsValid(typeTuple))
    2297           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2298       15602 :     type = (Form_pg_type) GETSTRUCT(typeTuple);
    2299             : 
    2300             :     /*
    2301             :      * typdefault and typdefaultbin are potentially null, so don't try to
    2302             :      * access 'em as struct fields. Must do it the hard way with
    2303             :      * SysCacheGetAttr.
    2304             :      */
    2305       15602 :     datum = SysCacheGetAttr(TYPEOID,
    2306             :                             typeTuple,
    2307             :                             Anum_pg_type_typdefaultbin,
    2308             :                             &isNull);
    2309             : 
    2310       15602 :     if (!isNull)
    2311             :     {
    2312             :         /* We have an expression default */
    2313         138 :         expr = stringToNode(TextDatumGetCString(datum));
    2314             :     }
    2315             :     else
    2316             :     {
    2317             :         /* Perhaps we have a plain literal default */
    2318       15464 :         datum = SysCacheGetAttr(TYPEOID,
    2319             :                                 typeTuple,
    2320             :                                 Anum_pg_type_typdefault,
    2321             :                                 &isNull);
    2322             : 
    2323       15464 :         if (!isNull)
    2324             :         {
    2325             :             char       *strDefaultVal;
    2326             : 
    2327             :             /* Convert text datum to C string */
    2328           8 :             strDefaultVal = TextDatumGetCString(datum);
    2329             :             /* Convert C string to a value of the given type */
    2330           8 :             datum = OidInputFunctionCall(type->typinput, strDefaultVal,
    2331             :                                          getTypeIOParam(typeTuple), -1);
    2332             :             /* Build a Const node containing the value */
    2333          16 :             expr = (Node *) makeConst(typid,
    2334             :                                       -1,
    2335             :                                       type->typcollation,
    2336           8 :                                       type->typlen,
    2337             :                                       datum,
    2338             :                                       false,
    2339           8 :                                       type->typbyval);
    2340           8 :             pfree(strDefaultVal);
    2341             :         }
    2342             :         else
    2343             :         {
    2344             :             /* No default */
    2345       15456 :             expr = NULL;
    2346             :         }
    2347             :     }
    2348             : 
    2349       15602 :     ReleaseSysCache(typeTuple);
    2350             : 
    2351       15602 :     return expr;
    2352             : }
    2353             : 
    2354             : /*
    2355             :  * getBaseType
    2356             :  *      If the given type is a domain, return its base type;
    2357             :  *      otherwise return the type's own OID.
    2358             :  */
    2359             : Oid
    2360     4600650 : getBaseType(Oid typid)
    2361             : {
    2362     4600650 :     int32       typmod = -1;
    2363             : 
    2364     4600650 :     return getBaseTypeAndTypmod(typid, &typmod);
    2365             : }
    2366             : 
    2367             : /*
    2368             :  * getBaseTypeAndTypmod
    2369             :  *      If the given type is a domain, return its base type and typmod;
    2370             :  *      otherwise return the type's own OID, and leave *typmod unchanged.
    2371             :  *
    2372             :  * Note that the "applied typmod" should be -1 for every domain level
    2373             :  * above the bottommost; therefore, if the passed-in typid is indeed
    2374             :  * a domain, *typmod should be -1.
    2375             :  */
    2376             : Oid
    2377     7325118 : getBaseTypeAndTypmod(Oid typid, int32 *typmod)
    2378             : {
    2379             :     /*
    2380             :      * We loop to find the bottom base type in a stack of domains.
    2381             :      */
    2382             :     for (;;)
    2383     1009694 :     {
    2384             :         HeapTuple   tup;
    2385             :         Form_pg_type typTup;
    2386             : 
    2387     7325118 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2388     7325118 :         if (!HeapTupleIsValid(tup))
    2389           0 :             elog(ERROR, "cache lookup failed for type %u", typid);
    2390     7325118 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2391     7325118 :         if (typTup->typtype != TYPTYPE_DOMAIN)
    2392             :         {
    2393             :             /* Not a domain, so done */
    2394     6315424 :             ReleaseSysCache(tup);
    2395     6315424 :             break;
    2396             :         }
    2397             : 
    2398             :         Assert(*typmod == -1);
    2399     1009694 :         typid = typTup->typbasetype;
    2400     1009694 :         *typmod = typTup->typtypmod;
    2401             : 
    2402     1009694 :         ReleaseSysCache(tup);
    2403             :     }
    2404             : 
    2405     6315424 :     return typid;
    2406             : }
    2407             : 
    2408             : /*
    2409             :  * get_typavgwidth
    2410             :  *
    2411             :  *    Given a type OID and a typmod value (pass -1 if typmod is unknown),
    2412             :  *    estimate the average width of values of the type.  This is used by
    2413             :  *    the planner, which doesn't require absolutely correct results;
    2414             :  *    it's OK (and expected) to guess if we don't know for sure.
    2415             :  */
    2416             : int32
    2417     1079922 : get_typavgwidth(Oid typid, int32 typmod)
    2418             : {
    2419     1079922 :     int         typlen = get_typlen(typid);
    2420             :     int32       maxwidth;
    2421             : 
    2422             :     /*
    2423             :      * Easy if it's a fixed-width type
    2424             :      */
    2425     1079922 :     if (typlen > 0)
    2426      694470 :         return typlen;
    2427             : 
    2428             :     /*
    2429             :      * type_maximum_size knows the encoding of typmod for some datatypes;
    2430             :      * don't duplicate that knowledge here.
    2431             :      */
    2432      385452 :     maxwidth = type_maximum_size(typid, typmod);
    2433      385452 :     if (maxwidth > 0)
    2434             :     {
    2435             :         /*
    2436             :          * For BPCHAR, the max width is also the only width.  Otherwise we
    2437             :          * need to guess about the typical data width given the max. A sliding
    2438             :          * scale for percentage of max width seems reasonable.
    2439             :          */
    2440       18660 :         if (typid == BPCHAROID)
    2441       12046 :             return maxwidth;
    2442        6614 :         if (maxwidth <= 32)
    2443        3654 :             return maxwidth;    /* assume full width */
    2444        2960 :         if (maxwidth < 1000)
    2445        2872 :             return 32 + (maxwidth - 32) / 2;    /* assume 50% */
    2446             : 
    2447             :         /*
    2448             :          * Beyond 1000, assume we're looking at something like
    2449             :          * "varchar(10000)" where the limit isn't actually reached often, and
    2450             :          * use a fixed estimate.
    2451             :          */
    2452          88 :         return 32 + (1000 - 32) / 2;
    2453             :     }
    2454             : 
    2455             :     /*
    2456             :      * Oops, we have no idea ... wild guess time.
    2457             :      */
    2458      366792 :     return 32;
    2459             : }
    2460             : 
    2461             : /*
    2462             :  * get_typtype
    2463             :  *
    2464             :  *      Given the type OID, find if it is a basic type, a complex type, etc.
    2465             :  *      It returns the null char if the cache lookup fails...
    2466             :  */
    2467             : char
    2468     2627260 : get_typtype(Oid typid)
    2469             : {
    2470             :     HeapTuple   tp;
    2471             : 
    2472     2627260 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2473     2627260 :     if (HeapTupleIsValid(tp))
    2474             :     {
    2475     2627210 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2476             :         char        result;
    2477             : 
    2478     2627210 :         result = typtup->typtype;
    2479     2627210 :         ReleaseSysCache(tp);
    2480     2627210 :         return result;
    2481             :     }
    2482             :     else
    2483          50 :         return '\0';
    2484             : }
    2485             : 
    2486             : /*
    2487             :  * type_is_rowtype
    2488             :  *
    2489             :  *      Convenience function to determine whether a type OID represents
    2490             :  *      a "rowtype" type --- either RECORD or a named composite type
    2491             :  *      (including a domain over a named composite type).
    2492             :  */
    2493             : bool
    2494     1459388 : type_is_rowtype(Oid typid)
    2495             : {
    2496     1459388 :     if (typid == RECORDOID)
    2497       36376 :         return true;            /* easy case */
    2498     1423012 :     switch (get_typtype(typid))
    2499             :     {
    2500        2526 :         case TYPTYPE_COMPOSITE:
    2501        2526 :             return true;
    2502         210 :         case TYPTYPE_DOMAIN:
    2503         210 :             if (get_typtype(getBaseType(typid)) == TYPTYPE_COMPOSITE)
    2504          52 :                 return true;
    2505         158 :             break;
    2506     1420276 :         default:
    2507     1420276 :             break;
    2508             :     }
    2509     1420434 :     return false;
    2510             : }
    2511             : 
    2512             : /*
    2513             :  * type_is_enum
    2514             :  *    Returns true if the given type is an enum type.
    2515             :  */
    2516             : bool
    2517       44898 : type_is_enum(Oid typid)
    2518             : {
    2519       44898 :     return (get_typtype(typid) == TYPTYPE_ENUM);
    2520             : }
    2521             : 
    2522             : /*
    2523             :  * type_is_range
    2524             :  *    Returns true if the given type is a range type.
    2525             :  */
    2526             : bool
    2527       15004 : type_is_range(Oid typid)
    2528             : {
    2529       15004 :     return (get_typtype(typid) == TYPTYPE_RANGE);
    2530             : }
    2531             : 
    2532             : /*
    2533             :  * get_type_category_preferred
    2534             :  *
    2535             :  *      Given the type OID, fetch its category and preferred-type status.
    2536             :  *      Throws error on failure.
    2537             :  */
    2538             : void
    2539      299388 : get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
    2540             : {
    2541             :     HeapTuple   tp;
    2542             :     Form_pg_type typtup;
    2543             : 
    2544      299388 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2545      299388 :     if (!HeapTupleIsValid(tp))
    2546           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2547      299388 :     typtup = (Form_pg_type) GETSTRUCT(tp);
    2548      299388 :     *typcategory = typtup->typcategory;
    2549      299388 :     *typispreferred = typtup->typispreferred;
    2550      299388 :     ReleaseSysCache(tp);
    2551      299388 : }
    2552             : 
    2553             : /*
    2554             :  * get_typ_typrelid
    2555             :  *
    2556             :  *      Given the type OID, get the typrelid (InvalidOid if not a complex
    2557             :  *      type).
    2558             :  */
    2559             : Oid
    2560       22406 : get_typ_typrelid(Oid typid)
    2561             : {
    2562             :     HeapTuple   tp;
    2563             : 
    2564       22406 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2565       22406 :     if (HeapTupleIsValid(tp))
    2566             :     {
    2567       22406 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2568             :         Oid         result;
    2569             : 
    2570       22406 :         result = typtup->typrelid;
    2571       22406 :         ReleaseSysCache(tp);
    2572       22406 :         return result;
    2573             :     }
    2574             :     else
    2575           0 :         return InvalidOid;
    2576             : }
    2577             : 
    2578             : /*
    2579             :  * get_element_type
    2580             :  *
    2581             :  *      Given the type OID, get the typelem (InvalidOid if not an array type).
    2582             :  *
    2583             :  * NB: this only considers varlena arrays to be true arrays; InvalidOid is
    2584             :  * returned if the input is a fixed-length array type.
    2585             :  */
    2586             : Oid
    2587     1651574 : get_element_type(Oid typid)
    2588             : {
    2589             :     HeapTuple   tp;
    2590             : 
    2591     1651574 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2592     1651574 :     if (HeapTupleIsValid(tp))
    2593             :     {
    2594     1651550 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2595             :         Oid         result;
    2596             : 
    2597     1651550 :         if (typtup->typlen == -1)
    2598      530432 :             result = typtup->typelem;
    2599             :         else
    2600     1121118 :             result = InvalidOid;
    2601     1651550 :         ReleaseSysCache(tp);
    2602     1651550 :         return result;
    2603             :     }
    2604             :     else
    2605          24 :         return InvalidOid;
    2606             : }
    2607             : 
    2608             : /*
    2609             :  * get_array_type
    2610             :  *
    2611             :  *      Given the type OID, get the corresponding "true" array type.
    2612             :  *      Returns InvalidOid if no array type can be found.
    2613             :  */
    2614             : Oid
    2615      130658 : get_array_type(Oid typid)
    2616             : {
    2617             :     HeapTuple   tp;
    2618      130658 :     Oid         result = InvalidOid;
    2619             : 
    2620      130658 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2621      130658 :     if (HeapTupleIsValid(tp))
    2622             :     {
    2623      130658 :         result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
    2624      130658 :         ReleaseSysCache(tp);
    2625             :     }
    2626      130658 :     return result;
    2627             : }
    2628             : 
    2629             : /*
    2630             :  * get_promoted_array_type
    2631             :  *
    2632             :  *      The "promoted" type is what you'd get from an ARRAY(SELECT ...)
    2633             :  *      construct, that is, either the corresponding "true" array type
    2634             :  *      if the input is a scalar type that has such an array type,
    2635             :  *      or the same type if the input is already a "true" array type.
    2636             :  *      Returns InvalidOid if neither rule is satisfied.
    2637             :  */
    2638             : Oid
    2639       33338 : get_promoted_array_type(Oid typid)
    2640             : {
    2641       33338 :     Oid         array_type = get_array_type(typid);
    2642             : 
    2643       33338 :     if (OidIsValid(array_type))
    2644       33314 :         return array_type;
    2645          24 :     if (OidIsValid(get_element_type(typid)))
    2646          24 :         return typid;
    2647           0 :     return InvalidOid;
    2648             : }
    2649             : 
    2650             : /*
    2651             :  * get_base_element_type
    2652             :  *      Given the type OID, get the typelem, looking "through" any domain
    2653             :  *      to its underlying array type.
    2654             :  *
    2655             :  * This is equivalent to get_element_type(getBaseType(typid)), but avoids
    2656             :  * an extra cache lookup.  Note that it fails to provide any information
    2657             :  * about the typmod of the array.
    2658             :  */
    2659             : Oid
    2660      191960 : get_base_element_type(Oid typid)
    2661             : {
    2662             :     /*
    2663             :      * We loop to find the bottom base type in a stack of domains.
    2664             :      */
    2665             :     for (;;)
    2666          44 :     {
    2667             :         HeapTuple   tup;
    2668             :         Form_pg_type typTup;
    2669             : 
    2670      191960 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2671      191960 :         if (!HeapTupleIsValid(tup))
    2672         810 :             break;
    2673      191150 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2674      191150 :         if (typTup->typtype != TYPTYPE_DOMAIN)
    2675             :         {
    2676             :             /* Not a domain, so stop descending */
    2677             :             Oid         result;
    2678             : 
    2679             :             /* This test must match get_element_type */
    2680      191106 :             if (typTup->typlen == -1)
    2681      120494 :                 result = typTup->typelem;
    2682             :             else
    2683       70612 :                 result = InvalidOid;
    2684      191106 :             ReleaseSysCache(tup);
    2685      191106 :             return result;
    2686             :         }
    2687             : 
    2688          44 :         typid = typTup->typbasetype;
    2689          44 :         ReleaseSysCache(tup);
    2690             :     }
    2691             : 
    2692             :     /* Like get_element_type, silently return InvalidOid for bogus input */
    2693         810 :     return InvalidOid;
    2694             : }
    2695             : 
    2696             : /*
    2697             :  * getTypeInputInfo
    2698             :  *
    2699             :  *      Get info needed for converting values of a type to internal form
    2700             :  */
    2701             : void
    2702      111374 : getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
    2703             : {
    2704             :     HeapTuple   typeTuple;
    2705             :     Form_pg_type pt;
    2706             : 
    2707      111374 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2708      111374 :     if (!HeapTupleIsValid(typeTuple))
    2709           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2710      111374 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2711             : 
    2712      111374 :     if (!pt->typisdefined)
    2713           0 :         ereport(ERROR,
    2714             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2715             :                  errmsg("type %s is only a shell",
    2716             :                         format_type_be(type))));
    2717      111374 :     if (!OidIsValid(pt->typinput))
    2718           0 :         ereport(ERROR,
    2719             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2720             :                  errmsg("no input function available for type %s",
    2721             :                         format_type_be(type))));
    2722             : 
    2723      111374 :     *typInput = pt->typinput;
    2724      111374 :     *typIOParam = getTypeIOParam(typeTuple);
    2725             : 
    2726      111374 :     ReleaseSysCache(typeTuple);
    2727      111374 : }
    2728             : 
    2729             : /*
    2730             :  * getTypeOutputInfo
    2731             :  *
    2732             :  *      Get info needed for printing values of a type
    2733             :  */
    2734             : void
    2735     1053856 : getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
    2736             : {
    2737             :     HeapTuple   typeTuple;
    2738             :     Form_pg_type pt;
    2739             : 
    2740     1053856 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2741     1053856 :     if (!HeapTupleIsValid(typeTuple))
    2742           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2743     1053856 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2744             : 
    2745     1053856 :     if (!pt->typisdefined)
    2746           0 :         ereport(ERROR,
    2747             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2748             :                  errmsg("type %s is only a shell",
    2749             :                         format_type_be(type))));
    2750     1053856 :     if (!OidIsValid(pt->typoutput))
    2751           0 :         ereport(ERROR,
    2752             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2753             :                  errmsg("no output function available for type %s",
    2754             :                         format_type_be(type))));
    2755             : 
    2756     1053856 :     *typOutput = pt->typoutput;
    2757     1053856 :     *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
    2758             : 
    2759     1053856 :     ReleaseSysCache(typeTuple);
    2760     1053856 : }
    2761             : 
    2762             : /*
    2763             :  * getTypeBinaryInputInfo
    2764             :  *
    2765             :  *      Get info needed for binary input of values of a type
    2766             :  */
    2767             : void
    2768        3888 : getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
    2769             : {
    2770             :     HeapTuple   typeTuple;
    2771             :     Form_pg_type pt;
    2772             : 
    2773        3888 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2774        3888 :     if (!HeapTupleIsValid(typeTuple))
    2775           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2776        3888 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2777             : 
    2778        3888 :     if (!pt->typisdefined)
    2779           0 :         ereport(ERROR,
    2780             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2781             :                  errmsg("type %s is only a shell",
    2782             :                         format_type_be(type))));
    2783        3888 :     if (!OidIsValid(pt->typreceive))
    2784           0 :         ereport(ERROR,
    2785             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2786             :                  errmsg("no binary input function available for type %s",
    2787             :                         format_type_be(type))));
    2788             : 
    2789        3888 :     *typReceive = pt->typreceive;
    2790        3888 :     *typIOParam = getTypeIOParam(typeTuple);
    2791             : 
    2792        3888 :     ReleaseSysCache(typeTuple);
    2793        3888 : }
    2794             : 
    2795             : /*
    2796             :  * getTypeBinaryOutputInfo
    2797             :  *
    2798             :  *      Get info needed for binary output of values of a type
    2799             :  */
    2800             : void
    2801        1320 : getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
    2802             : {
    2803             :     HeapTuple   typeTuple;
    2804             :     Form_pg_type pt;
    2805             : 
    2806        1320 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2807        1320 :     if (!HeapTupleIsValid(typeTuple))
    2808           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2809        1320 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2810             : 
    2811        1320 :     if (!pt->typisdefined)
    2812           0 :         ereport(ERROR,
    2813             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2814             :                  errmsg("type %s is only a shell",
    2815             :                         format_type_be(type))));
    2816        1320 :     if (!OidIsValid(pt->typsend))
    2817           0 :         ereport(ERROR,
    2818             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2819             :                  errmsg("no binary output function available for type %s",
    2820             :                         format_type_be(type))));
    2821             : 
    2822        1320 :     *typSend = pt->typsend;
    2823        1320 :     *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
    2824             : 
    2825        1320 :     ReleaseSysCache(typeTuple);
    2826        1320 : }
    2827             : 
    2828             : /*
    2829             :  * get_typmodin
    2830             :  *
    2831             :  *      Given the type OID, return the type's typmodin procedure, if any.
    2832             :  */
    2833             : Oid
    2834           0 : get_typmodin(Oid typid)
    2835             : {
    2836             :     HeapTuple   tp;
    2837             : 
    2838           0 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2839           0 :     if (HeapTupleIsValid(tp))
    2840             :     {
    2841           0 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2842             :         Oid         result;
    2843             : 
    2844           0 :         result = typtup->typmodin;
    2845           0 :         ReleaseSysCache(tp);
    2846           0 :         return result;
    2847             :     }
    2848             :     else
    2849           0 :         return InvalidOid;
    2850             : }
    2851             : 
    2852             : #ifdef NOT_USED
    2853             : /*
    2854             :  * get_typmodout
    2855             :  *
    2856             :  *      Given the type OID, return the type's typmodout procedure, if any.
    2857             :  */
    2858             : Oid
    2859             : get_typmodout(Oid typid)
    2860             : {
    2861             :     HeapTuple   tp;
    2862             : 
    2863             :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2864             :     if (HeapTupleIsValid(tp))
    2865             :     {
    2866             :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2867             :         Oid         result;
    2868             : 
    2869             :         result = typtup->typmodout;
    2870             :         ReleaseSysCache(tp);
    2871             :         return result;
    2872             :     }
    2873             :     else
    2874             :         return InvalidOid;
    2875             : }
    2876             : #endif                          /* NOT_USED */
    2877             : 
    2878             : /*
    2879             :  * get_typcollation
    2880             :  *
    2881             :  *      Given the type OID, return the type's typcollation attribute.
    2882             :  */
    2883             : Oid
    2884     3723568 : get_typcollation(Oid typid)
    2885             : {
    2886             :     HeapTuple   tp;
    2887             : 
    2888     3723568 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2889     3723568 :     if (HeapTupleIsValid(tp))
    2890             :     {
    2891     3723556 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2892             :         Oid         result;
    2893             : 
    2894     3723556 :         result = typtup->typcollation;
    2895     3723556 :         ReleaseSysCache(tp);
    2896     3723556 :         return result;
    2897             :     }
    2898             :     else
    2899          12 :         return InvalidOid;
    2900             : }
    2901             : 
    2902             : 
    2903             : /*
    2904             :  * type_is_collatable
    2905             :  *
    2906             :  *      Return whether the type cares about collations
    2907             :  */
    2908             : bool
    2909     1021496 : type_is_collatable(Oid typid)
    2910             : {
    2911     1021496 :     return OidIsValid(get_typcollation(typid));
    2912             : }
    2913             : 
    2914             : 
    2915             : /*              ---------- STATISTICS CACHE ----------                   */
    2916             : 
    2917             : /*
    2918             :  * get_attavgwidth
    2919             :  *
    2920             :  *    Given the table and attribute number of a column, get the average
    2921             :  *    width of entries in the column.  Return zero if no data available.
    2922             :  *
    2923             :  * Currently this is only consulted for individual tables, not for inheritance
    2924             :  * trees, so we don't need an "inh" parameter.
    2925             :  *
    2926             :  * Calling a hook at this point looks somewhat strange, but is required
    2927             :  * because the optimizer calls this function without any other way for
    2928             :  * plug-ins to control the result.
    2929             :  */
    2930             : int32
    2931      999334 : get_attavgwidth(Oid relid, AttrNumber attnum)
    2932             : {
    2933             :     HeapTuple   tp;
    2934             :     int32       stawidth;
    2935             : 
    2936      999334 :     if (get_attavgwidth_hook)
    2937             :     {
    2938           0 :         stawidth = (*get_attavgwidth_hook) (relid, attnum);
    2939           0 :         if (stawidth > 0)
    2940           0 :             return stawidth;
    2941             :     }
    2942      999334 :     tp = SearchSysCache3(STATRELATTINH,
    2943             :                          ObjectIdGetDatum(relid),
    2944             :                          Int16GetDatum(attnum),
    2945             :                          BoolGetDatum(false));
    2946      999334 :     if (HeapTupleIsValid(tp))
    2947             :     {
    2948      576428 :         stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
    2949      576428 :         ReleaseSysCache(tp);
    2950      576428 :         if (stawidth > 0)
    2951      550362 :             return stawidth;
    2952             :     }
    2953      448972 :     return 0;
    2954             : }
    2955             : 
    2956             : /*
    2957             :  * get_attstatsslot
    2958             :  *
    2959             :  *      Extract the contents of a "slot" of a pg_statistic tuple.
    2960             :  *      Returns true if requested slot type was found, else false.
    2961             :  *
    2962             :  * Unlike other routines in this file, this takes a pointer to an
    2963             :  * already-looked-up tuple in the pg_statistic cache.  We do this since
    2964             :  * most callers will want to extract more than one value from the cache
    2965             :  * entry, and we don't want to repeat the cache lookup unnecessarily.
    2966             :  * Also, this API allows this routine to be used with statistics tuples
    2967             :  * that have been provided by a stats hook and didn't really come from
    2968             :  * pg_statistic.
    2969             :  *
    2970             :  * sslot: pointer to output area (typically, a local variable in the caller).
    2971             :  * statstuple: pg_statistic tuple to be examined.
    2972             :  * reqkind: STAKIND code for desired statistics slot kind.
    2973             :  * reqop: STAOP value wanted, or InvalidOid if don't care.
    2974             :  * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
    2975             :  *
    2976             :  * If a matching slot is found, true is returned, and *sslot is filled thus:
    2977             :  * staop: receives the actual STAOP value.
    2978             :  * stacoll: receives the actual STACOLL value.
    2979             :  * valuetype: receives actual datatype of the elements of stavalues.
    2980             :  * values: receives pointer to an array of the slot's stavalues.
    2981             :  * nvalues: receives number of stavalues.
    2982             :  * numbers: receives pointer to an array of the slot's stanumbers (as float4).
    2983             :  * nnumbers: receives number of stanumbers.
    2984             :  *
    2985             :  * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
    2986             :  * wasn't specified.  Likewise, numbers/nnumbers are NULL/0 if
    2987             :  * ATTSTATSSLOT_NUMBERS wasn't specified.
    2988             :  *
    2989             :  * If no matching slot is found, false is returned, and *sslot is zeroed.
    2990             :  *
    2991             :  * Note that the current API doesn't allow for searching for a slot with
    2992             :  * a particular collation.  If we ever actually support recording more than
    2993             :  * one collation, we'll have to extend the API, but for now simple is good.
    2994             :  *
    2995             :  * The data referred to by the fields of sslot is locally palloc'd and
    2996             :  * is independent of the original pg_statistic tuple.  When the caller
    2997             :  * is done with it, call free_attstatsslot to release the palloc'd data.
    2998             :  *
    2999             :  * If it's desirable to call free_attstatsslot when get_attstatsslot might
    3000             :  * not have been called, memset'ing sslot to zeroes will allow that.
    3001             :  */
    3002             : bool
    3003     1212988 : get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
    3004             :                  int reqkind, Oid reqop, int flags)
    3005             : {
    3006     1212988 :     Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
    3007             :     int         i;
    3008             :     Datum       val;
    3009             :     bool        isnull;
    3010             :     ArrayType  *statarray;
    3011             :     Oid         arrayelemtype;
    3012             :     int         narrayelem;
    3013             :     HeapTuple   typeTuple;
    3014             :     Form_pg_type typeForm;
    3015             : 
    3016             :     /* initialize *sslot properly */
    3017     1212988 :     memset(sslot, 0, sizeof(AttStatsSlot));
    3018             : 
    3019     3316450 :     for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
    3020             :     {
    3021     2992336 :         if ((&stats->stakind1)[i] == reqkind &&
    3022      367424 :             (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
    3023             :             break;
    3024             :     }
    3025     1212988 :     if (i >= STATISTIC_NUM_SLOTS)
    3026      324114 :         return false;           /* not there */
    3027             : 
    3028      888874 :     sslot->staop = (&stats->staop1)[i];
    3029      888874 :     sslot->stacoll = (&stats->stacoll1)[i];
    3030             : 
    3031             :     /*
    3032             :      * XXX Hopefully-temporary hack: if stacoll isn't set, inject the default
    3033             :      * collation.  This won't matter for non-collation-aware datatypes.  For
    3034             :      * those that are, this covers cases where stacoll has not been set.  In
    3035             :      * the short term we need this because some code paths involving type NAME
    3036             :      * do not pass any collation to prefix_selectivity and related functions.
    3037             :      * Even when that's been fixed, it's likely that some add-on typanalyze
    3038             :      * functions won't get the word right away about filling stacoll during
    3039             :      * ANALYZE, so we'll probably need this for awhile.
    3040             :      */
    3041      888874 :     if (sslot->stacoll == InvalidOid)
    3042      831362 :         sslot->stacoll = DEFAULT_COLLATION_OID;
    3043             : 
    3044      888874 :     if (flags & ATTSTATSSLOT_VALUES)
    3045             :     {
    3046      501572 :         val = SysCacheGetAttr(STATRELATTINH, statstuple,
    3047      501572 :                               Anum_pg_statistic_stavalues1 + i,
    3048             :                               &isnull);
    3049      501572 :         if (isnull)
    3050           0 :             elog(ERROR, "stavalues is null");
    3051             : 
    3052             :         /*
    3053             :          * Detoast the array if needed, and in any case make a copy that's
    3054             :          * under control of this AttStatsSlot.
    3055             :          */
    3056      501572 :         statarray = DatumGetArrayTypePCopy(val);
    3057             : 
    3058             :         /*
    3059             :          * Extract the actual array element type, and pass it back in case the
    3060             :          * caller needs it.
    3061             :          */
    3062      501572 :         sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
    3063             : 
    3064             :         /* Need info about element type */
    3065      501572 :         typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
    3066      501572 :         if (!HeapTupleIsValid(typeTuple))
    3067           0 :             elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
    3068      501572 :         typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
    3069             : 
    3070             :         /* Deconstruct array into Datum elements; NULLs not expected */
    3071     2006288 :         deconstruct_array(statarray,
    3072             :                           arrayelemtype,
    3073      501572 :                           typeForm->typlen,
    3074      501572 :                           typeForm->typbyval,
    3075      501572 :                           typeForm->typalign,
    3076             :                           &sslot->values, NULL, &sslot->nvalues);
    3077             : 
    3078             :         /*
    3079             :          * If the element type is pass-by-reference, we now have a bunch of
    3080             :          * Datums that are pointers into the statarray, so we need to keep
    3081             :          * that until free_attstatsslot.  Otherwise, all the useful info is in
    3082             :          * sslot->values[], so we can free the array object immediately.
    3083             :          */
    3084      501572 :         if (!typeForm->typbyval)
    3085       24888 :             sslot->values_arr = statarray;
    3086             :         else
    3087      476684 :             pfree(statarray);
    3088             : 
    3089      501572 :         ReleaseSysCache(typeTuple);
    3090             :     }
    3091             : 
    3092      888874 :     if (flags & ATTSTATSSLOT_NUMBERS)
    3093             :     {
    3094      638204 :         val = SysCacheGetAttr(STATRELATTINH, statstuple,
    3095      638204 :                               Anum_pg_statistic_stanumbers1 + i,
    3096             :                               &isnull);
    3097      638204 :         if (isnull)
    3098           0 :             elog(ERROR, "stanumbers is null");
    3099             : 
    3100             :         /*
    3101             :          * Detoast the array if needed, and in any case make a copy that's
    3102             :          * under control of this AttStatsSlot.
    3103             :          */
    3104      638204 :         statarray = DatumGetArrayTypePCopy(val);
    3105             : 
    3106             :         /*
    3107             :          * We expect the array to be a 1-D float4 array; verify that. We don't
    3108             :          * need to use deconstruct_array() since the array data is just going
    3109             :          * to look like a C array of float4 values.
    3110             :          */
    3111      638204 :         narrayelem = ARR_DIMS(statarray)[0];
    3112      638204 :         if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
    3113      638204 :             ARR_HASNULL(statarray) ||
    3114      638204 :             ARR_ELEMTYPE(statarray) != FLOAT4OID)
    3115           0 :             elog(ERROR, "stanumbers is not a 1-D float4 array");
    3116             : 
    3117             :         /* Give caller a pointer directly into the statarray */
    3118      638204 :         sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
    3119      638204 :         sslot->nnumbers = narrayelem;
    3120             : 
    3121             :         /* We'll free the statarray in free_attstatsslot */
    3122      638204 :         sslot->numbers_arr = statarray;
    3123             :     }
    3124             : 
    3125      888874 :     return true;
    3126             : }
    3127             : 
    3128             : /*
    3129             :  * free_attstatsslot
    3130             :  *      Free data allocated by get_attstatsslot
    3131             :  */
    3132             : void
    3133     1070604 : free_attstatsslot(AttStatsSlot *sslot)
    3134             : {
    3135             :     /* The values[] array was separately palloc'd by deconstruct_array */
    3136     1070604 :     if (sslot->values)
    3137      501572 :         pfree(sslot->values);
    3138             :     /* The numbers[] array points into numbers_arr, do not pfree it */
    3139             :     /* Free the detoasted array objects, if any */
    3140     1070604 :     if (sslot->values_arr)
    3141       24888 :         pfree(sslot->values_arr);
    3142     1070604 :     if (sslot->numbers_arr)
    3143      638204 :         pfree(sslot->numbers_arr);
    3144     1070604 : }
    3145             : 
    3146             : /*              ---------- PG_NAMESPACE CACHE ----------                 */
    3147             : 
    3148             : /*
    3149             :  * get_namespace_name
    3150             :  *      Returns the name of a given namespace
    3151             :  *
    3152             :  * Returns a palloc'd copy of the string, or NULL if no such namespace.
    3153             :  */
    3154             : char *
    3155      580100 : get_namespace_name(Oid nspid)
    3156             : {
    3157             :     HeapTuple   tp;
    3158             : 
    3159      580100 :     tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
    3160      580100 :     if (HeapTupleIsValid(tp))
    3161             :     {
    3162      580100 :         Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
    3163             :         char       *result;
    3164             : 
    3165      580100 :         result = pstrdup(NameStr(nsptup->nspname));
    3166      580100 :         ReleaseSysCache(tp);
    3167      580100 :         return result;
    3168             :     }
    3169             :     else
    3170           0 :         return NULL;
    3171             : }
    3172             : 
    3173             : /*
    3174             :  * get_namespace_name_or_temp
    3175             :  *      As above, but if it is this backend's temporary namespace, return
    3176             :  *      "pg_temp" instead.
    3177             :  */
    3178             : char *
    3179       10990 : get_namespace_name_or_temp(Oid nspid)
    3180             : {
    3181       10990 :     if (isTempNamespace(nspid))
    3182          24 :         return "pg_temp";
    3183             :     else
    3184       10966 :         return get_namespace_name(nspid);
    3185             : }
    3186             : 
    3187             : /*              ---------- PG_RANGE CACHE ----------                 */
    3188             : 
    3189             : /*
    3190             :  * get_range_subtype
    3191             :  *      Returns the subtype of a given range type
    3192             :  *
    3193             :  * Returns InvalidOid if the type is not a range type.
    3194             :  */
    3195             : Oid
    3196        6816 : get_range_subtype(Oid rangeOid)
    3197             : {
    3198             :     HeapTuple   tp;
    3199             : 
    3200        6816 :     tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
    3201        6816 :     if (HeapTupleIsValid(tp))
    3202             :     {
    3203        2210 :         Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
    3204             :         Oid         result;
    3205             : 
    3206        2210 :         result = rngtup->rngsubtype;
    3207        2210 :         ReleaseSysCache(tp);
    3208        2210 :         return result;
    3209             :     }
    3210             :     else
    3211        4606 :         return InvalidOid;
    3212             : }
    3213             : 
    3214             : /*
    3215             :  * get_range_collation
    3216             :  *      Returns the collation of a given range type
    3217             :  *
    3218             :  * Returns InvalidOid if the type is not a range type,
    3219             :  * or if its subtype is not collatable.
    3220             :  */
    3221             : Oid
    3222         110 : get_range_collation(Oid rangeOid)
    3223             : {
    3224             :     HeapTuple   tp;
    3225             : 
    3226         110 :     tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
    3227         110 :     if (HeapTupleIsValid(tp))
    3228             :     {
    3229         110 :         Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
    3230             :         Oid         result;
    3231             : 
    3232         110 :         result = rngtup->rngcollation;
    3233         110 :         ReleaseSysCache(tp);
    3234         110 :         return result;
    3235             :     }
    3236             :     else
    3237           0 :         return InvalidOid;
    3238             : }
    3239             : 
    3240             : /*              ---------- PG_INDEX CACHE ----------                 */
    3241             : 
    3242             : /*
    3243             :  * get_index_column_opclass
    3244             :  *
    3245             :  *      Given the index OID and column number,
    3246             :  *      return opclass of the index column
    3247             :  *          or InvalidOid if the index was not found
    3248             :  *              or column is non-key one.
    3249             :  */
    3250             : Oid
    3251          24 : get_index_column_opclass(Oid index_oid, int attno)
    3252             : {
    3253             :     HeapTuple   tuple;
    3254             :     Form_pg_index rd_index PG_USED_FOR_ASSERTS_ONLY;
    3255             :     Datum       datum;
    3256             :     bool        isnull;
    3257             :     oidvector  *indclass;
    3258             :     Oid         opclass;
    3259             : 
    3260             :     /* First we need to know the column's opclass. */
    3261             : 
    3262          24 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3263          24 :     if (!HeapTupleIsValid(tuple))
    3264           0 :         return InvalidOid;
    3265             : 
    3266          24 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3267             : 
    3268             :     /* caller is supposed to guarantee this */
    3269             :     Assert(attno > 0 && attno <= rd_index->indnatts);
    3270             : 
    3271             :     /* Non-key attributes don't have an opclass */
    3272          24 :     if (attno > rd_index->indnkeyatts)
    3273             :     {
    3274           0 :         ReleaseSysCache(tuple);
    3275           0 :         return InvalidOid;
    3276             :     }
    3277             : 
    3278          24 :     datum = SysCacheGetAttr(INDEXRELID, tuple,
    3279             :                             Anum_pg_index_indclass, &isnull);
    3280             :     Assert(!isnull);
    3281             : 
    3282          24 :     indclass = ((oidvector *) DatumGetPointer(datum));
    3283             : 
    3284             :     Assert(attno <= indclass->dim1);
    3285          24 :     opclass = indclass->values[attno - 1];
    3286             : 
    3287          24 :     ReleaseSysCache(tuple);
    3288             : 
    3289          24 :     return opclass;
    3290             : }
    3291             : 
    3292             : /*
    3293             :  * get_index_isreplident
    3294             :  *
    3295             :  *      Given the index OID, return pg_index.indisreplident.
    3296             :  */
    3297             : bool
    3298         252 : get_index_isreplident(Oid index_oid)
    3299             : {
    3300             :     HeapTuple   tuple;
    3301             :     Form_pg_index rd_index;
    3302             :     bool        result;
    3303             : 
    3304         252 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3305         252 :     if (!HeapTupleIsValid(tuple))
    3306           0 :         return false;
    3307             : 
    3308         252 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3309         252 :     result = rd_index->indisreplident;
    3310         252 :     ReleaseSysCache(tuple);
    3311             : 
    3312         252 :     return result;
    3313             : }
    3314             : 
    3315             : /*
    3316             :  * get_index_isvalid
    3317             :  *
    3318             :  *      Given the index OID, return pg_index.indisvalid.
    3319             :  */
    3320             : bool
    3321        4036 : get_index_isvalid(Oid index_oid)
    3322             : {
    3323             :     bool        isvalid;
    3324             :     HeapTuple   tuple;
    3325             :     Form_pg_index rd_index;
    3326             : 
    3327        4036 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3328        4036 :     if (!HeapTupleIsValid(tuple))
    3329           0 :         elog(ERROR, "cache lookup failed for index %u", index_oid);
    3330             : 
    3331        4036 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3332        4036 :     isvalid = rd_index->indisvalid;
    3333        4036 :     ReleaseSysCache(tuple);
    3334             : 
    3335        4036 :     return isvalid;
    3336             : }
    3337             : 
    3338             : /*
    3339             :  * get_index_isclustered
    3340             :  *
    3341             :  *      Given the index OID, return pg_index.indisclustered.
    3342             :  */
    3343             : bool
    3344         378 : get_index_isclustered(Oid index_oid)
    3345             : {
    3346             :     bool        isclustered;
    3347             :     HeapTuple   tuple;
    3348             :     Form_pg_index rd_index;
    3349             : 
    3350         378 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3351         378 :     if (!HeapTupleIsValid(tuple))
    3352           0 :         elog(ERROR, "cache lookup failed for index %u", index_oid);
    3353             : 
    3354         378 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3355         378 :     isclustered = rd_index->indisclustered;
    3356         378 :     ReleaseSysCache(tuple);
    3357             : 
    3358         378 :     return isclustered;
    3359             : }

Generated by: LCOV version 1.13