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

Generated by: LCOV version 1.14