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

Generated by: LCOV version 1.13