LCOV - code coverage report
Current view: top level - src/backend/utils/cache - lsyscache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 1003 1134 88.4 %
Date: 2023-05-31 00:12:04 Functions: 113 115 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      395124 : op_in_opfamily(Oid opno, Oid opfamily)
      66             : {
      67      395124 :     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      456326 : get_op_opfamily_strategy(Oid opno, Oid opfamily)
      83             : {
      84             :     HeapTuple   tp;
      85             :     Form_pg_amop amop_tup;
      86             :     int         result;
      87             : 
      88      456326 :     tp = SearchSysCache3(AMOPOPID,
      89             :                          ObjectIdGetDatum(opno),
      90             :                          CharGetDatum(AMOP_SEARCH),
      91             :                          ObjectIdGetDatum(opfamily));
      92      456326 :     if (!HeapTupleIsValid(tp))
      93           0 :         return 0;
      94      456326 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
      95      456326 :     result = amop_tup->amopstrategy;
      96      456326 :     ReleaseSysCache(tp);
      97      456326 :     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         462 : get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
     108             : {
     109             :     HeapTuple   tp;
     110             :     Form_pg_amop amop_tup;
     111             :     Oid         result;
     112             : 
     113         462 :     tp = SearchSysCache3(AMOPOPID,
     114             :                          ObjectIdGetDatum(opno),
     115             :                          CharGetDatum(AMOP_ORDER),
     116             :                          ObjectIdGetDatum(opfamily));
     117         462 :     if (!HeapTupleIsValid(tp))
     118           0 :         return InvalidOid;
     119         462 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
     120         462 :     result = amop_tup->amopsortfamily;
     121         462 :     ReleaseSysCache(tp);
     122         462 :     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      271786 : 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      271786 :     tp = SearchSysCache3(AMOPOPID,
     144             :                          ObjectIdGetDatum(opno),
     145             :                          CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
     146             :                          ObjectIdGetDatum(opfamily));
     147      271786 :     if (!HeapTupleIsValid(tp))
     148           0 :         elog(ERROR, "operator %u is not a member of opfamily %u",
     149             :              opno, opfamily);
     150      271786 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
     151      271786 :     *strategy = amop_tup->amopstrategy;
     152      271786 :     *lefttype = amop_tup->amoplefttype;
     153      271786 :     *righttype = amop_tup->amoprighttype;
     154      271786 :     ReleaseSysCache(tp);
     155      271786 : }
     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     2387908 : 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     2387908 :     tp = SearchSysCache4(AMOPSTRATEGY,
     173             :                          ObjectIdGetDatum(opfamily),
     174             :                          ObjectIdGetDatum(lefttype),
     175             :                          ObjectIdGetDatum(righttype),
     176             :                          Int16GetDatum(strategy));
     177     2387908 :     if (!HeapTupleIsValid(tp))
     178         366 :         return InvalidOid;
     179     2387542 :     amop_tup = (Form_pg_amop) GETSTRUCT(tp);
     180     2387542 :     result = amop_tup->amopopr;
     181     2387542 :     ReleaseSysCache(tp);
     182     2387542 :     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      517188 : get_ordering_op_properties(Oid opno,
     207             :                            Oid *opfamily, Oid *opcintype, int16 *strategy)
     208             : {
     209      517188 :     bool        result = false;
     210             :     CatCList   *catlist;
     211             :     int         i;
     212             : 
     213             :     /* ensure outputs are initialized on failure */
     214      517188 :     *opfamily = InvalidOid;
     215      517188 :     *opcintype = InvalidOid;
     216      517188 :     *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      517188 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     223             : 
     224      517188 :     for (i = 0; i < catlist->n_members; i++)
     225             :     {
     226      517188 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     227      517188 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     228             : 
     229             :         /* must be btree */
     230      517188 :         if (aform->amopmethod != BTREE_AM_OID)
     231           0 :             continue;
     232             : 
     233      517188 :         if (aform->amopstrategy == BTLessStrategyNumber ||
     234        7244 :             aform->amopstrategy == BTGreaterStrategyNumber)
     235             :         {
     236             :             /* Found it ... should have consistent input types */
     237      517188 :             if (aform->amoplefttype == aform->amoprighttype)
     238             :             {
     239             :                 /* Found a suitable opfamily, return info */
     240      517188 :                 *opfamily = aform->amopfamily;
     241      517188 :                 *opcintype = aform->amoplefttype;
     242      517188 :                 *strategy = aform->amopstrategy;
     243      517188 :                 result = true;
     244      517188 :                 break;
     245             :             }
     246             :         }
     247             :     }
     248             : 
     249      517188 :     ReleaseSysCacheList(catlist);
     250             : 
     251      517188 :     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        1256 : get_equality_op_for_ordering_op(Oid opno, bool *reverse)
     267             : {
     268        1256 :     Oid         result = InvalidOid;
     269             :     Oid         opfamily;
     270             :     Oid         opcintype;
     271             :     int16       strategy;
     272             : 
     273             :     /* Find the operator in pg_amop */
     274        1256 :     if (get_ordering_op_properties(opno,
     275             :                                    &opfamily, &opcintype, &strategy))
     276             :     {
     277             :         /* Found a suitable opfamily, get matching equality operator */
     278        1256 :         result = get_opfamily_member(opfamily,
     279             :                                      opcintype,
     280             :                                      opcintype,
     281             :                                      BTEqualStrategyNumber);
     282        1256 :         if (reverse)
     283         952 :             *reverse = (strategy == BTGreaterStrategyNumber);
     284             :     }
     285             : 
     286        1256 :     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     1521544 : get_mergejoin_opfamilies(Oid opno)
     366             : {
     367     1521544 :     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     1521544 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     376             : 
     377     9094528 :     for (i = 0; i < catlist->n_members; i++)
     378             :     {
     379     7572984 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     380     7572984 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     381             : 
     382             :         /* must be btree equality */
     383     7572984 :         if (aform->amopmethod == BTREE_AM_OID &&
     384     1555898 :             aform->amopstrategy == BTEqualStrategyNumber)
     385     1555898 :             result = lappend_oid(result, aform->amopfamily);
     386             :     }
     387             : 
     388     1521544 :     ReleaseSysCacheList(catlist);
     389             : 
     390     1521544 :     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        1520 : get_compatible_hash_operators(Oid opno,
     410             :                               Oid *lhs_opno, Oid *rhs_opno)
     411             : {
     412        1520 :     bool        result = false;
     413             :     CatCList   *catlist;
     414             :     int         i;
     415             : 
     416             :     /* Ensure output args are initialized on failure */
     417        1520 :     if (lhs_opno)
     418           0 :         *lhs_opno = InvalidOid;
     419        1520 :     if (rhs_opno)
     420        1520 :         *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        1520 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     428             : 
     429        3040 :     for (i = 0; i < catlist->n_members; i++)
     430             :     {
     431        3040 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     432        3040 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     433             : 
     434        3040 :         if (aform->amopmethod == HASH_AM_OID &&
     435        1520 :             aform->amopstrategy == HTEqualStrategyNumber)
     436             :         {
     437             :             /* No extra lookup needed if given operator is single-type */
     438        1520 :             if (aform->amoplefttype == aform->amoprighttype)
     439             :             {
     440        1472 :                 if (lhs_opno)
     441           0 :                     *lhs_opno = opno;
     442        1472 :                 if (rhs_opno)
     443        1472 :                     *rhs_opno = opno;
     444        1472 :                 result = true;
     445        1472 :                 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        1520 :     ReleaseSysCacheList(catlist);
     489             : 
     490        1520 :     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       52296 : get_op_hash_functions(Oid opno,
     510             :                       RegProcedure *lhs_procno, RegProcedure *rhs_procno)
     511             : {
     512       52296 :     bool        result = false;
     513             :     CatCList   *catlist;
     514             :     int         i;
     515             : 
     516             :     /* Ensure output args are initialized on failure */
     517       52296 :     if (lhs_procno)
     518       52296 :         *lhs_procno = InvalidOid;
     519       52296 :     if (rhs_procno)
     520       52296 :         *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       52296 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     528             : 
     529      104370 :     for (i = 0; i < catlist->n_members; i++)
     530             :     {
     531      103984 :         HeapTuple   tuple = &catlist->members[i]->tuple;
     532      103984 :         Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
     533             : 
     534      103984 :         if (aform->amopmethod == HASH_AM_OID &&
     535       51910 :             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       51910 :             if (lhs_procno)
     543             :             {
     544       51910 :                 *lhs_procno = get_opfamily_proc(aform->amopfamily,
     545             :                                                 aform->amoplefttype,
     546             :                                                 aform->amoplefttype,
     547             :                                                 HASHSTANDARD_PROC);
     548       51910 :                 if (!OidIsValid(*lhs_procno))
     549           0 :                     continue;
     550             :                 /* Matching LHS found, done if caller doesn't want RHS */
     551       51910 :                 if (!rhs_procno)
     552             :                 {
     553           0 :                     result = true;
     554           0 :                     break;
     555             :                 }
     556             :                 /* Only one lookup needed if given operator is single-type */
     557       51910 :                 if (aform->amoplefttype == aform->amoprighttype)
     558             :                 {
     559       51736 :                     *rhs_procno = *lhs_procno;
     560       51736 :                     result = true;
     561       51736 :                     break;
     562             :                 }
     563             :             }
     564         174 :             if (rhs_procno)
     565             :             {
     566         174 :                 *rhs_procno = get_opfamily_proc(aform->amopfamily,
     567             :                                                 aform->amoprighttype,
     568             :                                                 aform->amoprighttype,
     569             :                                                 HASHSTANDARD_PROC);
     570         174 :                 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         174 :                 result = true;
     579         174 :                 break;
     580             :             }
     581             :         }
     582             :     }
     583             : 
     584       52296 :     ReleaseSysCacheList(catlist);
     585             : 
     586       52296 :     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       11794 : get_op_btree_interpretation(Oid opno)
     601             : {
     602       11794 :     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       11794 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
     611             : 
     612       39254 :     for (i = 0; i < catlist->n_members; i++)
     613             :     {
     614       27460 :         HeapTuple   op_tuple = &catlist->members[i]->tuple;
     615       27460 :         Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
     616             :         StrategyNumber op_strategy;
     617             : 
     618             :         /* must be btree */
     619       27460 :         if (op_form->amopmethod != BTREE_AM_OID)
     620       20306 :             continue;
     621             : 
     622             :         /* Get the operator's btree strategy number */
     623        7154 :         op_strategy = (StrategyNumber) op_form->amopstrategy;
     624             :         Assert(op_strategy >= 1 && op_strategy <= 5);
     625             : 
     626             :         thisresult = (OpBtreeInterpretation *)
     627        7154 :             palloc(sizeof(OpBtreeInterpretation));
     628        7154 :         thisresult->opfamily_id = op_form->amopfamily;
     629        7154 :         thisresult->strategy = op_strategy;
     630        7154 :         thisresult->oplefttype = op_form->amoplefttype;
     631        7154 :         thisresult->oprighttype = op_form->amoprighttype;
     632        7154 :         result = lappend(result, thisresult);
     633             :     }
     634             : 
     635       11794 :     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       11794 :     if (result == NIL)
     642             :     {
     643        5402 :         Oid         op_negator = get_negator(opno);
     644             : 
     645        5402 :         if (OidIsValid(op_negator))
     646             :         {
     647        5378 :             catlist = SearchSysCacheList1(AMOPOPID,
     648             :                                           ObjectIdGetDatum(op_negator));
     649             : 
     650       25582 :             for (i = 0; i < catlist->n_members; i++)
     651             :             {
     652       20204 :                 HeapTuple   op_tuple = &catlist->members[i]->tuple;
     653       20204 :                 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
     654             :                 StrategyNumber op_strategy;
     655             : 
     656             :                 /* must be btree */
     657       20204 :                 if (op_form->amopmethod != BTREE_AM_OID)
     658       15206 :                     continue;
     659             : 
     660             :                 /* Get the operator's btree strategy number */
     661        4998 :                 op_strategy = (StrategyNumber) op_form->amopstrategy;
     662             :                 Assert(op_strategy >= 1 && op_strategy <= 5);
     663             : 
     664             :                 /* Only consider negators that are = */
     665        4998 :                 if (op_strategy != BTEqualStrategyNumber)
     666           0 :                     continue;
     667             : 
     668             :                 /* OK, report it with "strategy" ROWCOMPARE_NE */
     669             :                 thisresult = (OpBtreeInterpretation *)
     670        4998 :                     palloc(sizeof(OpBtreeInterpretation));
     671        4998 :                 thisresult->opfamily_id = op_form->amopfamily;
     672        4998 :                 thisresult->strategy = ROWCOMPARE_NE;
     673        4998 :                 thisresult->oplefttype = op_form->amoplefttype;
     674        4998 :                 thisresult->oprighttype = op_form->amoprighttype;
     675        4998 :                 result = lappend(result, thisresult);
     676             :             }
     677             : 
     678        5378 :             ReleaseSysCacheList(catlist);
     679             :         }
     680             :     }
     681             : 
     682       11794 :     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      162734 : 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      162734 :     if (opno1 == opno2)
     756       76782 :         return true;
     757             : 
     758             :     /*
     759             :      * We search through all the pg_amop entries for opno1.
     760             :      */
     761       85952 :     catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
     762             : 
     763       85952 :     result = false;
     764       86276 :     for (i = 0; i < catlist->n_members; i++)
     765             :     {
     766       86168 :         HeapTuple   op_tuple = &catlist->members[i]->tuple;
     767       86168 :         Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
     768             : 
     769       86168 :         if (op_form->amopmethod == BTREE_AM_OID)
     770             :         {
     771       85952 :             if (op_in_opfamily(opno2, op_form->amopfamily))
     772             :             {
     773       85844 :                 result = true;
     774       85844 :                 break;
     775             :             }
     776             :         }
     777             :     }
     778             : 
     779       85952 :     ReleaseSysCacheList(catlist);
     780             : 
     781       85952 :     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     1288472 : 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     1288472 :     tp = SearchSysCache4(AMPROCNUM,
     802             :                          ObjectIdGetDatum(opfamily),
     803             :                          ObjectIdGetDatum(lefttype),
     804             :                          ObjectIdGetDatum(righttype),
     805             :                          Int16GetDatum(procnum));
     806     1288472 :     if (!HeapTupleIsValid(tp))
     807       90896 :         return InvalidOid;
     808     1197576 :     amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
     809     1197576 :     result = amproc_tup->amproc;
     810     1197576 :     ReleaseSysCache(tp);
     811     1197576 :     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       53152 : get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
     827             : {
     828             :     HeapTuple   tp;
     829             : 
     830       53152 :     tp = SearchSysCache2(ATTNUM,
     831             :                          ObjectIdGetDatum(relid), Int16GetDatum(attnum));
     832       53152 :     if (HeapTupleIsValid(tp))
     833             :     {
     834       53128 :         Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     835             :         char       *result;
     836             : 
     837       53128 :         result = pstrdup(NameStr(att_tup->attname));
     838       53128 :         ReleaseSysCache(tp);
     839       53128 :         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       14684 : get_attnum(Oid relid, const char *attname)
     858             : {
     859             :     HeapTuple   tp;
     860             : 
     861       14684 :     tp = SearchSysCacheAttName(relid, attname);
     862       14684 :     if (HeapTupleIsValid(tp))
     863             :     {
     864       14620 :         Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     865             :         AttrNumber  result;
     866             : 
     867       14620 :         result = att_tup->attnum;
     868       14620 :         ReleaseSysCache(tp);
     869       14620 :         return result;
     870             :     }
     871             :     else
     872          64 :         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         650 : get_attstattarget(Oid relid, AttrNumber attnum)
     885             : {
     886             :     HeapTuple   tp;
     887             :     Form_pg_attribute att_tup;
     888             :     int         result;
     889             : 
     890         650 :     tp = SearchSysCache2(ATTNUM,
     891             :                          ObjectIdGetDatum(relid),
     892             :                          Int16GetDatum(attnum));
     893         650 :     if (!HeapTupleIsValid(tp))
     894           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     895             :              attnum, relid);
     896         650 :     att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     897         650 :     result = att_tup->attstattarget;
     898         650 :     ReleaseSysCache(tp);
     899         650 :     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         930 : get_attgenerated(Oid relid, AttrNumber attnum)
     915             : {
     916             :     HeapTuple   tp;
     917             :     Form_pg_attribute att_tup;
     918             :     char        result;
     919             : 
     920         930 :     tp = SearchSysCache2(ATTNUM,
     921             :                          ObjectIdGetDatum(relid),
     922             :                          Int16GetDatum(attnum));
     923         930 :     if (!HeapTupleIsValid(tp))
     924           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     925             :              attnum, relid);
     926         930 :     att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     927         930 :     result = att_tup->attgenerated;
     928         930 :     ReleaseSysCache(tp);
     929         930 :     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        1862 : get_atttype(Oid relid, AttrNumber attnum)
     940             : {
     941             :     HeapTuple   tp;
     942             : 
     943        1862 :     tp = SearchSysCache2(ATTNUM,
     944             :                          ObjectIdGetDatum(relid),
     945             :                          Int16GetDatum(attnum));
     946        1862 :     if (HeapTupleIsValid(tp))
     947             :     {
     948        1862 :         Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     949             :         Oid         result;
     950             : 
     951        1862 :         result = att_tup->atttypid;
     952        1862 :         ReleaseSysCache(tp);
     953        1862 :         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       11190 : 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       11190 :     tp = SearchSysCache2(ATTNUM,
     976             :                          ObjectIdGetDatum(relid),
     977             :                          Int16GetDatum(attnum));
     978       11190 :     if (!HeapTupleIsValid(tp))
     979           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
     980             :              attnum, relid);
     981       11190 :     att_tup = (Form_pg_attribute) GETSTRUCT(tp);
     982             : 
     983       11190 :     *typid = att_tup->atttypid;
     984       11190 :     *typmod = att_tup->atttypmod;
     985       11190 :     *collid = att_tup->attcollation;
     986       11190 :     ReleaseSysCache(tp);
     987       11190 : }
     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      915382 : get_attoptions(Oid relid, int16 attnum)
     997             : {
     998             :     HeapTuple   tuple;
     999             :     Datum       attopts;
    1000             :     Datum       result;
    1001             :     bool        isnull;
    1002             : 
    1003      915382 :     tuple = SearchSysCache2(ATTNUM,
    1004             :                             ObjectIdGetDatum(relid),
    1005             :                             Int16GetDatum(attnum));
    1006             : 
    1007      915382 :     if (!HeapTupleIsValid(tuple))
    1008           0 :         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    1009             :              attnum, relid);
    1010             : 
    1011      915382 :     attopts = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
    1012             :                               &isnull);
    1013             : 
    1014      915382 :     if (isnull)
    1015      914994 :         result = (Datum) 0;
    1016             :     else
    1017         388 :         result = datumCopy(attopts, false, -1); /* text[] */
    1018             : 
    1019      915382 :     ReleaseSysCache(tuple);
    1020             : 
    1021      915382 :     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          70 : get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
    1034             : {
    1035             :     Oid         oid;
    1036             : 
    1037          70 :     oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
    1038             :                           ObjectIdGetDatum(sourcetypeid),
    1039             :                           ObjectIdGetDatum(targettypeid));
    1040          70 :     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          64 :     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         254 : get_collation_name(Oid colloid)
    1062             : {
    1063             :     HeapTuple   tp;
    1064             : 
    1065         254 :     tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
    1066         254 :     if (HeapTupleIsValid(tp))
    1067             :     {
    1068         254 :         Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
    1069             :         char       *result;
    1070             : 
    1071         254 :         result = pstrdup(NameStr(colltup->collname));
    1072         254 :         ReleaseSysCache(tp);
    1073         254 :         return result;
    1074             :     }
    1075             :     else
    1076           0 :         return NULL;
    1077             : }
    1078             : 
    1079             : bool
    1080        6908 : get_collation_isdeterministic(Oid colloid)
    1081             : {
    1082             :     HeapTuple   tp;
    1083             :     Form_pg_collation colltup;
    1084             :     bool        result;
    1085             : 
    1086        6908 :     tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
    1087        6908 :     if (!HeapTupleIsValid(tp))
    1088           0 :         elog(ERROR, "cache lookup failed for collation %u", colloid);
    1089        6908 :     colltup = (Form_pg_collation) GETSTRUCT(tp);
    1090        6908 :     result = colltup->collisdeterministic;
    1091        6908 :     ReleaseSysCache(tp);
    1092        6908 :     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         640 : get_constraint_name(Oid conoid)
    1108             : {
    1109             :     HeapTuple   tp;
    1110             : 
    1111         640 :     tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
    1112         640 :     if (HeapTupleIsValid(tp))
    1113             :     {
    1114         640 :         Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
    1115             :         char       *result;
    1116             : 
    1117         640 :         result = pstrdup(NameStr(contup->conname));
    1118         640 :         ReleaseSysCache(tp);
    1119         640 :         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         602 : get_constraint_index(Oid conoid)
    1140             : {
    1141             :     HeapTuple   tp;
    1142             : 
    1143         602 :     tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
    1144         602 :     if (HeapTupleIsValid(tp))
    1145             :     {
    1146         602 :         Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
    1147             :         Oid         result;
    1148             : 
    1149         602 :         if (contup->contype == CONSTRAINT_UNIQUE ||
    1150         440 :             contup->contype == CONSTRAINT_PRIMARY ||
    1151         218 :             contup->contype == CONSTRAINT_EXCLUSION)
    1152         456 :             result = contup->conindid;
    1153             :         else
    1154         146 :             result = InvalidOid;
    1155         602 :         ReleaseSysCache(tp);
    1156         602 :         return result;
    1157             :     }
    1158             :     else
    1159           0 :         return InvalidOid;
    1160             : }
    1161             : 
    1162             : /*              ---------- LANGUAGE CACHE ----------                     */
    1163             : 
    1164             : char *
    1165         252 : get_language_name(Oid langoid, bool missing_ok)
    1166             : {
    1167             :     HeapTuple   tp;
    1168             : 
    1169         252 :     tp = SearchSysCache1(LANGOID, ObjectIdGetDatum(langoid));
    1170         252 :     if (HeapTupleIsValid(tp))
    1171             :     {
    1172         246 :         Form_pg_language lantup = (Form_pg_language) GETSTRUCT(tp);
    1173             :         char       *result;
    1174             : 
    1175         246 :         result = pstrdup(NameStr(lantup->lanname));
    1176         246 :         ReleaseSysCache(tp);
    1177         246 :         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      205264 : get_opclass_family(Oid opclass)
    1195             : {
    1196             :     HeapTuple   tp;
    1197             :     Form_pg_opclass cla_tup;
    1198             :     Oid         result;
    1199             : 
    1200      205264 :     tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    1201      205264 :     if (!HeapTupleIsValid(tp))
    1202           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
    1203      205264 :     cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
    1204             : 
    1205      205264 :     result = cla_tup->opcfamily;
    1206      205264 :     ReleaseSysCache(tp);
    1207      205264 :     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      206492 : get_opclass_input_type(Oid opclass)
    1217             : {
    1218             :     HeapTuple   tp;
    1219             :     Form_pg_opclass cla_tup;
    1220             :     Oid         result;
    1221             : 
    1222      206492 :     tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    1223      206492 :     if (!HeapTupleIsValid(tp))
    1224           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
    1225      206492 :     cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
    1226             : 
    1227      206492 :     result = cla_tup->opcintype;
    1228      206492 :     ReleaseSysCache(tp);
    1229      206492 :     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        1004 : get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
    1240             : {
    1241             :     HeapTuple   tp;
    1242             :     Form_pg_opclass cla_tup;
    1243             : 
    1244        1004 :     tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    1245        1004 :     if (!HeapTupleIsValid(tp))
    1246           0 :         return false;
    1247             : 
    1248        1004 :     cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
    1249             : 
    1250        1004 :     *opfamily = cla_tup->opcfamily;
    1251        1004 :     *opcintype = cla_tup->opcintype;
    1252             : 
    1253        1004 :     ReleaseSysCache(tp);
    1254             : 
    1255        1004 :     return true;
    1256             : }
    1257             : 
    1258             : /*              ---------- OPERATOR CACHE ----------                     */
    1259             : 
    1260             : /*
    1261             :  * get_opcode
    1262             :  *
    1263             :  *      Returns the regproc id of the routine used to implement an
    1264             :  *      operator given the operator oid.
    1265             :  */
    1266             : RegProcedure
    1267     1427606 : get_opcode(Oid opno)
    1268             : {
    1269             :     HeapTuple   tp;
    1270             : 
    1271     1427606 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1272     1427606 :     if (HeapTupleIsValid(tp))
    1273             :     {
    1274     1427606 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1275             :         RegProcedure result;
    1276             : 
    1277     1427606 :         result = optup->oprcode;
    1278     1427606 :         ReleaseSysCache(tp);
    1279     1427606 :         return result;
    1280             :     }
    1281             :     else
    1282           0 :         return (RegProcedure) InvalidOid;
    1283             : }
    1284             : 
    1285             : /*
    1286             :  * get_opname
    1287             :  *    returns the name of the operator with the given opno
    1288             :  *
    1289             :  * Note: returns a palloc'd copy of the string, or NULL if no such operator.
    1290             :  */
    1291             : char *
    1292          28 : get_opname(Oid opno)
    1293             : {
    1294             :     HeapTuple   tp;
    1295             : 
    1296          28 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1297          28 :     if (HeapTupleIsValid(tp))
    1298             :     {
    1299          28 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1300             :         char       *result;
    1301             : 
    1302          28 :         result = pstrdup(NameStr(optup->oprname));
    1303          28 :         ReleaseSysCache(tp);
    1304          28 :         return result;
    1305             :     }
    1306             :     else
    1307           0 :         return NULL;
    1308             : }
    1309             : 
    1310             : /*
    1311             :  * get_op_rettype
    1312             :  *      Given operator oid, return the operator's result type.
    1313             :  */
    1314             : Oid
    1315          92 : get_op_rettype(Oid opno)
    1316             : {
    1317             :     HeapTuple   tp;
    1318             : 
    1319          92 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1320          92 :     if (HeapTupleIsValid(tp))
    1321             :     {
    1322          92 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1323             :         Oid         result;
    1324             : 
    1325          92 :         result = optup->oprresult;
    1326          92 :         ReleaseSysCache(tp);
    1327          92 :         return result;
    1328             :     }
    1329             :     else
    1330           0 :         return InvalidOid;
    1331             : }
    1332             : 
    1333             : /*
    1334             :  * op_input_types
    1335             :  *
    1336             :  *      Returns the left and right input datatypes for an operator
    1337             :  *      (InvalidOid if not relevant).
    1338             :  */
    1339             : void
    1340      298396 : op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
    1341             : {
    1342             :     HeapTuple   tp;
    1343             :     Form_pg_operator optup;
    1344             : 
    1345      298396 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1346      298396 :     if (!HeapTupleIsValid(tp))  /* shouldn't happen */
    1347           0 :         elog(ERROR, "cache lookup failed for operator %u", opno);
    1348      298396 :     optup = (Form_pg_operator) GETSTRUCT(tp);
    1349      298396 :     *lefttype = optup->oprleft;
    1350      298396 :     *righttype = optup->oprright;
    1351      298396 :     ReleaseSysCache(tp);
    1352      298396 : }
    1353             : 
    1354             : /*
    1355             :  * op_mergejoinable
    1356             :  *
    1357             :  * Returns true if the operator is potentially mergejoinable.  (The planner
    1358             :  * will fail to find any mergejoin plans unless there are suitable btree
    1359             :  * opfamily entries for this operator and associated sortops.  The pg_operator
    1360             :  * flag is just a hint to tell the planner whether to bother looking.)
    1361             :  *
    1362             :  * In some cases (currently only array_eq and record_eq), mergejoinability
    1363             :  * depends on the specific input data type the operator is invoked for, so
    1364             :  * that must be passed as well. We currently assume that only one input's type
    1365             :  * is needed to check this --- by convention, pass the left input's data type.
    1366             :  */
    1367             : bool
    1368      389030 : op_mergejoinable(Oid opno, Oid inputtype)
    1369             : {
    1370      389030 :     bool        result = false;
    1371             :     HeapTuple   tp;
    1372             :     TypeCacheEntry *typentry;
    1373             : 
    1374             :     /*
    1375             :      * For array_eq or record_eq, we can sort if the element or field types
    1376             :      * are all sortable.  We could implement all the checks for that here, but
    1377             :      * the typcache already does that and caches the results too, so let's
    1378             :      * rely on the typcache.
    1379             :      */
    1380      389030 :     if (opno == ARRAY_EQ_OP)
    1381             :     {
    1382         146 :         typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
    1383         146 :         if (typentry->cmp_proc == F_BTARRAYCMP)
    1384         146 :             result = true;
    1385             :     }
    1386      388884 :     else if (opno == RECORD_EQ_OP)
    1387             :     {
    1388          64 :         typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
    1389          64 :         if (typentry->cmp_proc == F_BTRECORDCMP)
    1390          64 :             result = true;
    1391             :     }
    1392             :     else
    1393             :     {
    1394             :         /* For all other operators, rely on pg_operator.oprcanmerge */
    1395      388820 :         tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1396      388820 :         if (HeapTupleIsValid(tp))
    1397             :         {
    1398      388820 :             Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1399             : 
    1400      388820 :             result = optup->oprcanmerge;
    1401      388820 :             ReleaseSysCache(tp);
    1402             :         }
    1403             :     }
    1404      389030 :     return result;
    1405             : }
    1406             : 
    1407             : /*
    1408             :  * op_hashjoinable
    1409             :  *
    1410             :  * Returns true if the operator is hashjoinable.  (There must be a suitable
    1411             :  * hash opfamily entry for this operator if it is so marked.)
    1412             :  *
    1413             :  * In some cases (currently only array_eq), hashjoinability depends on the
    1414             :  * specific input data type the operator is invoked for, so that must be
    1415             :  * passed as well.  We currently assume that only one input's type is needed
    1416             :  * to check this --- by convention, pass the left input's data type.
    1417             :  */
    1418             : bool
    1419      279846 : op_hashjoinable(Oid opno, Oid inputtype)
    1420             : {
    1421      279846 :     bool        result = false;
    1422             :     HeapTuple   tp;
    1423             :     TypeCacheEntry *typentry;
    1424             : 
    1425             :     /* As in op_mergejoinable, let the typcache handle the hard cases */
    1426      279846 :     if (opno == ARRAY_EQ_OP)
    1427             :     {
    1428           0 :         typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
    1429           0 :         if (typentry->hash_proc == F_HASH_ARRAY)
    1430           0 :             result = true;
    1431             :     }
    1432      279846 :     else if (opno == RECORD_EQ_OP)
    1433             :     {
    1434          66 :         typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
    1435          66 :         if (typentry->hash_proc == F_HASH_RECORD)
    1436          54 :             result = true;
    1437             :     }
    1438             :     else
    1439             :     {
    1440             :         /* For all other operators, rely on pg_operator.oprcanhash */
    1441      279780 :         tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1442      279780 :         if (HeapTupleIsValid(tp))
    1443             :         {
    1444      279780 :             Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1445             : 
    1446      279780 :             result = optup->oprcanhash;
    1447      279780 :             ReleaseSysCache(tp);
    1448             :         }
    1449             :     }
    1450      279846 :     return result;
    1451             : }
    1452             : 
    1453             : /*
    1454             :  * op_strict
    1455             :  *
    1456             :  * Get the proisstrict flag for the operator's underlying function.
    1457             :  */
    1458             : bool
    1459       45158 : op_strict(Oid opno)
    1460             : {
    1461       45158 :     RegProcedure funcid = get_opcode(opno);
    1462             : 
    1463       45158 :     if (funcid == (RegProcedure) InvalidOid)
    1464           0 :         elog(ERROR, "operator %u does not exist", opno);
    1465             : 
    1466       45158 :     return func_strict((Oid) funcid);
    1467             : }
    1468             : 
    1469             : /*
    1470             :  * op_volatile
    1471             :  *
    1472             :  * Get the provolatile flag for the operator's underlying function.
    1473             :  */
    1474             : char
    1475       19412 : op_volatile(Oid opno)
    1476             : {
    1477       19412 :     RegProcedure funcid = get_opcode(opno);
    1478             : 
    1479       19412 :     if (funcid == (RegProcedure) InvalidOid)
    1480           0 :         elog(ERROR, "operator %u does not exist", opno);
    1481             : 
    1482       19412 :     return func_volatile((Oid) funcid);
    1483             : }
    1484             : 
    1485             : /*
    1486             :  * get_commutator
    1487             :  *
    1488             :  *      Returns the corresponding commutator of an operator.
    1489             :  */
    1490             : Oid
    1491       68380 : get_commutator(Oid opno)
    1492             : {
    1493             :     HeapTuple   tp;
    1494             : 
    1495       68380 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1496       68380 :     if (HeapTupleIsValid(tp))
    1497             :     {
    1498       68380 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1499             :         Oid         result;
    1500             : 
    1501       68380 :         result = optup->oprcom;
    1502       68380 :         ReleaseSysCache(tp);
    1503       68380 :         return result;
    1504             :     }
    1505             :     else
    1506           0 :         return InvalidOid;
    1507             : }
    1508             : 
    1509             : /*
    1510             :  * get_negator
    1511             :  *
    1512             :  *      Returns the corresponding negator of an operator.
    1513             :  */
    1514             : Oid
    1515       55396 : get_negator(Oid opno)
    1516             : {
    1517             :     HeapTuple   tp;
    1518             : 
    1519       55396 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1520       55396 :     if (HeapTupleIsValid(tp))
    1521             :     {
    1522       55396 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1523             :         Oid         result;
    1524             : 
    1525       55396 :         result = optup->oprnegate;
    1526       55396 :         ReleaseSysCache(tp);
    1527       55396 :         return result;
    1528             :     }
    1529             :     else
    1530           0 :         return InvalidOid;
    1531             : }
    1532             : 
    1533             : /*
    1534             :  * get_oprrest
    1535             :  *
    1536             :  *      Returns procedure id for computing selectivity of an operator.
    1537             :  */
    1538             : RegProcedure
    1539      784838 : get_oprrest(Oid opno)
    1540             : {
    1541             :     HeapTuple   tp;
    1542             : 
    1543      784838 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1544      784838 :     if (HeapTupleIsValid(tp))
    1545             :     {
    1546      784838 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1547             :         RegProcedure result;
    1548             : 
    1549      784838 :         result = optup->oprrest;
    1550      784838 :         ReleaseSysCache(tp);
    1551      784838 :         return result;
    1552             :     }
    1553             :     else
    1554           0 :         return (RegProcedure) InvalidOid;
    1555             : }
    1556             : 
    1557             : /*
    1558             :  * get_oprjoin
    1559             :  *
    1560             :  *      Returns procedure id for computing selectivity of a join.
    1561             :  */
    1562             : RegProcedure
    1563      162170 : get_oprjoin(Oid opno)
    1564             : {
    1565             :     HeapTuple   tp;
    1566             : 
    1567      162170 :     tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
    1568      162170 :     if (HeapTupleIsValid(tp))
    1569             :     {
    1570      162170 :         Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
    1571             :         RegProcedure result;
    1572             : 
    1573      162170 :         result = optup->oprjoin;
    1574      162170 :         ReleaseSysCache(tp);
    1575      162170 :         return result;
    1576             :     }
    1577             :     else
    1578           0 :         return (RegProcedure) InvalidOid;
    1579             : }
    1580             : 
    1581             : /*              ---------- FUNCTION CACHE ----------                     */
    1582             : 
    1583             : /*
    1584             :  * get_func_name
    1585             :  *    returns the name of the function with the given funcid
    1586             :  *
    1587             :  * Note: returns a palloc'd copy of the string, or NULL if no such function.
    1588             :  */
    1589             : char *
    1590         538 : get_func_name(Oid funcid)
    1591             : {
    1592             :     HeapTuple   tp;
    1593             : 
    1594         538 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1595         538 :     if (HeapTupleIsValid(tp))
    1596             :     {
    1597         538 :         Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
    1598             :         char       *result;
    1599             : 
    1600         538 :         result = pstrdup(NameStr(functup->proname));
    1601         538 :         ReleaseSysCache(tp);
    1602         538 :         return result;
    1603             :     }
    1604             :     else
    1605           0 :         return NULL;
    1606             : }
    1607             : 
    1608             : /*
    1609             :  * get_func_namespace
    1610             :  *
    1611             :  *      Returns the pg_namespace OID associated with a given function.
    1612             :  */
    1613             : Oid
    1614         132 : get_func_namespace(Oid funcid)
    1615             : {
    1616             :     HeapTuple   tp;
    1617             : 
    1618         132 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1619         132 :     if (HeapTupleIsValid(tp))
    1620             :     {
    1621         132 :         Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
    1622             :         Oid         result;
    1623             : 
    1624         132 :         result = functup->pronamespace;
    1625         132 :         ReleaseSysCache(tp);
    1626         132 :         return result;
    1627             :     }
    1628             :     else
    1629           0 :         return InvalidOid;
    1630             : }
    1631             : 
    1632             : /*
    1633             :  * get_func_rettype
    1634             :  *      Given procedure id, return the function's result type.
    1635             :  */
    1636             : Oid
    1637       22688 : get_func_rettype(Oid funcid)
    1638             : {
    1639             :     HeapTuple   tp;
    1640             :     Oid         result;
    1641             : 
    1642       22688 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1643       22688 :     if (!HeapTupleIsValid(tp))
    1644           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1645             : 
    1646       22688 :     result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
    1647       22688 :     ReleaseSysCache(tp);
    1648       22688 :     return result;
    1649             : }
    1650             : 
    1651             : /*
    1652             :  * get_func_nargs
    1653             :  *      Given procedure id, return the number of arguments.
    1654             :  */
    1655             : int
    1656           0 : get_func_nargs(Oid funcid)
    1657             : {
    1658             :     HeapTuple   tp;
    1659             :     int         result;
    1660             : 
    1661           0 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1662           0 :     if (!HeapTupleIsValid(tp))
    1663           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1664             : 
    1665           0 :     result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
    1666           0 :     ReleaseSysCache(tp);
    1667           0 :     return result;
    1668             : }
    1669             : 
    1670             : /*
    1671             :  * get_func_signature
    1672             :  *      Given procedure id, return the function's argument and result types.
    1673             :  *      (The return value is the result type.)
    1674             :  *
    1675             :  * The arguments are returned as a palloc'd array.
    1676             :  */
    1677             : Oid
    1678        1010 : get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
    1679             : {
    1680             :     HeapTuple   tp;
    1681             :     Form_pg_proc procstruct;
    1682             :     Oid         result;
    1683             : 
    1684        1010 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1685        1010 :     if (!HeapTupleIsValid(tp))
    1686           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1687             : 
    1688        1010 :     procstruct = (Form_pg_proc) GETSTRUCT(tp);
    1689             : 
    1690        1010 :     result = procstruct->prorettype;
    1691        1010 :     *nargs = (int) procstruct->pronargs;
    1692             :     Assert(*nargs == procstruct->proargtypes.dim1);
    1693        1010 :     *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
    1694        1010 :     memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
    1695             : 
    1696        1010 :     ReleaseSysCache(tp);
    1697        1010 :     return result;
    1698             : }
    1699             : 
    1700             : /*
    1701             :  * get_func_variadictype
    1702             :  *      Given procedure id, return the function's provariadic field.
    1703             :  */
    1704             : Oid
    1705         276 : get_func_variadictype(Oid funcid)
    1706             : {
    1707             :     HeapTuple   tp;
    1708             :     Oid         result;
    1709             : 
    1710         276 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1711         276 :     if (!HeapTupleIsValid(tp))
    1712           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1713             : 
    1714         276 :     result = ((Form_pg_proc) GETSTRUCT(tp))->provariadic;
    1715         276 :     ReleaseSysCache(tp);
    1716         276 :     return result;
    1717             : }
    1718             : 
    1719             : /*
    1720             :  * get_func_retset
    1721             :  *      Given procedure id, return the function's proretset flag.
    1722             :  */
    1723             : bool
    1724      956402 : get_func_retset(Oid funcid)
    1725             : {
    1726             :     HeapTuple   tp;
    1727             :     bool        result;
    1728             : 
    1729      956402 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1730      956402 :     if (!HeapTupleIsValid(tp))
    1731           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1732             : 
    1733      956402 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
    1734      956402 :     ReleaseSysCache(tp);
    1735      956402 :     return result;
    1736             : }
    1737             : 
    1738             : /*
    1739             :  * func_strict
    1740             :  *      Given procedure id, return the function's proisstrict flag.
    1741             :  */
    1742             : bool
    1743      197844 : func_strict(Oid funcid)
    1744             : {
    1745             :     HeapTuple   tp;
    1746             :     bool        result;
    1747             : 
    1748      197844 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1749      197844 :     if (!HeapTupleIsValid(tp))
    1750           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1751             : 
    1752      197844 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
    1753      197844 :     ReleaseSysCache(tp);
    1754      197844 :     return result;
    1755             : }
    1756             : 
    1757             : /*
    1758             :  * func_volatile
    1759             :  *      Given procedure id, return the function's provolatile flag.
    1760             :  */
    1761             : char
    1762      707194 : func_volatile(Oid funcid)
    1763             : {
    1764             :     HeapTuple   tp;
    1765             :     char        result;
    1766             : 
    1767      707194 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1768      707194 :     if (!HeapTupleIsValid(tp))
    1769           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1770             : 
    1771      707194 :     result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
    1772      707194 :     ReleaseSysCache(tp);
    1773      707194 :     return result;
    1774             : }
    1775             : 
    1776             : /*
    1777             :  * func_parallel
    1778             :  *      Given procedure id, return the function's proparallel flag.
    1779             :  */
    1780             : char
    1781     1020682 : func_parallel(Oid funcid)
    1782             : {
    1783             :     HeapTuple   tp;
    1784             :     char        result;
    1785             : 
    1786     1020682 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1787     1020682 :     if (!HeapTupleIsValid(tp))
    1788           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1789             : 
    1790     1020682 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proparallel;
    1791     1020682 :     ReleaseSysCache(tp);
    1792     1020682 :     return result;
    1793             : }
    1794             : 
    1795             : /*
    1796             :  * get_func_prokind
    1797             :  *     Given procedure id, return the routine kind.
    1798             :  */
    1799             : char
    1800       76070 : get_func_prokind(Oid funcid)
    1801             : {
    1802             :     HeapTuple   tp;
    1803             :     char        result;
    1804             : 
    1805       76070 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1806       76070 :     if (!HeapTupleIsValid(tp))
    1807           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1808             : 
    1809       76070 :     result = ((Form_pg_proc) GETSTRUCT(tp))->prokind;
    1810       76070 :     ReleaseSysCache(tp);
    1811       76070 :     return result;
    1812             : }
    1813             : 
    1814             : /*
    1815             :  * get_func_leakproof
    1816             :  *     Given procedure id, return the function's leakproof field.
    1817             :  */
    1818             : bool
    1819        5076 : get_func_leakproof(Oid funcid)
    1820             : {
    1821             :     HeapTuple   tp;
    1822             :     bool        result;
    1823             : 
    1824        5076 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1825        5076 :     if (!HeapTupleIsValid(tp))
    1826           0 :         elog(ERROR, "cache lookup failed for function %u", funcid);
    1827             : 
    1828        5076 :     result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
    1829        5076 :     ReleaseSysCache(tp);
    1830        5076 :     return result;
    1831             : }
    1832             : 
    1833             : /*
    1834             :  * get_func_support
    1835             :  *
    1836             :  *      Returns the support function OID associated with a given function,
    1837             :  *      or InvalidOid if there is none.
    1838             :  */
    1839             : RegProcedure
    1840       27812 : get_func_support(Oid funcid)
    1841             : {
    1842             :     HeapTuple   tp;
    1843             : 
    1844       27812 :     tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
    1845       27812 :     if (HeapTupleIsValid(tp))
    1846             :     {
    1847       27812 :         Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
    1848             :         RegProcedure result;
    1849             : 
    1850       27812 :         result = functup->prosupport;
    1851       27812 :         ReleaseSysCache(tp);
    1852       27812 :         return result;
    1853             :     }
    1854             :     else
    1855           0 :         return (RegProcedure) InvalidOid;
    1856             : }
    1857             : 
    1858             : /*              ---------- RELATION CACHE ----------                     */
    1859             : 
    1860             : /*
    1861             :  * get_relname_relid
    1862             :  *      Given name and namespace of a relation, look up the OID.
    1863             :  *
    1864             :  * Returns InvalidOid if there is no such relation.
    1865             :  */
    1866             : Oid
    1867     2142038 : get_relname_relid(const char *relname, Oid relnamespace)
    1868             : {
    1869     2142038 :     return GetSysCacheOid2(RELNAMENSP, Anum_pg_class_oid,
    1870             :                            PointerGetDatum(relname),
    1871             :                            ObjectIdGetDatum(relnamespace));
    1872             : }
    1873             : 
    1874             : #ifdef NOT_USED
    1875             : /*
    1876             :  * get_relnatts
    1877             :  *
    1878             :  *      Returns the number of attributes for a given relation.
    1879             :  */
    1880             : int
    1881             : get_relnatts(Oid relid)
    1882             : {
    1883             :     HeapTuple   tp;
    1884             : 
    1885             :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1886             :     if (HeapTupleIsValid(tp))
    1887             :     {
    1888             :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1889             :         int         result;
    1890             : 
    1891             :         result = reltup->relnatts;
    1892             :         ReleaseSysCache(tp);
    1893             :         return result;
    1894             :     }
    1895             :     else
    1896             :         return InvalidAttrNumber;
    1897             : }
    1898             : #endif
    1899             : 
    1900             : /*
    1901             :  * get_rel_name
    1902             :  *      Returns the name of a given relation.
    1903             :  *
    1904             :  * Returns a palloc'd copy of the string, or NULL if no such relation.
    1905             :  *
    1906             :  * NOTE: since relation name is not unique, be wary of code that uses this
    1907             :  * for anything except preparing error messages.
    1908             :  */
    1909             : char *
    1910       86452 : get_rel_name(Oid relid)
    1911             : {
    1912             :     HeapTuple   tp;
    1913             : 
    1914       86452 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1915       86452 :     if (HeapTupleIsValid(tp))
    1916             :     {
    1917       86440 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1918             :         char       *result;
    1919             : 
    1920       86440 :         result = pstrdup(NameStr(reltup->relname));
    1921       86440 :         ReleaseSysCache(tp);
    1922       86440 :         return result;
    1923             :     }
    1924             :     else
    1925          12 :         return NULL;
    1926             : }
    1927             : 
    1928             : /*
    1929             :  * get_rel_namespace
    1930             :  *
    1931             :  *      Returns the pg_namespace OID associated with a given relation.
    1932             :  */
    1933             : Oid
    1934      317624 : get_rel_namespace(Oid relid)
    1935             : {
    1936             :     HeapTuple   tp;
    1937             : 
    1938      317624 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1939      317624 :     if (HeapTupleIsValid(tp))
    1940             :     {
    1941      317624 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1942             :         Oid         result;
    1943             : 
    1944      317624 :         result = reltup->relnamespace;
    1945      317624 :         ReleaseSysCache(tp);
    1946      317624 :         return result;
    1947             :     }
    1948             :     else
    1949           0 :         return InvalidOid;
    1950             : }
    1951             : 
    1952             : /*
    1953             :  * get_rel_type_id
    1954             :  *
    1955             :  *      Returns the pg_type OID associated with a given relation.
    1956             :  *
    1957             :  * Note: not all pg_class entries have associated pg_type OIDs; so be
    1958             :  * careful to check for InvalidOid result.
    1959             :  */
    1960             : Oid
    1961       36424 : get_rel_type_id(Oid relid)
    1962             : {
    1963             :     HeapTuple   tp;
    1964             : 
    1965       36424 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1966       36424 :     if (HeapTupleIsValid(tp))
    1967             :     {
    1968       36424 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1969             :         Oid         result;
    1970             : 
    1971       36424 :         result = reltup->reltype;
    1972       36424 :         ReleaseSysCache(tp);
    1973       36424 :         return result;
    1974             :     }
    1975             :     else
    1976           0 :         return InvalidOid;
    1977             : }
    1978             : 
    1979             : /*
    1980             :  * get_rel_relkind
    1981             :  *
    1982             :  *      Returns the relkind associated with a given relation.
    1983             :  */
    1984             : char
    1985      151610 : get_rel_relkind(Oid relid)
    1986             : {
    1987             :     HeapTuple   tp;
    1988             : 
    1989      151610 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    1990      151610 :     if (HeapTupleIsValid(tp))
    1991             :     {
    1992      151610 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    1993             :         char        result;
    1994             : 
    1995      151610 :         result = reltup->relkind;
    1996      151610 :         ReleaseSysCache(tp);
    1997      151610 :         return result;
    1998             :     }
    1999             :     else
    2000           0 :         return '\0';
    2001             : }
    2002             : 
    2003             : /*
    2004             :  * get_rel_relispartition
    2005             :  *
    2006             :  *      Returns the relispartition flag associated with a given relation.
    2007             :  */
    2008             : bool
    2009        4718 : get_rel_relispartition(Oid relid)
    2010             : {
    2011             :     HeapTuple   tp;
    2012             : 
    2013        4718 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    2014        4718 :     if (HeapTupleIsValid(tp))
    2015             :     {
    2016        4718 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    2017             :         bool        result;
    2018             : 
    2019        4718 :         result = reltup->relispartition;
    2020        4718 :         ReleaseSysCache(tp);
    2021        4718 :         return result;
    2022             :     }
    2023             :     else
    2024           0 :         return false;
    2025             : }
    2026             : 
    2027             : /*
    2028             :  * get_rel_tablespace
    2029             :  *
    2030             :  *      Returns the pg_tablespace OID associated with a given relation.
    2031             :  *
    2032             :  * Note: InvalidOid might mean either that we couldn't find the relation,
    2033             :  * or that it is in the database's default tablespace.
    2034             :  */
    2035             : Oid
    2036        7638 : get_rel_tablespace(Oid relid)
    2037             : {
    2038             :     HeapTuple   tp;
    2039             : 
    2040        7638 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    2041        7638 :     if (HeapTupleIsValid(tp))
    2042             :     {
    2043        7638 :         Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
    2044             :         Oid         result;
    2045             : 
    2046        7638 :         result = reltup->reltablespace;
    2047        7638 :         ReleaseSysCache(tp);
    2048        7638 :         return result;
    2049             :     }
    2050             :     else
    2051           0 :         return InvalidOid;
    2052             : }
    2053             : 
    2054             : /*
    2055             :  * get_rel_persistence
    2056             :  *
    2057             :  *      Returns the relpersistence associated with a given relation.
    2058             :  */
    2059             : char
    2060      264666 : get_rel_persistence(Oid relid)
    2061             : {
    2062             :     HeapTuple   tp;
    2063             :     Form_pg_class reltup;
    2064             :     char        result;
    2065             : 
    2066      264666 :     tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
    2067      264666 :     if (!HeapTupleIsValid(tp))
    2068           0 :         elog(ERROR, "cache lookup failed for relation %u", relid);
    2069      264666 :     reltup = (Form_pg_class) GETSTRUCT(tp);
    2070      264666 :     result = reltup->relpersistence;
    2071      264666 :     ReleaseSysCache(tp);
    2072             : 
    2073      264666 :     return result;
    2074             : }
    2075             : 
    2076             : 
    2077             : /*              ---------- TRANSFORM CACHE ----------                        */
    2078             : 
    2079             : Oid
    2080        1544 : get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
    2081             : {
    2082             :     HeapTuple   tup;
    2083             : 
    2084        1544 :     if (!list_member_oid(trftypes, typid))
    2085        1382 :         return InvalidOid;
    2086             : 
    2087         162 :     tup = SearchSysCache2(TRFTYPELANG, typid, langid);
    2088         162 :     if (HeapTupleIsValid(tup))
    2089             :     {
    2090             :         Oid         funcid;
    2091             : 
    2092         162 :         funcid = ((Form_pg_transform) GETSTRUCT(tup))->trffromsql;
    2093         162 :         ReleaseSysCache(tup);
    2094         162 :         return funcid;
    2095             :     }
    2096             :     else
    2097           0 :         return InvalidOid;
    2098             : }
    2099             : 
    2100             : Oid
    2101        2052 : get_transform_tosql(Oid typid, Oid langid, List *trftypes)
    2102             : {
    2103             :     HeapTuple   tup;
    2104             : 
    2105        2052 :     if (!list_member_oid(trftypes, typid))
    2106        1870 :         return InvalidOid;
    2107             : 
    2108         182 :     tup = SearchSysCache2(TRFTYPELANG, typid, langid);
    2109         182 :     if (HeapTupleIsValid(tup))
    2110             :     {
    2111             :         Oid         funcid;
    2112             : 
    2113         182 :         funcid = ((Form_pg_transform) GETSTRUCT(tup))->trftosql;
    2114         182 :         ReleaseSysCache(tup);
    2115         182 :         return funcid;
    2116             :     }
    2117             :     else
    2118           0 :         return InvalidOid;
    2119             : }
    2120             : 
    2121             : 
    2122             : /*              ---------- TYPE CACHE ----------                         */
    2123             : 
    2124             : /*
    2125             :  * get_typisdefined
    2126             :  *
    2127             :  *      Given the type OID, determine whether the type is defined
    2128             :  *      (if not, it's only a shell).
    2129             :  */
    2130             : bool
    2131         278 : get_typisdefined(Oid typid)
    2132             : {
    2133             :     HeapTuple   tp;
    2134             : 
    2135         278 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2136         278 :     if (HeapTupleIsValid(tp))
    2137             :     {
    2138         278 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2139             :         bool        result;
    2140             : 
    2141         278 :         result = typtup->typisdefined;
    2142         278 :         ReleaseSysCache(tp);
    2143         278 :         return result;
    2144             :     }
    2145             :     else
    2146           0 :         return false;
    2147             : }
    2148             : 
    2149             : /*
    2150             :  * get_typlen
    2151             :  *
    2152             :  *      Given the type OID, return the length of the type.
    2153             :  */
    2154             : int16
    2155     2456154 : get_typlen(Oid typid)
    2156             : {
    2157             :     HeapTuple   tp;
    2158             : 
    2159     2456154 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2160     2456154 :     if (HeapTupleIsValid(tp))
    2161             :     {
    2162     2456154 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2163             :         int16       result;
    2164             : 
    2165     2456154 :         result = typtup->typlen;
    2166     2456154 :         ReleaseSysCache(tp);
    2167     2456154 :         return result;
    2168             :     }
    2169             :     else
    2170           0 :         return 0;
    2171             : }
    2172             : 
    2173             : /*
    2174             :  * get_typbyval
    2175             :  *
    2176             :  *      Given the type OID, determine whether the type is returned by value or
    2177             :  *      not.  Returns true if by value, false if by reference.
    2178             :  */
    2179             : bool
    2180       59072 : get_typbyval(Oid typid)
    2181             : {
    2182             :     HeapTuple   tp;
    2183             : 
    2184       59072 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2185       59072 :     if (HeapTupleIsValid(tp))
    2186             :     {
    2187       59072 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2188             :         bool        result;
    2189             : 
    2190       59072 :         result = typtup->typbyval;
    2191       59072 :         ReleaseSysCache(tp);
    2192       59072 :         return result;
    2193             :     }
    2194             :     else
    2195           0 :         return false;
    2196             : }
    2197             : 
    2198             : /*
    2199             :  * get_typlenbyval
    2200             :  *
    2201             :  *      A two-fer: given the type OID, return both typlen and typbyval.
    2202             :  *
    2203             :  *      Since both pieces of info are needed to know how to copy a Datum,
    2204             :  *      many places need both.  Might as well get them with one cache lookup
    2205             :  *      instead of two.  Also, this routine raises an error instead of
    2206             :  *      returning a bogus value when given a bad type OID.
    2207             :  */
    2208             : void
    2209      830206 : get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
    2210             : {
    2211             :     HeapTuple   tp;
    2212             :     Form_pg_type typtup;
    2213             : 
    2214      830206 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2215      830206 :     if (!HeapTupleIsValid(tp))
    2216           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2217      830206 :     typtup = (Form_pg_type) GETSTRUCT(tp);
    2218      830206 :     *typlen = typtup->typlen;
    2219      830206 :     *typbyval = typtup->typbyval;
    2220      830206 :     ReleaseSysCache(tp);
    2221      830206 : }
    2222             : 
    2223             : /*
    2224             :  * get_typlenbyvalalign
    2225             :  *
    2226             :  *      A three-fer: given the type OID, return typlen, typbyval, typalign.
    2227             :  */
    2228             : void
    2229     1657474 : get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
    2230             :                      char *typalign)
    2231             : {
    2232             :     HeapTuple   tp;
    2233             :     Form_pg_type typtup;
    2234             : 
    2235     1657474 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2236     1657474 :     if (!HeapTupleIsValid(tp))
    2237           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2238     1657474 :     typtup = (Form_pg_type) GETSTRUCT(tp);
    2239     1657474 :     *typlen = typtup->typlen;
    2240     1657474 :     *typbyval = typtup->typbyval;
    2241     1657474 :     *typalign = typtup->typalign;
    2242     1657474 :     ReleaseSysCache(tp);
    2243     1657474 : }
    2244             : 
    2245             : /*
    2246             :  * getTypeIOParam
    2247             :  *      Given a pg_type row, select the type OID to pass to I/O functions
    2248             :  *
    2249             :  * Formerly, all I/O functions were passed pg_type.typelem as their second
    2250             :  * parameter, but we now have a more complex rule about what to pass.
    2251             :  * This knowledge is intended to be centralized here --- direct references
    2252             :  * to typelem elsewhere in the code are wrong, if they are associated with
    2253             :  * I/O calls and not with actual subscripting operations!  (But see
    2254             :  * bootstrap.c's boot_get_type_io_data() if you need to change this.)
    2255             :  *
    2256             :  * As of PostgreSQL 8.1, output functions receive only the value itself
    2257             :  * and not any auxiliary parameters, so the name of this routine is now
    2258             :  * a bit of a misnomer ... it should be getTypeInputParam.
    2259             :  */
    2260             : Oid
    2261     2263484 : getTypeIOParam(HeapTuple typeTuple)
    2262             : {
    2263     2263484 :     Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
    2264             : 
    2265             :     /*
    2266             :      * Array types get their typelem as parameter; everybody else gets their
    2267             :      * own type OID as parameter.
    2268             :      */
    2269     2263484 :     if (OidIsValid(typeStruct->typelem))
    2270      166756 :         return typeStruct->typelem;
    2271             :     else
    2272     2096728 :         return typeStruct->oid;
    2273             : }
    2274             : 
    2275             : /*
    2276             :  * get_type_io_data
    2277             :  *
    2278             :  *      A six-fer:  given the type OID, return typlen, typbyval, typalign,
    2279             :  *                  typdelim, typioparam, and IO function OID. The IO function
    2280             :  *                  returned is controlled by IOFuncSelector
    2281             :  */
    2282             : void
    2283      286606 : get_type_io_data(Oid typid,
    2284             :                  IOFuncSelector which_func,
    2285             :                  int16 *typlen,
    2286             :                  bool *typbyval,
    2287             :                  char *typalign,
    2288             :                  char *typdelim,
    2289             :                  Oid *typioparam,
    2290             :                  Oid *func)
    2291             : {
    2292             :     HeapTuple   typeTuple;
    2293             :     Form_pg_type typeStruct;
    2294             : 
    2295             :     /*
    2296             :      * In bootstrap mode, pass it off to bootstrap.c.  This hack allows us to
    2297             :      * use array_in and array_out during bootstrap.
    2298             :      */
    2299      286606 :     if (IsBootstrapProcessingMode())
    2300             :     {
    2301             :         Oid         typinput;
    2302             :         Oid         typoutput;
    2303             : 
    2304      233916 :         boot_get_type_io_data(typid,
    2305             :                               typlen,
    2306             :                               typbyval,
    2307             :                               typalign,
    2308             :                               typdelim,
    2309             :                               typioparam,
    2310             :                               &typinput,
    2311             :                               &typoutput);
    2312      233916 :         switch (which_func)
    2313             :         {
    2314      233916 :             case IOFunc_input:
    2315      233916 :                 *func = typinput;
    2316      233916 :                 break;
    2317           0 :             case IOFunc_output:
    2318           0 :                 *func = typoutput;
    2319           0 :                 break;
    2320           0 :             default:
    2321           0 :                 elog(ERROR, "binary I/O not supported during bootstrap");
    2322             :                 break;
    2323             :         }
    2324      233916 :         return;
    2325             :     }
    2326             : 
    2327       52690 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2328       52690 :     if (!HeapTupleIsValid(typeTuple))
    2329           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2330       52690 :     typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
    2331             : 
    2332       52690 :     *typlen = typeStruct->typlen;
    2333       52690 :     *typbyval = typeStruct->typbyval;
    2334       52690 :     *typalign = typeStruct->typalign;
    2335       52690 :     *typdelim = typeStruct->typdelim;
    2336       52690 :     *typioparam = getTypeIOParam(typeTuple);
    2337       52690 :     switch (which_func)
    2338             :     {
    2339       27288 :         case IOFunc_input:
    2340       27288 :             *func = typeStruct->typinput;
    2341       27288 :             break;
    2342       25306 :         case IOFunc_output:
    2343       25306 :             *func = typeStruct->typoutput;
    2344       25306 :             break;
    2345          56 :         case IOFunc_receive:
    2346          56 :             *func = typeStruct->typreceive;
    2347          56 :             break;
    2348          40 :         case IOFunc_send:
    2349          40 :             *func = typeStruct->typsend;
    2350          40 :             break;
    2351             :     }
    2352       52690 :     ReleaseSysCache(typeTuple);
    2353             : }
    2354             : 
    2355             : #ifdef NOT_USED
    2356             : char
    2357             : get_typalign(Oid typid)
    2358             : {
    2359             :     HeapTuple   tp;
    2360             : 
    2361             :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2362             :     if (HeapTupleIsValid(tp))
    2363             :     {
    2364             :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2365             :         char        result;
    2366             : 
    2367             :         result = typtup->typalign;
    2368             :         ReleaseSysCache(tp);
    2369             :         return result;
    2370             :     }
    2371             :     else
    2372             :         return TYPALIGN_INT;
    2373             : }
    2374             : #endif
    2375             : 
    2376             : char
    2377       60110 : get_typstorage(Oid typid)
    2378             : {
    2379             :     HeapTuple   tp;
    2380             : 
    2381       60110 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2382       60110 :     if (HeapTupleIsValid(tp))
    2383             :     {
    2384       60110 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2385             :         char        result;
    2386             : 
    2387       60110 :         result = typtup->typstorage;
    2388       60110 :         ReleaseSysCache(tp);
    2389       60110 :         return result;
    2390             :     }
    2391             :     else
    2392           0 :         return TYPSTORAGE_PLAIN;
    2393             : }
    2394             : 
    2395             : /*
    2396             :  * get_typdefault
    2397             :  *    Given a type OID, return the type's default value, if any.
    2398             :  *
    2399             :  *    The result is a palloc'd expression node tree, or NULL if there
    2400             :  *    is no defined default for the datatype.
    2401             :  *
    2402             :  * NB: caller should be prepared to coerce result to correct datatype;
    2403             :  * the returned expression tree might produce something of the wrong type.
    2404             :  */
    2405             : Node *
    2406       43764 : get_typdefault(Oid typid)
    2407             : {
    2408             :     HeapTuple   typeTuple;
    2409             :     Form_pg_type type;
    2410             :     Datum       datum;
    2411             :     bool        isNull;
    2412             :     Node       *expr;
    2413             : 
    2414       43764 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2415       43764 :     if (!HeapTupleIsValid(typeTuple))
    2416           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2417       43764 :     type = (Form_pg_type) GETSTRUCT(typeTuple);
    2418             : 
    2419             :     /*
    2420             :      * typdefault and typdefaultbin are potentially null, so don't try to
    2421             :      * access 'em as struct fields. Must do it the hard way with
    2422             :      * SysCacheGetAttr.
    2423             :      */
    2424       43764 :     datum = SysCacheGetAttr(TYPEOID,
    2425             :                             typeTuple,
    2426             :                             Anum_pg_type_typdefaultbin,
    2427             :                             &isNull);
    2428             : 
    2429       43764 :     if (!isNull)
    2430             :     {
    2431             :         /* We have an expression default */
    2432         212 :         expr = stringToNode(TextDatumGetCString(datum));
    2433             :     }
    2434             :     else
    2435             :     {
    2436             :         /* Perhaps we have a plain literal default */
    2437       43552 :         datum = SysCacheGetAttr(TYPEOID,
    2438             :                                 typeTuple,
    2439             :                                 Anum_pg_type_typdefault,
    2440             :                                 &isNull);
    2441             : 
    2442       43552 :         if (!isNull)
    2443             :         {
    2444             :             char       *strDefaultVal;
    2445             : 
    2446             :             /* Convert text datum to C string */
    2447          12 :             strDefaultVal = TextDatumGetCString(datum);
    2448             :             /* Convert C string to a value of the given type */
    2449          12 :             datum = OidInputFunctionCall(type->typinput, strDefaultVal,
    2450             :                                          getTypeIOParam(typeTuple), -1);
    2451             :             /* Build a Const node containing the value */
    2452          12 :             expr = (Node *) makeConst(typid,
    2453             :                                       -1,
    2454             :                                       type->typcollation,
    2455          12 :                                       type->typlen,
    2456             :                                       datum,
    2457             :                                       false,
    2458          12 :                                       type->typbyval);
    2459          12 :             pfree(strDefaultVal);
    2460             :         }
    2461             :         else
    2462             :         {
    2463             :             /* No default */
    2464       43540 :             expr = NULL;
    2465             :         }
    2466             :     }
    2467             : 
    2468       43764 :     ReleaseSysCache(typeTuple);
    2469             : 
    2470       43764 :     return expr;
    2471             : }
    2472             : 
    2473             : /*
    2474             :  * getBaseType
    2475             :  *      If the given type is a domain, return its base type;
    2476             :  *      otherwise return the type's own OID.
    2477             :  */
    2478             : Oid
    2479    10533076 : getBaseType(Oid typid)
    2480             : {
    2481    10533076 :     int32       typmod = -1;
    2482             : 
    2483    10533076 :     return getBaseTypeAndTypmod(typid, &typmod);
    2484             : }
    2485             : 
    2486             : /*
    2487             :  * getBaseTypeAndTypmod
    2488             :  *      If the given type is a domain, return its base type and typmod;
    2489             :  *      otherwise return the type's own OID, and leave *typmod unchanged.
    2490             :  *
    2491             :  * Note that the "applied typmod" should be -1 for every domain level
    2492             :  * above the bottommost; therefore, if the passed-in typid is indeed
    2493             :  * a domain, *typmod should be -1.
    2494             :  */
    2495             : Oid
    2496    14812598 : getBaseTypeAndTypmod(Oid typid, int32 *typmod)
    2497             : {
    2498             :     /*
    2499             :      * We loop to find the bottom base type in a stack of domains.
    2500             :      */
    2501             :     for (;;)
    2502     1787080 :     {
    2503             :         HeapTuple   tup;
    2504             :         Form_pg_type typTup;
    2505             : 
    2506    14812598 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2507    14812598 :         if (!HeapTupleIsValid(tup))
    2508           0 :             elog(ERROR, "cache lookup failed for type %u", typid);
    2509    14812598 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2510    14812598 :         if (typTup->typtype != TYPTYPE_DOMAIN)
    2511             :         {
    2512             :             /* Not a domain, so done */
    2513    13025518 :             ReleaseSysCache(tup);
    2514    13025518 :             break;
    2515             :         }
    2516             : 
    2517             :         Assert(*typmod == -1);
    2518     1787080 :         typid = typTup->typbasetype;
    2519     1787080 :         *typmod = typTup->typtypmod;
    2520             : 
    2521     1787080 :         ReleaseSysCache(tup);
    2522             :     }
    2523             : 
    2524    13025518 :     return typid;
    2525             : }
    2526             : 
    2527             : /*
    2528             :  * get_typavgwidth
    2529             :  *
    2530             :  *    Given a type OID and a typmod value (pass -1 if typmod is unknown),
    2531             :  *    estimate the average width of values of the type.  This is used by
    2532             :  *    the planner, which doesn't require absolutely correct results;
    2533             :  *    it's OK (and expected) to guess if we don't know for sure.
    2534             :  */
    2535             : int32
    2536     1375358 : get_typavgwidth(Oid typid, int32 typmod)
    2537             : {
    2538     1375358 :     int         typlen = get_typlen(typid);
    2539             :     int32       maxwidth;
    2540             : 
    2541             :     /*
    2542             :      * Easy if it's a fixed-width type
    2543             :      */
    2544     1375358 :     if (typlen > 0)
    2545      874240 :         return typlen;
    2546             : 
    2547             :     /*
    2548             :      * type_maximum_size knows the encoding of typmod for some datatypes;
    2549             :      * don't duplicate that knowledge here.
    2550             :      */
    2551      501118 :     maxwidth = type_maximum_size(typid, typmod);
    2552      501118 :     if (maxwidth > 0)
    2553             :     {
    2554             :         /*
    2555             :          * For BPCHAR, the max width is also the only width.  Otherwise we
    2556             :          * need to guess about the typical data width given the max. A sliding
    2557             :          * scale for percentage of max width seems reasonable.
    2558             :          */
    2559       24840 :         if (typid == BPCHAROID)
    2560       15690 :             return maxwidth;
    2561        9150 :         if (maxwidth <= 32)
    2562        4554 :             return maxwidth;    /* assume full width */
    2563        4596 :         if (maxwidth < 1000)
    2564        4484 :             return 32 + (maxwidth - 32) / 2;    /* assume 50% */
    2565             : 
    2566             :         /*
    2567             :          * Beyond 1000, assume we're looking at something like
    2568             :          * "varchar(10000)" where the limit isn't actually reached often, and
    2569             :          * use a fixed estimate.
    2570             :          */
    2571         112 :         return 32 + (1000 - 32) / 2;
    2572             :     }
    2573             : 
    2574             :     /*
    2575             :      * Oops, we have no idea ... wild guess time.
    2576             :      */
    2577      476278 :     return 32;
    2578             : }
    2579             : 
    2580             : /*
    2581             :  * get_typtype
    2582             :  *
    2583             :  *      Given the type OID, find if it is a basic type, a complex type, etc.
    2584             :  *      It returns the null char if the cache lookup fails...
    2585             :  */
    2586             : char
    2587     2660064 : get_typtype(Oid typid)
    2588             : {
    2589             :     HeapTuple   tp;
    2590             : 
    2591     2660064 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2592     2660064 :     if (HeapTupleIsValid(tp))
    2593             :     {
    2594     2659942 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2595             :         char        result;
    2596             : 
    2597     2659942 :         result = typtup->typtype;
    2598     2659942 :         ReleaseSysCache(tp);
    2599     2659942 :         return result;
    2600             :     }
    2601             :     else
    2602         122 :         return '\0';
    2603             : }
    2604             : 
    2605             : /*
    2606             :  * type_is_rowtype
    2607             :  *
    2608             :  *      Convenience function to determine whether a type OID represents
    2609             :  *      a "rowtype" type --- either RECORD or a named composite type
    2610             :  *      (including a domain over a named composite type).
    2611             :  */
    2612             : bool
    2613      153258 : type_is_rowtype(Oid typid)
    2614             : {
    2615      153258 :     if (typid == RECORDOID)
    2616       82254 :         return true;            /* easy case */
    2617       71004 :     switch (get_typtype(typid))
    2618             :     {
    2619        3524 :         case TYPTYPE_COMPOSITE:
    2620        3524 :             return true;
    2621         264 :         case TYPTYPE_DOMAIN:
    2622         264 :             if (get_typtype(getBaseType(typid)) == TYPTYPE_COMPOSITE)
    2623          82 :                 return true;
    2624         182 :             break;
    2625       67216 :         default:
    2626       67216 :             break;
    2627             :     }
    2628       67398 :     return false;
    2629             : }
    2630             : 
    2631             : /*
    2632             :  * type_is_enum
    2633             :  *    Returns true if the given type is an enum type.
    2634             :  */
    2635             : bool
    2636      195428 : type_is_enum(Oid typid)
    2637             : {
    2638      195428 :     return (get_typtype(typid) == TYPTYPE_ENUM);
    2639             : }
    2640             : 
    2641             : /*
    2642             :  * type_is_range
    2643             :  *    Returns true if the given type is a range type.
    2644             :  */
    2645             : bool
    2646       32878 : type_is_range(Oid typid)
    2647             : {
    2648       32878 :     return (get_typtype(typid) == TYPTYPE_RANGE);
    2649             : }
    2650             : 
    2651             : /*
    2652             :  * type_is_multirange
    2653             :  *    Returns true if the given type is a multirange type.
    2654             :  */
    2655             : bool
    2656      141894 : type_is_multirange(Oid typid)
    2657             : {
    2658      141894 :     return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
    2659             : }
    2660             : 
    2661             : /*
    2662             :  * get_type_category_preferred
    2663             :  *
    2664             :  *      Given the type OID, fetch its category and preferred-type status.
    2665             :  *      Throws error on failure.
    2666             :  */
    2667             : void
    2668      645432 : get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
    2669             : {
    2670             :     HeapTuple   tp;
    2671             :     Form_pg_type typtup;
    2672             : 
    2673      645432 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2674      645432 :     if (!HeapTupleIsValid(tp))
    2675           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    2676      645432 :     typtup = (Form_pg_type) GETSTRUCT(tp);
    2677      645432 :     *typcategory = typtup->typcategory;
    2678      645432 :     *typispreferred = typtup->typispreferred;
    2679      645432 :     ReleaseSysCache(tp);
    2680      645432 : }
    2681             : 
    2682             : /*
    2683             :  * get_typ_typrelid
    2684             :  *
    2685             :  *      Given the type OID, get the typrelid (InvalidOid if not a complex
    2686             :  *      type).
    2687             :  */
    2688             : Oid
    2689       87184 : get_typ_typrelid(Oid typid)
    2690             : {
    2691             :     HeapTuple   tp;
    2692             : 
    2693       87184 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2694       87184 :     if (HeapTupleIsValid(tp))
    2695             :     {
    2696       87184 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2697             :         Oid         result;
    2698             : 
    2699       87184 :         result = typtup->typrelid;
    2700       87184 :         ReleaseSysCache(tp);
    2701       87184 :         return result;
    2702             :     }
    2703             :     else
    2704           0 :         return InvalidOid;
    2705             : }
    2706             : 
    2707             : /*
    2708             :  * get_element_type
    2709             :  *
    2710             :  *      Given the type OID, get the typelem (InvalidOid if not an array type).
    2711             :  *
    2712             :  * NB: this only succeeds for "true" arrays having array_subscript_handler
    2713             :  * as typsubscript.  For other types, InvalidOid is returned independently
    2714             :  * of whether they have typelem or typsubscript set.
    2715             :  */
    2716             : Oid
    2717     2995054 : get_element_type(Oid typid)
    2718             : {
    2719             :     HeapTuple   tp;
    2720             : 
    2721     2995054 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2722     2995054 :     if (HeapTupleIsValid(tp))
    2723             :     {
    2724     2995020 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2725             :         Oid         result;
    2726             : 
    2727     2995020 :         if (IsTrueArrayType(typtup))
    2728      182942 :             result = typtup->typelem;
    2729             :         else
    2730     2812078 :             result = InvalidOid;
    2731     2995020 :         ReleaseSysCache(tp);
    2732     2995020 :         return result;
    2733             :     }
    2734             :     else
    2735          34 :         return InvalidOid;
    2736             : }
    2737             : 
    2738             : /*
    2739             :  * get_array_type
    2740             :  *
    2741             :  *      Given the type OID, get the corresponding "true" array type.
    2742             :  *      Returns InvalidOid if no array type can be found.
    2743             :  */
    2744             : Oid
    2745      181000 : get_array_type(Oid typid)
    2746             : {
    2747             :     HeapTuple   tp;
    2748      181000 :     Oid         result = InvalidOid;
    2749             : 
    2750      181000 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2751      181000 :     if (HeapTupleIsValid(tp))
    2752             :     {
    2753      181000 :         result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
    2754      181000 :         ReleaseSysCache(tp);
    2755             :     }
    2756      181000 :     return result;
    2757             : }
    2758             : 
    2759             : /*
    2760             :  * get_promoted_array_type
    2761             :  *
    2762             :  *      The "promoted" type is what you'd get from an ARRAY(SELECT ...)
    2763             :  *      construct, that is, either the corresponding "true" array type
    2764             :  *      if the input is a scalar type that has such an array type,
    2765             :  *      or the same type if the input is already a "true" array type.
    2766             :  *      Returns InvalidOid if neither rule is satisfied.
    2767             :  */
    2768             : Oid
    2769       21272 : get_promoted_array_type(Oid typid)
    2770             : {
    2771       21272 :     Oid         array_type = get_array_type(typid);
    2772             : 
    2773       21272 :     if (OidIsValid(array_type))
    2774       21236 :         return array_type;
    2775          36 :     if (OidIsValid(get_element_type(typid)))
    2776          36 :         return typid;
    2777           0 :     return InvalidOid;
    2778             : }
    2779             : 
    2780             : /*
    2781             :  * get_base_element_type
    2782             :  *      Given the type OID, get the typelem, looking "through" any domain
    2783             :  *      to its underlying array type.
    2784             :  *
    2785             :  * This is equivalent to get_element_type(getBaseType(typid)), but avoids
    2786             :  * an extra cache lookup.  Note that it fails to provide any information
    2787             :  * about the typmod of the array.
    2788             :  */
    2789             : Oid
    2790      283878 : get_base_element_type(Oid typid)
    2791             : {
    2792             :     /*
    2793             :      * We loop to find the bottom base type in a stack of domains.
    2794             :      */
    2795             :     for (;;)
    2796          66 :     {
    2797             :         HeapTuple   tup;
    2798             :         Form_pg_type typTup;
    2799             : 
    2800      283878 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2801      283878 :         if (!HeapTupleIsValid(tup))
    2802        1352 :             break;
    2803      282526 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2804      282526 :         if (typTup->typtype != TYPTYPE_DOMAIN)
    2805             :         {
    2806             :             /* Not a domain, so stop descending */
    2807             :             Oid         result;
    2808             : 
    2809             :             /* This test must match get_element_type */
    2810      282460 :             if (IsTrueArrayType(typTup))
    2811      118412 :                 result = typTup->typelem;
    2812             :             else
    2813      164048 :                 result = InvalidOid;
    2814      282460 :             ReleaseSysCache(tup);
    2815      282460 :             return result;
    2816             :         }
    2817             : 
    2818          66 :         typid = typTup->typbasetype;
    2819          66 :         ReleaseSysCache(tup);
    2820             :     }
    2821             : 
    2822             :     /* Like get_element_type, silently return InvalidOid for bogus input */
    2823        1352 :     return InvalidOid;
    2824             : }
    2825             : 
    2826             : /*
    2827             :  * getTypeInputInfo
    2828             :  *
    2829             :  *      Get info needed for converting values of a type to internal form
    2830             :  */
    2831             : void
    2832      715352 : getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
    2833             : {
    2834             :     HeapTuple   typeTuple;
    2835             :     Form_pg_type pt;
    2836             : 
    2837      715352 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2838      715352 :     if (!HeapTupleIsValid(typeTuple))
    2839           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2840      715352 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2841             : 
    2842      715352 :     if (!pt->typisdefined)
    2843           0 :         ereport(ERROR,
    2844             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2845             :                  errmsg("type %s is only a shell",
    2846             :                         format_type_be(type))));
    2847      715352 :     if (!OidIsValid(pt->typinput))
    2848           0 :         ereport(ERROR,
    2849             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2850             :                  errmsg("no input function available for type %s",
    2851             :                         format_type_be(type))));
    2852             : 
    2853      715352 :     *typInput = pt->typinput;
    2854      715352 :     *typIOParam = getTypeIOParam(typeTuple);
    2855             : 
    2856      715352 :     ReleaseSysCache(typeTuple);
    2857      715352 : }
    2858             : 
    2859             : /*
    2860             :  * getTypeOutputInfo
    2861             :  *
    2862             :  *      Get info needed for printing values of a type
    2863             :  */
    2864             : void
    2865     1357222 : getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
    2866             : {
    2867             :     HeapTuple   typeTuple;
    2868             :     Form_pg_type pt;
    2869             : 
    2870     1357222 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2871     1357222 :     if (!HeapTupleIsValid(typeTuple))
    2872           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2873     1357222 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2874             : 
    2875     1357222 :     if (!pt->typisdefined)
    2876           0 :         ereport(ERROR,
    2877             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2878             :                  errmsg("type %s is only a shell",
    2879             :                         format_type_be(type))));
    2880     1357222 :     if (!OidIsValid(pt->typoutput))
    2881           0 :         ereport(ERROR,
    2882             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2883             :                  errmsg("no output function available for type %s",
    2884             :                         format_type_be(type))));
    2885             : 
    2886     1357222 :     *typOutput = pt->typoutput;
    2887     1357222 :     *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
    2888             : 
    2889     1357222 :     ReleaseSysCache(typeTuple);
    2890     1357222 : }
    2891             : 
    2892             : /*
    2893             :  * getTypeBinaryInputInfo
    2894             :  *
    2895             :  *      Get info needed for binary input of values of a type
    2896             :  */
    2897             : void
    2898      313892 : getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
    2899             : {
    2900             :     HeapTuple   typeTuple;
    2901             :     Form_pg_type pt;
    2902             : 
    2903      313892 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2904      313892 :     if (!HeapTupleIsValid(typeTuple))
    2905           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2906      313892 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2907             : 
    2908      313892 :     if (!pt->typisdefined)
    2909           0 :         ereport(ERROR,
    2910             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2911             :                  errmsg("type %s is only a shell",
    2912             :                         format_type_be(type))));
    2913      313892 :     if (!OidIsValid(pt->typreceive))
    2914           2 :         ereport(ERROR,
    2915             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2916             :                  errmsg("no binary input function available for type %s",
    2917             :                         format_type_be(type))));
    2918             : 
    2919      313890 :     *typReceive = pt->typreceive;
    2920      313890 :     *typIOParam = getTypeIOParam(typeTuple);
    2921             : 
    2922      313890 :     ReleaseSysCache(typeTuple);
    2923      313890 : }
    2924             : 
    2925             : /*
    2926             :  * getTypeBinaryOutputInfo
    2927             :  *
    2928             :  *      Get info needed for binary output of values of a type
    2929             :  */
    2930             : void
    2931        2232 : getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
    2932             : {
    2933             :     HeapTuple   typeTuple;
    2934             :     Form_pg_type pt;
    2935             : 
    2936        2232 :     typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
    2937        2232 :     if (!HeapTupleIsValid(typeTuple))
    2938           0 :         elog(ERROR, "cache lookup failed for type %u", type);
    2939        2232 :     pt = (Form_pg_type) GETSTRUCT(typeTuple);
    2940             : 
    2941        2232 :     if (!pt->typisdefined)
    2942           0 :         ereport(ERROR,
    2943             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2944             :                  errmsg("type %s is only a shell",
    2945             :                         format_type_be(type))));
    2946        2232 :     if (!OidIsValid(pt->typsend))
    2947           2 :         ereport(ERROR,
    2948             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2949             :                  errmsg("no binary output function available for type %s",
    2950             :                         format_type_be(type))));
    2951             : 
    2952        2230 :     *typSend = pt->typsend;
    2953        2230 :     *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
    2954             : 
    2955        2230 :     ReleaseSysCache(typeTuple);
    2956        2230 : }
    2957             : 
    2958             : /*
    2959             :  * get_typmodin
    2960             :  *
    2961             :  *      Given the type OID, return the type's typmodin procedure, if any.
    2962             :  */
    2963             : Oid
    2964           0 : get_typmodin(Oid typid)
    2965             : {
    2966             :     HeapTuple   tp;
    2967             : 
    2968           0 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2969           0 :     if (HeapTupleIsValid(tp))
    2970             :     {
    2971           0 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2972             :         Oid         result;
    2973             : 
    2974           0 :         result = typtup->typmodin;
    2975           0 :         ReleaseSysCache(tp);
    2976           0 :         return result;
    2977             :     }
    2978             :     else
    2979           0 :         return InvalidOid;
    2980             : }
    2981             : 
    2982             : #ifdef NOT_USED
    2983             : /*
    2984             :  * get_typmodout
    2985             :  *
    2986             :  *      Given the type OID, return the type's typmodout procedure, if any.
    2987             :  */
    2988             : Oid
    2989             : get_typmodout(Oid typid)
    2990             : {
    2991             :     HeapTuple   tp;
    2992             : 
    2993             :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    2994             :     if (HeapTupleIsValid(tp))
    2995             :     {
    2996             :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    2997             :         Oid         result;
    2998             : 
    2999             :         result = typtup->typmodout;
    3000             :         ReleaseSysCache(tp);
    3001             :         return result;
    3002             :     }
    3003             :     else
    3004             :         return InvalidOid;
    3005             : }
    3006             : #endif                          /* NOT_USED */
    3007             : 
    3008             : /*
    3009             :  * get_typcollation
    3010             :  *
    3011             :  *      Given the type OID, return the type's typcollation attribute.
    3012             :  */
    3013             : Oid
    3014     6738322 : get_typcollation(Oid typid)
    3015             : {
    3016             :     HeapTuple   tp;
    3017             : 
    3018     6738322 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    3019     6738322 :     if (HeapTupleIsValid(tp))
    3020             :     {
    3021     6738306 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
    3022             :         Oid         result;
    3023             : 
    3024     6738306 :         result = typtup->typcollation;
    3025     6738306 :         ReleaseSysCache(tp);
    3026     6738306 :         return result;
    3027             :     }
    3028             :     else
    3029          16 :         return InvalidOid;
    3030             : }
    3031             : 
    3032             : 
    3033             : /*
    3034             :  * type_is_collatable
    3035             :  *
    3036             :  *      Return whether the type cares about collations
    3037             :  */
    3038             : bool
    3039     1935486 : type_is_collatable(Oid typid)
    3040             : {
    3041     1935486 :     return OidIsValid(get_typcollation(typid));
    3042             : }
    3043             : 
    3044             : 
    3045             : /*
    3046             :  * get_typsubscript
    3047             :  *
    3048             :  *      Given the type OID, return the type's subscripting handler's OID,
    3049             :  *      if it has one.
    3050             :  *
    3051             :  * If typelemp isn't NULL, we also store the type's typelem value there.
    3052             :  * This saves some callers an extra catalog lookup.
    3053             :  */
    3054             : RegProcedure
    3055       36844 : get_typsubscript(Oid typid, Oid *typelemp)
    3056             : {
    3057             :     HeapTuple   tp;
    3058             : 
    3059       36844 :     tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    3060       36844 :     if (HeapTupleIsValid(tp))
    3061             :     {
    3062       36844 :         Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
    3063       36844 :         RegProcedure handler = typform->typsubscript;
    3064             : 
    3065       36844 :         if (typelemp)
    3066       18328 :             *typelemp = typform->typelem;
    3067       36844 :         ReleaseSysCache(tp);
    3068       36844 :         return handler;
    3069             :     }
    3070             :     else
    3071             :     {
    3072           0 :         if (typelemp)
    3073           0 :             *typelemp = InvalidOid;
    3074           0 :         return InvalidOid;
    3075             :     }
    3076             : }
    3077             : 
    3078             : /*
    3079             :  * getSubscriptingRoutines
    3080             :  *
    3081             :  *      Given the type OID, fetch the type's subscripting methods struct.
    3082             :  *      Return NULL if type is not subscriptable.
    3083             :  *
    3084             :  * If typelemp isn't NULL, we also store the type's typelem value there.
    3085             :  * This saves some callers an extra catalog lookup.
    3086             :  */
    3087             : const struct SubscriptRoutines *
    3088       36790 : getSubscriptingRoutines(Oid typid, Oid *typelemp)
    3089             : {
    3090       36790 :     RegProcedure typsubscript = get_typsubscript(typid, typelemp);
    3091             : 
    3092       36790 :     if (!OidIsValid(typsubscript))
    3093          10 :         return NULL;
    3094             : 
    3095       36780 :     return (const struct SubscriptRoutines *)
    3096       36780 :         DatumGetPointer(OidFunctionCall0(typsubscript));
    3097             : }
    3098             : 
    3099             : 
    3100             : /*              ---------- STATISTICS CACHE ----------                   */
    3101             : 
    3102             : /*
    3103             :  * get_attavgwidth
    3104             :  *
    3105             :  *    Given the table and attribute number of a column, get the average
    3106             :  *    width of entries in the column.  Return zero if no data available.
    3107             :  *
    3108             :  * Currently this is only consulted for individual tables, not for inheritance
    3109             :  * trees, so we don't need an "inh" parameter.
    3110             :  *
    3111             :  * Calling a hook at this point looks somewhat strange, but is required
    3112             :  * because the optimizer calls this function without any other way for
    3113             :  * plug-ins to control the result.
    3114             :  */
    3115             : int32
    3116      941406 : get_attavgwidth(Oid relid, AttrNumber attnum)
    3117             : {
    3118             :     HeapTuple   tp;
    3119             :     int32       stawidth;
    3120             : 
    3121      941406 :     if (get_attavgwidth_hook)
    3122             :     {
    3123           0 :         stawidth = (*get_attavgwidth_hook) (relid, attnum);
    3124           0 :         if (stawidth > 0)
    3125           0 :             return stawidth;
    3126             :     }
    3127      941406 :     tp = SearchSysCache3(STATRELATTINH,
    3128             :                          ObjectIdGetDatum(relid),
    3129             :                          Int16GetDatum(attnum),
    3130             :                          BoolGetDatum(false));
    3131      941406 :     if (HeapTupleIsValid(tp))
    3132             :     {
    3133      456994 :         stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
    3134      456994 :         ReleaseSysCache(tp);
    3135      456994 :         if (stawidth > 0)
    3136      447754 :             return stawidth;
    3137             :     }
    3138      493652 :     return 0;
    3139             : }
    3140             : 
    3141             : /*
    3142             :  * get_attstatsslot
    3143             :  *
    3144             :  *      Extract the contents of a "slot" of a pg_statistic tuple.
    3145             :  *      Returns true if requested slot type was found, else false.
    3146             :  *
    3147             :  * Unlike other routines in this file, this takes a pointer to an
    3148             :  * already-looked-up tuple in the pg_statistic cache.  We do this since
    3149             :  * most callers will want to extract more than one value from the cache
    3150             :  * entry, and we don't want to repeat the cache lookup unnecessarily.
    3151             :  * Also, this API allows this routine to be used with statistics tuples
    3152             :  * that have been provided by a stats hook and didn't really come from
    3153             :  * pg_statistic.
    3154             :  *
    3155             :  * sslot: pointer to output area (typically, a local variable in the caller).
    3156             :  * statstuple: pg_statistic tuple to be examined.
    3157             :  * reqkind: STAKIND code for desired statistics slot kind.
    3158             :  * reqop: STAOP value wanted, or InvalidOid if don't care.
    3159             :  * flags: bitmask of ATTSTATSSLOT_VALUES and/or ATTSTATSSLOT_NUMBERS.
    3160             :  *
    3161             :  * If a matching slot is found, true is returned, and *sslot is filled thus:
    3162             :  * staop: receives the actual STAOP value.
    3163             :  * stacoll: receives the actual STACOLL value.
    3164             :  * valuetype: receives actual datatype of the elements of stavalues.
    3165             :  * values: receives pointer to an array of the slot's stavalues.
    3166             :  * nvalues: receives number of stavalues.
    3167             :  * numbers: receives pointer to an array of the slot's stanumbers (as float4).
    3168             :  * nnumbers: receives number of stanumbers.
    3169             :  *
    3170             :  * valuetype/values/nvalues are InvalidOid/NULL/0 if ATTSTATSSLOT_VALUES
    3171             :  * wasn't specified.  Likewise, numbers/nnumbers are NULL/0 if
    3172             :  * ATTSTATSSLOT_NUMBERS wasn't specified.
    3173             :  *
    3174             :  * If no matching slot is found, false is returned, and *sslot is zeroed.
    3175             :  *
    3176             :  * Note that the current API doesn't allow for searching for a slot with
    3177             :  * a particular collation.  If we ever actually support recording more than
    3178             :  * one collation, we'll have to extend the API, but for now simple is good.
    3179             :  *
    3180             :  * The data referred to by the fields of sslot is locally palloc'd and
    3181             :  * is independent of the original pg_statistic tuple.  When the caller
    3182             :  * is done with it, call free_attstatsslot to release the palloc'd data.
    3183             :  *
    3184             :  * If it's desirable to call free_attstatsslot when get_attstatsslot might
    3185             :  * not have been called, memset'ing sslot to zeroes will allow that.
    3186             :  *
    3187             :  * Passing flags=0 can be useful to quickly check if the requested slot type
    3188             :  * exists.  In this case no arrays are extracted, so free_attstatsslot need
    3189             :  * not be called.
    3190             :  */
    3191             : bool
    3192     1511070 : get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
    3193             :                  int reqkind, Oid reqop, int flags)
    3194             : {
    3195     1511070 :     Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
    3196             :     int         i;
    3197             :     Datum       val;
    3198             :     ArrayType  *statarray;
    3199             :     Oid         arrayelemtype;
    3200             :     int         narrayelem;
    3201             :     HeapTuple   typeTuple;
    3202             :     Form_pg_type typeForm;
    3203             : 
    3204             :     /* initialize *sslot properly */
    3205     1511070 :     memset(sslot, 0, sizeof(AttStatsSlot));
    3206             : 
    3207     4224164 :     for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
    3208             :     {
    3209     3786626 :         if ((&stats->stakind1)[i] == reqkind &&
    3210      455180 :             (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
    3211             :             break;
    3212             :     }
    3213     1511070 :     if (i >= STATISTIC_NUM_SLOTS)
    3214      437538 :         return false;           /* not there */
    3215             : 
    3216     1073532 :     sslot->staop = (&stats->staop1)[i];
    3217     1073532 :     sslot->stacoll = (&stats->stacoll1)[i];
    3218             : 
    3219     1073532 :     if (flags & ATTSTATSSLOT_VALUES)
    3220             :     {
    3221      531032 :         val = SysCacheGetAttrNotNull(STATRELATTINH, statstuple,
    3222      531032 :                                      Anum_pg_statistic_stavalues1 + i);
    3223             : 
    3224             :         /*
    3225             :          * Detoast the array if needed, and in any case make a copy that's
    3226             :          * under control of this AttStatsSlot.
    3227             :          */
    3228      531032 :         statarray = DatumGetArrayTypePCopy(val);
    3229             : 
    3230             :         /*
    3231             :          * Extract the actual array element type, and pass it back in case the
    3232             :          * caller needs it.
    3233             :          */
    3234      531032 :         sslot->valuetype = arrayelemtype = ARR_ELEMTYPE(statarray);
    3235             : 
    3236             :         /* Need info about element type */
    3237      531032 :         typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
    3238      531032 :         if (!HeapTupleIsValid(typeTuple))
    3239           0 :             elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
    3240      531032 :         typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
    3241             : 
    3242             :         /* Deconstruct array into Datum elements; NULLs not expected */
    3243      531032 :         deconstruct_array(statarray,
    3244             :                           arrayelemtype,
    3245      531032 :                           typeForm->typlen,
    3246      531032 :                           typeForm->typbyval,
    3247      531032 :                           typeForm->typalign,
    3248             :                           &sslot->values, NULL, &sslot->nvalues);
    3249             : 
    3250             :         /*
    3251             :          * If the element type is pass-by-reference, we now have a bunch of
    3252             :          * Datums that are pointers into the statarray, so we need to keep
    3253             :          * that until free_attstatsslot.  Otherwise, all the useful info is in
    3254             :          * sslot->values[], so we can free the array object immediately.
    3255             :          */
    3256      531032 :         if (!typeForm->typbyval)
    3257       37594 :             sslot->values_arr = statarray;
    3258             :         else
    3259      493438 :             pfree(statarray);
    3260             : 
    3261      531032 :         ReleaseSysCache(typeTuple);
    3262             :     }
    3263             : 
    3264     1073532 :     if (flags & ATTSTATSSLOT_NUMBERS)
    3265             :     {
    3266      732432 :         val = SysCacheGetAttrNotNull(STATRELATTINH, statstuple,
    3267      732432 :                                      Anum_pg_statistic_stanumbers1 + i);
    3268             : 
    3269             :         /*
    3270             :          * Detoast the array if needed, and in any case make a copy that's
    3271             :          * under control of this AttStatsSlot.
    3272             :          */
    3273      732432 :         statarray = DatumGetArrayTypePCopy(val);
    3274             : 
    3275             :         /*
    3276             :          * We expect the array to be a 1-D float4 array; verify that. We don't
    3277             :          * need to use deconstruct_array() since the array data is just going
    3278             :          * to look like a C array of float4 values.
    3279             :          */
    3280      732432 :         narrayelem = ARR_DIMS(statarray)[0];
    3281      732432 :         if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
    3282      732432 :             ARR_HASNULL(statarray) ||
    3283      732432 :             ARR_ELEMTYPE(statarray) != FLOAT4OID)
    3284           0 :             elog(ERROR, "stanumbers is not a 1-D float4 array");
    3285             : 
    3286             :         /* Give caller a pointer directly into the statarray */
    3287      732432 :         sslot->numbers = (float4 *) ARR_DATA_PTR(statarray);
    3288      732432 :         sslot->nnumbers = narrayelem;
    3289             : 
    3290             :         /* We'll free the statarray in free_attstatsslot */
    3291      732432 :         sslot->numbers_arr = statarray;
    3292             :     }
    3293             : 
    3294     1073532 :     return true;
    3295             : }
    3296             : 
    3297             : /*
    3298             :  * free_attstatsslot
    3299             :  *      Free data allocated by get_attstatsslot
    3300             :  */
    3301             : void
    3302     1320746 : free_attstatsslot(AttStatsSlot *sslot)
    3303             : {
    3304             :     /* The values[] array was separately palloc'd by deconstruct_array */
    3305     1320746 :     if (sslot->values)
    3306      531032 :         pfree(sslot->values);
    3307             :     /* The numbers[] array points into numbers_arr, do not pfree it */
    3308             :     /* Free the detoasted array objects, if any */
    3309     1320746 :     if (sslot->values_arr)
    3310       37594 :         pfree(sslot->values_arr);
    3311     1320746 :     if (sslot->numbers_arr)
    3312      732432 :         pfree(sslot->numbers_arr);
    3313     1320746 : }
    3314             : 
    3315             : /*              ---------- PG_NAMESPACE CACHE ----------                 */
    3316             : 
    3317             : /*
    3318             :  * get_namespace_name
    3319             :  *      Returns the name of a given namespace
    3320             :  *
    3321             :  * Returns a palloc'd copy of the string, or NULL if no such namespace.
    3322             :  */
    3323             : char *
    3324      861166 : get_namespace_name(Oid nspid)
    3325             : {
    3326             :     HeapTuple   tp;
    3327             : 
    3328      861166 :     tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
    3329      861166 :     if (HeapTupleIsValid(tp))
    3330             :     {
    3331      861148 :         Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
    3332             :         char       *result;
    3333             : 
    3334      861148 :         result = pstrdup(NameStr(nsptup->nspname));
    3335      861148 :         ReleaseSysCache(tp);
    3336      861148 :         return result;
    3337             :     }
    3338             :     else
    3339          18 :         return NULL;
    3340             : }
    3341             : 
    3342             : /*
    3343             :  * get_namespace_name_or_temp
    3344             :  *      As above, but if it is this backend's temporary namespace, return
    3345             :  *      "pg_temp" instead.
    3346             :  */
    3347             : char *
    3348       25720 : get_namespace_name_or_temp(Oid nspid)
    3349             : {
    3350       25720 :     if (isTempNamespace(nspid))
    3351         104 :         return pstrdup("pg_temp");
    3352             :     else
    3353       25616 :         return get_namespace_name(nspid);
    3354             : }
    3355             : 
    3356             : /*              ---------- PG_RANGE CACHES ----------                */
    3357             : 
    3358             : /*
    3359             :  * get_range_subtype
    3360             :  *      Returns the subtype of a given range type
    3361             :  *
    3362             :  * Returns InvalidOid if the type is not a range type.
    3363             :  */
    3364             : Oid
    3365       17564 : get_range_subtype(Oid rangeOid)
    3366             : {
    3367             :     HeapTuple   tp;
    3368             : 
    3369       17564 :     tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
    3370       17564 :     if (HeapTupleIsValid(tp))
    3371             :     {
    3372        9056 :         Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
    3373             :         Oid         result;
    3374             : 
    3375        9056 :         result = rngtup->rngsubtype;
    3376        9056 :         ReleaseSysCache(tp);
    3377        9056 :         return result;
    3378             :     }
    3379             :     else
    3380        8508 :         return InvalidOid;
    3381             : }
    3382             : 
    3383             : /*
    3384             :  * get_range_collation
    3385             :  *      Returns the collation of a given range type
    3386             :  *
    3387             :  * Returns InvalidOid if the type is not a range type,
    3388             :  * or if its subtype is not collatable.
    3389             :  */
    3390             : Oid
    3391         336 : get_range_collation(Oid rangeOid)
    3392             : {
    3393             :     HeapTuple   tp;
    3394             : 
    3395         336 :     tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
    3396         336 :     if (HeapTupleIsValid(tp))
    3397             :     {
    3398         336 :         Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
    3399             :         Oid         result;
    3400             : 
    3401         336 :         result = rngtup->rngcollation;
    3402         336 :         ReleaseSysCache(tp);
    3403         336 :         return result;
    3404             :     }
    3405             :     else
    3406           0 :         return InvalidOid;
    3407             : }
    3408             : 
    3409             : /*
    3410             :  * get_range_multirange
    3411             :  *      Returns the multirange type of a given range type
    3412             :  *
    3413             :  * Returns InvalidOid if the type is not a range type.
    3414             :  */
    3415             : Oid
    3416         174 : get_range_multirange(Oid rangeOid)
    3417             : {
    3418             :     HeapTuple   tp;
    3419             : 
    3420         174 :     tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
    3421         174 :     if (HeapTupleIsValid(tp))
    3422             :     {
    3423         174 :         Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
    3424             :         Oid         result;
    3425             : 
    3426         174 :         result = rngtup->rngmultitypid;
    3427         174 :         ReleaseSysCache(tp);
    3428         174 :         return result;
    3429             :     }
    3430             :     else
    3431           0 :         return InvalidOid;
    3432             : }
    3433             : 
    3434             : /*
    3435             :  * get_multirange_range
    3436             :  *      Returns the range type of a given multirange
    3437             :  *
    3438             :  * Returns InvalidOid if the type is not a multirange.
    3439             :  */
    3440             : Oid
    3441       21834 : get_multirange_range(Oid multirangeOid)
    3442             : {
    3443             :     HeapTuple   tp;
    3444             : 
    3445       21834 :     tp = SearchSysCache1(RANGEMULTIRANGE, ObjectIdGetDatum(multirangeOid));
    3446       21834 :     if (HeapTupleIsValid(tp))
    3447             :     {
    3448        4656 :         Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
    3449             :         Oid         result;
    3450             : 
    3451        4656 :         result = rngtup->rngtypid;
    3452        4656 :         ReleaseSysCache(tp);
    3453        4656 :         return result;
    3454             :     }
    3455             :     else
    3456       17178 :         return InvalidOid;
    3457             : }
    3458             : 
    3459             : /*              ---------- PG_INDEX CACHE ----------                 */
    3460             : 
    3461             : /*
    3462             :  * get_index_column_opclass
    3463             :  *
    3464             :  *      Given the index OID and column number,
    3465             :  *      return opclass of the index column
    3466             :  *          or InvalidOid if the index was not found
    3467             :  *              or column is non-key one.
    3468             :  */
    3469             : Oid
    3470          36 : get_index_column_opclass(Oid index_oid, int attno)
    3471             : {
    3472             :     HeapTuple   tuple;
    3473             :     Form_pg_index rd_index;
    3474             :     Datum       datum;
    3475             :     oidvector  *indclass;
    3476             :     Oid         opclass;
    3477             : 
    3478             :     /* First we need to know the column's opclass. */
    3479             : 
    3480          36 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3481          36 :     if (!HeapTupleIsValid(tuple))
    3482           0 :         return InvalidOid;
    3483             : 
    3484          36 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3485             : 
    3486             :     /* caller is supposed to guarantee this */
    3487             :     Assert(attno > 0 && attno <= rd_index->indnatts);
    3488             : 
    3489             :     /* Non-key attributes don't have an opclass */
    3490          36 :     if (attno > rd_index->indnkeyatts)
    3491             :     {
    3492           0 :         ReleaseSysCache(tuple);
    3493           0 :         return InvalidOid;
    3494             :     }
    3495             : 
    3496          36 :     datum = SysCacheGetAttrNotNull(INDEXRELID, tuple, Anum_pg_index_indclass);
    3497          36 :     indclass = ((oidvector *) DatumGetPointer(datum));
    3498             : 
    3499             :     Assert(attno <= indclass->dim1);
    3500          36 :     opclass = indclass->values[attno - 1];
    3501             : 
    3502          36 :     ReleaseSysCache(tuple);
    3503             : 
    3504          36 :     return opclass;
    3505             : }
    3506             : 
    3507             : /*
    3508             :  * get_index_isreplident
    3509             :  *
    3510             :  *      Given the index OID, return pg_index.indisreplident.
    3511             :  */
    3512             : bool
    3513         398 : get_index_isreplident(Oid index_oid)
    3514             : {
    3515             :     HeapTuple   tuple;
    3516             :     Form_pg_index rd_index;
    3517             :     bool        result;
    3518             : 
    3519         398 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3520         398 :     if (!HeapTupleIsValid(tuple))
    3521           0 :         return false;
    3522             : 
    3523         398 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3524         398 :     result = rd_index->indisreplident;
    3525         398 :     ReleaseSysCache(tuple);
    3526             : 
    3527         398 :     return result;
    3528             : }
    3529             : 
    3530             : /*
    3531             :  * get_index_isvalid
    3532             :  *
    3533             :  *      Given the index OID, return pg_index.indisvalid.
    3534             :  */
    3535             : bool
    3536        3660 : get_index_isvalid(Oid index_oid)
    3537             : {
    3538             :     bool        isvalid;
    3539             :     HeapTuple   tuple;
    3540             :     Form_pg_index rd_index;
    3541             : 
    3542        3660 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3543        3660 :     if (!HeapTupleIsValid(tuple))
    3544           0 :         elog(ERROR, "cache lookup failed for index %u", index_oid);
    3545             : 
    3546        3660 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3547        3660 :     isvalid = rd_index->indisvalid;
    3548        3660 :     ReleaseSysCache(tuple);
    3549             : 
    3550        3660 :     return isvalid;
    3551             : }
    3552             : 
    3553             : /*
    3554             :  * get_index_isclustered
    3555             :  *
    3556             :  *      Given the index OID, return pg_index.indisclustered.
    3557             :  */
    3558             : bool
    3559         692 : get_index_isclustered(Oid index_oid)
    3560             : {
    3561             :     bool        isclustered;
    3562             :     HeapTuple   tuple;
    3563             :     Form_pg_index rd_index;
    3564             : 
    3565         692 :     tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
    3566         692 :     if (!HeapTupleIsValid(tuple))
    3567           0 :         elog(ERROR, "cache lookup failed for index %u", index_oid);
    3568             : 
    3569         692 :     rd_index = (Form_pg_index) GETSTRUCT(tuple);
    3570         692 :     isclustered = rd_index->indisclustered;
    3571         692 :     ReleaseSysCache(tuple);
    3572             : 
    3573         692 :     return isclustered;
    3574             : }
    3575             : 
    3576             : /*
    3577             :  * get_publication_oid - given a publication name, look up the OID
    3578             :  *
    3579             :  * If missing_ok is false, throw an error if name not found.  If true, just
    3580             :  * return InvalidOid.
    3581             :  */
    3582             : Oid
    3583        2494 : get_publication_oid(const char *pubname, bool missing_ok)
    3584             : {
    3585             :     Oid         oid;
    3586             : 
    3587        2494 :     oid = GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
    3588             :                           CStringGetDatum(pubname));
    3589        2494 :     if (!OidIsValid(oid) && !missing_ok)
    3590           8 :         ereport(ERROR,
    3591             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3592             :                  errmsg("publication \"%s\" does not exist", pubname)));
    3593        2486 :     return oid;
    3594             : }
    3595             : 
    3596             : /*
    3597             :  * get_publication_name - given a publication Oid, look up the name
    3598             :  *
    3599             :  * If missing_ok is false, throw an error if name not found.  If true, just
    3600             :  * return NULL.
    3601             :  */
    3602             : char *
    3603         598 : get_publication_name(Oid pubid, bool missing_ok)
    3604             : {
    3605             :     HeapTuple   tup;
    3606             :     char       *pubname;
    3607             :     Form_pg_publication pubform;
    3608             : 
    3609         598 :     tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
    3610             : 
    3611         598 :     if (!HeapTupleIsValid(tup))
    3612             :     {
    3613          18 :         if (!missing_ok)
    3614           0 :             elog(ERROR, "cache lookup failed for publication %u", pubid);
    3615          18 :         return NULL;
    3616             :     }
    3617             : 
    3618         580 :     pubform = (Form_pg_publication) GETSTRUCT(tup);
    3619         580 :     pubname = pstrdup(NameStr(pubform->pubname));
    3620             : 
    3621         580 :     ReleaseSysCache(tup);
    3622             : 
    3623         580 :     return pubname;
    3624             : }
    3625             : 
    3626             : /*
    3627             :  * get_subscription_oid - given a subscription name, look up the OID
    3628             :  *
    3629             :  * If missing_ok is false, throw an error if name not found.  If true, just
    3630             :  * return InvalidOid.
    3631             :  */
    3632             : Oid
    3633          66 : get_subscription_oid(const char *subname, bool missing_ok)
    3634             : {
    3635             :     Oid         oid;
    3636             : 
    3637          66 :     oid = GetSysCacheOid2(SUBSCRIPTIONNAME, Anum_pg_subscription_oid,
    3638             :                           MyDatabaseId, CStringGetDatum(subname));
    3639          66 :     if (!OidIsValid(oid) && !missing_ok)
    3640           6 :         ereport(ERROR,
    3641             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3642             :                  errmsg("subscription \"%s\" does not exist", subname)));
    3643          60 :     return oid;
    3644             : }
    3645             : 
    3646             : /*
    3647             :  * get_subscription_name - given a subscription OID, look up the name
    3648             :  *
    3649             :  * If missing_ok is false, throw an error if name not found.  If true, just
    3650             :  * return NULL.
    3651             :  */
    3652             : char *
    3653          60 : get_subscription_name(Oid subid, bool missing_ok)
    3654             : {
    3655             :     HeapTuple   tup;
    3656             :     char       *subname;
    3657             :     Form_pg_subscription subform;
    3658             : 
    3659          60 :     tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
    3660             : 
    3661          60 :     if (!HeapTupleIsValid(tup))
    3662             :     {
    3663          18 :         if (!missing_ok)
    3664           0 :             elog(ERROR, "cache lookup failed for subscription %u", subid);
    3665          18 :         return NULL;
    3666             :     }
    3667             : 
    3668          42 :     subform = (Form_pg_subscription) GETSTRUCT(tup);
    3669          42 :     subname = pstrdup(NameStr(subform->subname));
    3670             : 
    3671          42 :     ReleaseSysCache(tup);
    3672             : 
    3673          42 :     return subname;
    3674             : }

Generated by: LCOV version 1.14