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

Generated by: LCOV version 1.14