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

Generated by: LCOV version 1.11