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

Generated by: LCOV version 1.14