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

Generated by: LCOV version 1.14