LCOV - code coverage report
Current view: top level - src/backend/parser - parse_oper.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 93.7 % 395 370
Test Date: 2026-01-26 10:56:24 Functions: 95.0 % 20 19
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 65.1 % 252 164

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * parse_oper.c
       4                 :             :  *              handle operator things for parser
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *        src/backend/parser/parse_oper.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : 
      16                 :             : #include "postgres.h"
      17                 :             : 
      18                 :             : #include "access/htup_details.h"
      19                 :             : #include "catalog/pg_operator.h"
      20                 :             : #include "catalog/pg_type.h"
      21                 :             : #include "lib/stringinfo.h"
      22                 :             : #include "nodes/nodeFuncs.h"
      23                 :             : #include "parser/parse_coerce.h"
      24                 :             : #include "parser/parse_func.h"
      25                 :             : #include "parser/parse_oper.h"
      26                 :             : #include "parser/parse_type.h"
      27                 :             : #include "utils/builtins.h"
      28                 :             : #include "utils/inval.h"
      29                 :             : #include "utils/lsyscache.h"
      30                 :             : #include "utils/syscache.h"
      31                 :             : #include "utils/typcache.h"
      32                 :             : 
      33                 :             : 
      34                 :             : /*
      35                 :             :  * The lookup key for the operator lookaside hash table.  Unused bits must be
      36                 :             :  * zeroes to ensure hashing works consistently --- in particular, oprname
      37                 :             :  * must be zero-padded and any unused entries in search_path must be zero.
      38                 :             :  *
      39                 :             :  * search_path contains the actual search_path with which the entry was
      40                 :             :  * derived (minus temp namespace if any), or else the single specified
      41                 :             :  * schema OID if we are looking up an explicitly-qualified operator name.
      42                 :             :  *
      43                 :             :  * search_path has to be fixed-length since the hashtable code insists on
      44                 :             :  * fixed-size keys.  If your search path is longer than that, we just punt
      45                 :             :  * and don't cache anything.
      46                 :             :  */
      47                 :             : 
      48                 :             : /* If your search_path is longer than this, sucks to be you ... */
      49                 :             : #define MAX_CACHED_PATH_LEN             16
      50                 :             : 
      51                 :             : typedef struct OprCacheKey
      52                 :             : {
      53                 :             :         char            oprname[NAMEDATALEN];
      54                 :             :         Oid                     left_arg;               /* Left input OID, or 0 if prefix op */
      55                 :             :         Oid                     right_arg;              /* Right input OID */
      56                 :             :         Oid                     search_path[MAX_CACHED_PATH_LEN];
      57                 :             : } OprCacheKey;
      58                 :             : 
      59                 :             : typedef struct OprCacheEntry
      60                 :             : {
      61                 :             :         /* the hash lookup key MUST BE FIRST */
      62                 :             :         OprCacheKey key;
      63                 :             : 
      64                 :             :         Oid                     opr_oid;                /* OID of the resolved operator */
      65                 :             : } OprCacheEntry;
      66                 :             : 
      67                 :             : 
      68                 :             : static Oid      binary_oper_exact(List *opname, Oid arg1, Oid arg2);
      69                 :             : static FuncDetailCode oper_select_candidate(int nargs,
      70                 :             :                                                                                         Oid *input_typeids,
      71                 :             :                                                                                         FuncCandidateList candidates,
      72                 :             :                                                                                         Oid *operOid);
      73                 :             : static void op_error(ParseState *pstate, List *op,
      74                 :             :                                          Oid arg1, Oid arg2,
      75                 :             :                                          FuncDetailCode fdresult, int fgc_flags, int location);
      76                 :             : static int      oper_lookup_failure_details(int fgc_flags, bool is_unary_op);
      77                 :             : static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key,
      78                 :             :                                                                 List *opname, Oid ltypeId, Oid rtypeId,
      79                 :             :                                                                 int location);
      80                 :             : static Oid      find_oper_cache_entry(OprCacheKey *key);
      81                 :             : static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
      82                 :             : static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
      83                 :             : 
      84                 :             : 
      85                 :             : /*
      86                 :             :  * LookupOperName
      87                 :             :  *              Given a possibly-qualified operator name and exact input datatypes,
      88                 :             :  *              look up the operator.
      89                 :             :  *
      90                 :             :  * Pass oprleft = InvalidOid for a prefix op.
      91                 :             :  *
      92                 :             :  * If the operator name is not schema-qualified, it is sought in the current
      93                 :             :  * namespace search path.
      94                 :             :  *
      95                 :             :  * If the operator is not found, we return InvalidOid if noError is true,
      96                 :             :  * else raise an error.  pstate and location are used only to report the
      97                 :             :  * error position; pass NULL/-1 if not available.
      98                 :             :  */
      99                 :             : Oid
     100                 :         175 : LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
     101                 :             :                            bool noError, int location)
     102                 :             : {
     103                 :         175 :         Oid                     result;
     104                 :             : 
     105                 :         175 :         result = OpernameGetOprid(opername, oprleft, oprright);
     106         [ +  + ]:         175 :         if (OidIsValid(result))
     107                 :         146 :                 return result;
     108                 :             : 
     109                 :             :         /* we don't use op_error here because only an exact match is wanted */
     110         [ +  + ]:          29 :         if (!noError)
     111                 :             :         {
     112         [ +  + ]:           8 :                 if (!OidIsValid(oprright))
     113   [ +  -  +  - ]:           2 :                         ereport(ERROR,
     114                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     115                 :             :                                          errmsg("postfix operators are not supported"),
     116                 :             :                                          parser_errposition(pstate, location)));
     117                 :             : 
     118   [ +  -  +  - ]:           6 :                 ereport(ERROR,
     119                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     120                 :             :                                  errmsg("operator does not exist: %s",
     121                 :             :                                                 op_signature_string(opername, oprleft, oprright)),
     122                 :             :                                  parser_errposition(pstate, location)));
     123                 :           0 :         }
     124                 :             : 
     125                 :          21 :         return InvalidOid;
     126                 :         167 : }
     127                 :             : 
     128                 :             : /*
     129                 :             :  * LookupOperWithArgs
     130                 :             :  *              Like LookupOperName, but the argument types are specified by
     131                 :             :  *              a ObjectWithArgs node.
     132                 :             :  */
     133                 :             : Oid
     134                 :         127 : LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
     135                 :             : {
     136                 :         127 :         TypeName   *oprleft,
     137                 :             :                            *oprright;
     138                 :         127 :         Oid                     leftoid,
     139                 :             :                                 rightoid;
     140                 :             : 
     141         [ +  - ]:         127 :         Assert(list_length(oper->objargs) == 2);
     142                 :         127 :         oprleft = linitial_node(TypeName, oper->objargs);
     143                 :         127 :         oprright = lsecond_node(TypeName, oper->objargs);
     144                 :             : 
     145         [ +  + ]:         127 :         if (oprleft == NULL)
     146                 :           4 :                 leftoid = InvalidOid;
     147                 :             :         else
     148                 :         123 :                 leftoid = LookupTypeNameOid(NULL, oprleft, noError);
     149                 :             : 
     150         [ +  + ]:         127 :         if (oprright == NULL)
     151                 :           2 :                 rightoid = InvalidOid;
     152                 :             :         else
     153                 :         125 :                 rightoid = LookupTypeNameOid(NULL, oprright, noError);
     154                 :             : 
     155                 :         381 :         return LookupOperName(NULL, oper->objname, leftoid, rightoid,
     156                 :         127 :                                                   noError, -1);
     157                 :         127 : }
     158                 :             : 
     159                 :             : /*
     160                 :             :  * get_sort_group_operators - get default sorting/grouping operators for type
     161                 :             :  *
     162                 :             :  * We fetch the "<", "=", and ">" operators all at once to reduce lookup
     163                 :             :  * overhead (knowing that most callers will be interested in at least two).
     164                 :             :  * However, a given datatype might have only an "=" operator, if it is
     165                 :             :  * hashable but not sortable.  (Other combinations of present and missing
     166                 :             :  * operators shouldn't happen, unless the system catalogs are messed up.)
     167                 :             :  *
     168                 :             :  * If an operator is missing and the corresponding needXX flag is true,
     169                 :             :  * throw a standard error message, else return InvalidOid.
     170                 :             :  *
     171                 :             :  * In addition to the operator OIDs themselves, this function can identify
     172                 :             :  * whether the "=" operator is hashable.
     173                 :             :  *
     174                 :             :  * Callers can pass NULL pointers for any results they don't care to get.
     175                 :             :  *
     176                 :             :  * Note: the results are guaranteed to be exact or binary-compatible matches,
     177                 :             :  * since most callers are not prepared to cope with adding any run-time type
     178                 :             :  * coercion steps.
     179                 :             :  */
     180                 :             : void
     181                 :       20880 : get_sort_group_operators(Oid argtype,
     182                 :             :                                                  bool needLT, bool needEQ, bool needGT,
     183                 :             :                                                  Oid *ltOpr, Oid *eqOpr, Oid *gtOpr,
     184                 :             :                                                  bool *isHashable)
     185                 :             : {
     186                 :       20880 :         TypeCacheEntry *typentry;
     187                 :       20880 :         int                     cache_flags;
     188                 :       20880 :         Oid                     lt_opr;
     189                 :       20880 :         Oid                     eq_opr;
     190                 :       20880 :         Oid                     gt_opr;
     191                 :       20880 :         bool            hashable;
     192                 :             : 
     193                 :             :         /*
     194                 :             :          * Look up the operators using the type cache.
     195                 :             :          *
     196                 :             :          * Note: the search algorithm used by typcache.c ensures that the results
     197                 :             :          * are consistent, ie all from matching opclasses.
     198                 :             :          */
     199         [ +  + ]:       20880 :         if (isHashable != NULL)
     200                 :       17981 :                 cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR |
     201                 :             :                         TYPECACHE_HASH_PROC;
     202                 :             :         else
     203                 :        2899 :                 cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR;
     204                 :             : 
     205                 :       20880 :         typentry = lookup_type_cache(argtype, cache_flags);
     206                 :       20880 :         lt_opr = typentry->lt_opr;
     207                 :       20880 :         eq_opr = typentry->eq_opr;
     208                 :       20880 :         gt_opr = typentry->gt_opr;
     209                 :       20880 :         hashable = OidIsValid(typentry->hash_proc);
     210                 :             : 
     211                 :             :         /* Report errors if needed */
     212   [ +  +  +  + ]:       21389 :         if ((needLT && !OidIsValid(lt_opr)) ||
     213         [ +  + ]:       20879 :                 (needGT && !OidIsValid(gt_opr)))
     214   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     215                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     216                 :             :                                  errmsg("could not identify an ordering operator for type %s",
     217                 :             :                                                 format_type_be(argtype)),
     218                 :             :                                  errhint("Use an explicit ordering operator or modify the query.")));
     219   [ +  +  +  - ]:       20879 :         if (needEQ && !OidIsValid(eq_opr))
     220   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     221                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     222                 :             :                                  errmsg("could not identify an equality operator for type %s",
     223                 :             :                                                 format_type_be(argtype))));
     224                 :             : 
     225                 :             :         /* Return results as needed */
     226         [ +  + ]:       20879 :         if (ltOpr)
     227                 :       20370 :                 *ltOpr = lt_opr;
     228         [ -  + ]:       20879 :         if (eqOpr)
     229                 :       20879 :                 *eqOpr = eq_opr;
     230         [ +  + ]:       20879 :         if (gtOpr)
     231                 :         509 :                 *gtOpr = gt_opr;
     232         [ +  + ]:       20879 :         if (isHashable)
     233                 :       17980 :                 *isHashable = hashable;
     234                 :       20879 : }
     235                 :             : 
     236                 :             : 
     237                 :             : /* given operator tuple, return the operator OID */
     238                 :             : Oid
     239                 :       66247 : oprid(Operator op)
     240                 :             : {
     241                 :       66247 :         return ((Form_pg_operator) GETSTRUCT(op))->oid;
     242                 :             : }
     243                 :             : 
     244                 :             : /* given operator tuple, return the underlying function's OID */
     245                 :             : Oid
     246                 :           0 : oprfuncid(Operator op)
     247                 :             : {
     248                 :           0 :         Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(op);
     249                 :             : 
     250                 :           0 :         return pgopform->oprcode;
     251                 :           0 : }
     252                 :             : 
     253                 :             : 
     254                 :             : /* binary_oper_exact()
     255                 :             :  * Check for an "exact" match to the specified operand types.
     256                 :             :  *
     257                 :             :  * If one operand is an unknown literal, assume it should be taken to be
     258                 :             :  * the same type as the other operand for this purpose.  Also, consider
     259                 :             :  * the possibility that the other operand is a domain type that needs to
     260                 :             :  * be reduced to its base type to find an "exact" match.
     261                 :             :  */
     262                 :             : static Oid
     263                 :        6374 : binary_oper_exact(List *opname, Oid arg1, Oid arg2)
     264                 :             : {
     265                 :        6374 :         Oid                     result;
     266                 :        6374 :         bool            was_unknown = false;
     267                 :             : 
     268                 :             :         /* Unspecified type for one of the arguments? then use the other */
     269   [ +  +  -  + ]:        6374 :         if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
     270                 :             :         {
     271                 :         306 :                 arg1 = arg2;
     272                 :         306 :                 was_unknown = true;
     273                 :         306 :         }
     274   [ +  +  -  + ]:        6068 :         else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
     275                 :             :         {
     276                 :        1489 :                 arg2 = arg1;
     277                 :        1489 :                 was_unknown = true;
     278                 :        1489 :         }
     279                 :             : 
     280                 :        6374 :         result = OpernameGetOprid(opname, arg1, arg2);
     281         [ +  + ]:        6374 :         if (OidIsValid(result))
     282                 :        4823 :                 return result;
     283                 :             : 
     284         [ +  + ]:        1551 :         if (was_unknown)
     285                 :             :         {
     286                 :             :                 /* arg1 and arg2 are the same here, need only look at arg1 */
     287                 :         505 :                 Oid                     basetype = getBaseType(arg1);
     288                 :             : 
     289         [ +  + ]:         505 :                 if (basetype != arg1)
     290                 :             :                 {
     291                 :          24 :                         result = OpernameGetOprid(opname, basetype, basetype);
     292         [ +  + ]:          24 :                         if (OidIsValid(result))
     293                 :          11 :                                 return result;
     294                 :          13 :                 }
     295         [ +  + ]:         505 :         }
     296                 :             : 
     297                 :        1540 :         return InvalidOid;
     298                 :        6374 : }
     299                 :             : 
     300                 :             : 
     301                 :             : /* oper_select_candidate()
     302                 :             :  *              Given the input argtype array and one or more candidates
     303                 :             :  *              for the operator, attempt to resolve the conflict.
     304                 :             :  *
     305                 :             :  * Returns FUNCDETAIL_NOTFOUND, FUNCDETAIL_MULTIPLE, or FUNCDETAIL_NORMAL.
     306                 :             :  * In the success case the Oid of the best candidate is stored in *operOid.
     307                 :             :  *
     308                 :             :  * Note that the caller has already determined that there is no candidate
     309                 :             :  * exactly matching the input argtype(s).  Incompatible candidates are not yet
     310                 :             :  * pruned away, however.
     311                 :             :  */
     312                 :             : static FuncDetailCode
     313                 :        1545 : oper_select_candidate(int nargs,
     314                 :             :                                           Oid *input_typeids,
     315                 :             :                                           FuncCandidateList candidates,
     316                 :             :                                           Oid *operOid) /* output argument */
     317                 :             : {
     318                 :        1545 :         int                     ncandidates;
     319                 :             : 
     320                 :             :         /*
     321                 :             :          * Delete any candidates that cannot actually accept the given input
     322                 :             :          * types, whether directly or by coercion.
     323                 :             :          */
     324                 :        3090 :         ncandidates = func_match_argtypes(nargs, input_typeids,
     325                 :        1545 :                                                                           candidates, &candidates);
     326                 :             : 
     327                 :             :         /* Done if no candidate or only one candidate survives */
     328         [ +  + ]:        1545 :         if (ncandidates == 0)
     329                 :             :         {
     330                 :          18 :                 *operOid = InvalidOid;
     331                 :          18 :                 return FUNCDETAIL_NOTFOUND;
     332                 :             :         }
     333         [ +  + ]:        1527 :         if (ncandidates == 1)
     334                 :             :         {
     335                 :         935 :                 *operOid = candidates->oid;
     336                 :         935 :                 return FUNCDETAIL_NORMAL;
     337                 :             :         }
     338                 :             : 
     339                 :             :         /*
     340                 :             :          * Use the same heuristics as for ambiguous functions to resolve the
     341                 :             :          * conflict.
     342                 :             :          */
     343                 :         592 :         candidates = func_select_candidate(nargs, input_typeids, candidates);
     344                 :             : 
     345         [ +  + ]:         592 :         if (candidates)
     346                 :             :         {
     347                 :         591 :                 *operOid = candidates->oid;
     348                 :         591 :                 return FUNCDETAIL_NORMAL;
     349                 :             :         }
     350                 :             : 
     351                 :           1 :         *operOid = InvalidOid;
     352                 :           1 :         return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
     353                 :        1545 : }
     354                 :             : 
     355                 :             : 
     356                 :             : /* oper() -- search for a binary operator
     357                 :             :  * Given operator name, types of arg1 and arg2, return oper struct.
     358                 :             :  *
     359                 :             :  * IMPORTANT: the returned operator (if any) is only promised to be
     360                 :             :  * coercion-compatible with the input datatypes.  Do not use this if
     361                 :             :  * you need an exact- or binary-compatible match; see compatible_oper.
     362                 :             :  *
     363                 :             :  * If no matching operator found, return NULL if noError is true,
     364                 :             :  * raise an error if it is false.  pstate and location are used only to report
     365                 :             :  * the error position; pass NULL/-1 if not available.
     366                 :             :  *
     367                 :             :  * NOTE: on success, the returned object is a syscache entry.  The caller
     368                 :             :  * must ReleaseSysCache() the entry when done with it.
     369                 :             :  */
     370                 :             : Operator
     371                 :       66098 : oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
     372                 :             :          bool noError, int location)
     373                 :             : {
     374                 :       66098 :         Oid                     operOid;
     375                 :       66098 :         OprCacheKey key;
     376                 :       66098 :         bool            key_ok;
     377                 :       66098 :         int                     fgc_flags = 0;
     378                 :       66098 :         FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
     379                 :       66098 :         HeapTuple       tup = NULL;
     380                 :             : 
     381                 :             :         /*
     382                 :             :          * Try to find the mapping in the lookaside cache.
     383                 :             :          */
     384                 :       66098 :         key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
     385                 :             : 
     386         [ +  + ]:       66098 :         if (key_ok)
     387                 :             :         {
     388                 :       66080 :                 operOid = find_oper_cache_entry(&key);
     389         [ +  + ]:       66080 :                 if (OidIsValid(operOid))
     390                 :             :                 {
     391                 :       59706 :                         tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     392         [ +  - ]:       59706 :                         if (HeapTupleIsValid(tup))
     393                 :       59706 :                                 return (Operator) tup;
     394                 :           0 :                 }
     395                 :        6374 :         }
     396                 :             : 
     397                 :             :         /*
     398                 :             :          * First try for an "exact" match.
     399                 :             :          */
     400                 :        6392 :         operOid = binary_oper_exact(opname, ltypeId, rtypeId);
     401         [ +  + ]:        6392 :         if (!OidIsValid(operOid))
     402                 :             :         {
     403                 :             :                 /*
     404                 :             :                  * Otherwise, search for the most suitable candidate.
     405                 :             :                  */
     406                 :        1540 :                 FuncCandidateList clist;
     407                 :             : 
     408                 :             :                 /* Get binary operators of given name */
     409                 :        1540 :                 clist = OpernameGetCandidates(opname, 'b', false, &fgc_flags);
     410                 :             : 
     411                 :             :                 /* No operators found? Then fail... */
     412         [ -  + ]:        1540 :                 if (clist != NULL)
     413                 :             :                 {
     414                 :             :                         /*
     415                 :             :                          * Unspecified type for one of the arguments? then use the other
     416                 :             :                          * (XXX this is probably dead code?)
     417                 :             :                          */
     418                 :        1540 :                         Oid                     inputOids[2];
     419                 :             : 
     420         [ +  - ]:        1540 :                         if (rtypeId == InvalidOid)
     421                 :           0 :                                 rtypeId = ltypeId;
     422         [ +  - ]:        1540 :                         else if (ltypeId == InvalidOid)
     423                 :           0 :                                 ltypeId = rtypeId;
     424                 :        1540 :                         inputOids[0] = ltypeId;
     425                 :        1540 :                         inputOids[1] = rtypeId;
     426                 :        1540 :                         fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
     427                 :        1540 :                 }
     428                 :        1540 :         }
     429                 :             : 
     430         [ +  + ]:        6392 :         if (OidIsValid(operOid))
     431                 :        6356 :                 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     432                 :             : 
     433         [ +  + ]:        6392 :         if (HeapTupleIsValid(tup))
     434                 :             :         {
     435         [ -  + ]:        6356 :                 if (key_ok)
     436                 :        6356 :                         make_oper_cache_entry(&key, operOid);
     437                 :        6356 :         }
     438         [ +  + ]:          36 :         else if (!noError)
     439                 :          36 :                 op_error(pstate, opname, ltypeId, rtypeId,
     440                 :          18 :                                  fdresult, fgc_flags, location);
     441                 :             : 
     442                 :        6356 :         return (Operator) tup;
     443                 :       66062 : }
     444                 :             : 
     445                 :             : /* compatible_oper()
     446                 :             :  *      given an opname and input datatypes, find a compatible binary operator
     447                 :             :  *
     448                 :             :  *      This is tighter than oper() because it will not return an operator that
     449                 :             :  *      requires coercion of the input datatypes (but binary-compatible operators
     450                 :             :  *      are accepted).  Otherwise, the semantics are the same.
     451                 :             :  */
     452                 :             : Operator
     453                 :          84 : compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2,
     454                 :             :                                 bool noError, int location)
     455                 :             : {
     456                 :          84 :         Operator        optup;
     457                 :          84 :         Form_pg_operator opform;
     458                 :             : 
     459                 :             :         /* oper() will find the best available match */
     460                 :          84 :         optup = oper(pstate, op, arg1, arg2, noError, location);
     461         [ +  - ]:          84 :         if (optup == (Operator) NULL)
     462                 :           0 :                 return (Operator) NULL; /* must be noError case */
     463                 :             : 
     464                 :             :         /* but is it good enough? */
     465                 :          84 :         opform = (Form_pg_operator) GETSTRUCT(optup);
     466   [ +  -  -  + ]:          84 :         if (IsBinaryCoercible(arg1, opform->oprleft) &&
     467                 :          84 :                 IsBinaryCoercible(arg2, opform->oprright))
     468                 :          84 :                 return optup;
     469                 :             : 
     470                 :             :         /* nope... */
     471                 :           0 :         ReleaseSysCache(optup);
     472                 :             : 
     473         [ #  # ]:           0 :         if (!noError)
     474   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     475                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     476                 :             :                                  errmsg("operator requires run-time type coercion: %s",
     477                 :             :                                                 op_signature_string(op, arg1, arg2)),
     478                 :             :                                  parser_errposition(pstate, location)));
     479                 :             : 
     480                 :           0 :         return (Operator) NULL;
     481                 :          84 : }
     482                 :             : 
     483                 :             : /* compatible_oper_opid() -- get OID of a binary operator
     484                 :             :  *
     485                 :             :  * This is a convenience routine that extracts only the operator OID
     486                 :             :  * from the result of compatible_oper().  InvalidOid is returned if the
     487                 :             :  * lookup fails and noError is true.
     488                 :             :  */
     489                 :             : Oid
     490                 :          84 : compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
     491                 :             : {
     492                 :          84 :         Operator        optup;
     493                 :          84 :         Oid                     result;
     494                 :             : 
     495                 :          84 :         optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
     496         [ +  - ]:          84 :         if (optup != NULL)
     497                 :             :         {
     498                 :          84 :                 result = oprid(optup);
     499                 :          84 :                 ReleaseSysCache(optup);
     500                 :          84 :                 return result;
     501                 :             :         }
     502                 :           0 :         return InvalidOid;
     503                 :          84 : }
     504                 :             : 
     505                 :             : 
     506                 :             : /* left_oper() -- search for a unary left operator (prefix operator)
     507                 :             :  * Given operator name and type of arg, return oper struct.
     508                 :             :  *
     509                 :             :  * IMPORTANT: the returned operator (if any) is only promised to be
     510                 :             :  * coercion-compatible with the input datatype.  Do not use this if
     511                 :             :  * you need an exact- or binary-compatible match.
     512                 :             :  *
     513                 :             :  * If no matching operator found, return NULL if noError is true,
     514                 :             :  * raise an error if it is false.  pstate and location are used only to report
     515                 :             :  * the error position; pass NULL/-1 if not available.
     516                 :             :  *
     517                 :             :  * NOTE: on success, the returned object is a syscache entry.  The caller
     518                 :             :  * must ReleaseSysCache() the entry when done with it.
     519                 :             :  */
     520                 :             : Operator
     521                 :         193 : left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
     522                 :             : {
     523                 :         193 :         Oid                     operOid;
     524                 :         193 :         OprCacheKey key;
     525                 :         193 :         bool            key_ok;
     526                 :         193 :         int                     fgc_flags = 0;
     527                 :         193 :         FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
     528                 :         193 :         HeapTuple       tup = NULL;
     529                 :             : 
     530                 :             :         /*
     531                 :             :          * Try to find the mapping in the lookaside cache.
     532                 :             :          */
     533                 :         193 :         key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
     534                 :             : 
     535         [ +  + ]:         193 :         if (key_ok)
     536                 :             :         {
     537                 :         190 :                 operOid = find_oper_cache_entry(&key);
     538         [ +  + ]:         190 :                 if (OidIsValid(operOid))
     539                 :             :                 {
     540                 :         117 :                         tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     541         [ +  - ]:         117 :                         if (HeapTupleIsValid(tup))
     542                 :         117 :                                 return (Operator) tup;
     543                 :           0 :                 }
     544                 :          73 :         }
     545                 :             : 
     546                 :             :         /*
     547                 :             :          * First try for an "exact" match.
     548                 :             :          */
     549                 :          76 :         operOid = OpernameGetOprid(op, InvalidOid, arg);
     550         [ +  + ]:          76 :         if (!OidIsValid(operOid))
     551                 :             :         {
     552                 :             :                 /*
     553                 :             :                  * Otherwise, search for the most suitable candidate.
     554                 :             :                  */
     555                 :           7 :                 FuncCandidateList clist;
     556                 :             : 
     557                 :             :                 /* Get prefix operators of given name */
     558                 :           7 :                 clist = OpernameGetCandidates(op, 'l', false, &fgc_flags);
     559                 :             : 
     560                 :             :                 /* No operators found? Then fail... */
     561         [ +  + ]:           7 :                 if (clist != NULL)
     562                 :             :                 {
     563                 :             :                         /*
     564                 :             :                          * The returned list has args in the form (0, oprright). Move the
     565                 :             :                          * useful data into args[0] to keep oper_select_candidate simple.
     566                 :             :                          * XXX we are assuming here that we may scribble on the list!
     567                 :             :                          */
     568                 :           5 :                         FuncCandidateList clisti;
     569                 :             : 
     570         [ +  + ]:          16 :                         for (clisti = clist; clisti != NULL; clisti = clisti->next)
     571                 :             :                         {
     572                 :          11 :                                 clisti->args[0] = clisti->args[1];
     573                 :          11 :                         }
     574                 :             : 
     575                 :             :                         /*
     576                 :             :                          * We must run oper_select_candidate even if only one candidate,
     577                 :             :                          * otherwise we may falsely return a non-type-compatible operator.
     578                 :             :                          */
     579                 :           5 :                         fdresult = oper_select_candidate(1, &arg, clist, &operOid);
     580                 :           5 :                 }
     581                 :           7 :         }
     582                 :             : 
     583         [ +  + ]:          76 :         if (OidIsValid(operOid))
     584                 :          70 :                 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     585                 :             : 
     586         [ +  + ]:          76 :         if (HeapTupleIsValid(tup))
     587                 :             :         {
     588         [ -  + ]:          70 :                 if (key_ok)
     589                 :          70 :                         make_oper_cache_entry(&key, operOid);
     590                 :          70 :         }
     591         [ +  + ]:           6 :         else if (!noError)
     592                 :           6 :                 op_error(pstate, op, InvalidOid, arg,
     593                 :           3 :                                  fdresult, fgc_flags, location);
     594                 :             : 
     595                 :          70 :         return (Operator) tup;
     596                 :         187 : }
     597                 :             : 
     598                 :             : /*
     599                 :             :  * op_signature_string
     600                 :             :  *              Build a string representing an operator name, including arg type(s).
     601                 :             :  *              The result is something like "integer + integer".
     602                 :             :  *
     603                 :             :  * This is typically used in the construction of operator-not-found error
     604                 :             :  * messages.
     605                 :             :  */
     606                 :             : const char *
     607                 :          27 : op_signature_string(List *op, Oid arg1, Oid arg2)
     608                 :             : {
     609                 :          27 :         StringInfoData argbuf;
     610                 :             : 
     611                 :          27 :         initStringInfo(&argbuf);
     612                 :             : 
     613         [ +  + ]:          27 :         if (OidIsValid(arg1))
     614                 :          22 :                 appendStringInfo(&argbuf, "%s ", format_type_be(arg1));
     615                 :             : 
     616                 :          27 :         appendStringInfoString(&argbuf, NameListToString(op));
     617                 :             : 
     618                 :          27 :         appendStringInfo(&argbuf, " %s", format_type_be(arg2));
     619                 :             : 
     620                 :          54 :         return argbuf.data;                     /* return palloc'd string buffer */
     621                 :          27 : }
     622                 :             : 
     623                 :             : /*
     624                 :             :  * op_error - utility routine to complain about an unresolvable operator
     625                 :             :  */
     626                 :             : static void
     627                 :          21 : op_error(ParseState *pstate, List *op,
     628                 :             :                  Oid arg1, Oid arg2,
     629                 :             :                  FuncDetailCode fdresult, int fgc_flags, int location)
     630                 :             : {
     631         [ +  + ]:          21 :         if (fdresult == FUNCDETAIL_MULTIPLE)
     632   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     633                 :             :                                 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
     634                 :             :                                  errmsg("operator is not unique: %s",
     635                 :             :                                                 op_signature_string(op, arg1, arg2)),
     636                 :             :                                  errdetail("Could not choose a best candidate operator."),
     637                 :             :                                  errhint("You might need to add explicit type casts."),
     638                 :             :                                  parser_errposition(pstate, location)));
     639                 :             :         else
     640   [ +  -  +  -  :          20 :                 ereport(ERROR,
                   +  + ]
     641                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     642                 :             :                                  errmsg("operator does not exist: %s",
     643                 :             :                                                 op_signature_string(op, arg1, arg2)),
     644                 :             :                                  oper_lookup_failure_details(fgc_flags, (!arg1 || !arg2)),
     645                 :             :                                  parser_errposition(pstate, location)));
     646                 :           0 : }
     647                 :             : 
     648                 :             : /*
     649                 :             :  * Interpret the fgc_flags and issue a suitable detail or hint message.
     650                 :             :  */
     651                 :             : static int
     652                 :          20 : oper_lookup_failure_details(int fgc_flags, bool is_unary_op)
     653                 :             : {
     654                 :             :         /*
     655                 :             :          * If not FGC_NAME_VISIBLE, we shouldn't raise the question of whether the
     656                 :             :          * arguments are wrong.  If the operator name was not schema-qualified,
     657                 :             :          * it's helpful to distinguish between doesn't-exist-anywhere and
     658                 :             :          * not-in-search-path; but if it was, there's really nothing to add to the
     659                 :             :          * basic "operator does not exist" message.
     660                 :             :          *
     661                 :             :          * Note: we passed missing_ok = false to OpernameGetCandidates, so there's
     662                 :             :          * no need to consider FGC_SCHEMA_EXISTS here: we'd have already thrown an
     663                 :             :          * error if an explicitly-given schema doesn't exist.
     664                 :             :          */
     665         [ +  + ]:          20 :         if (!(fgc_flags & FGC_NAME_VISIBLE))
     666                 :             :         {
     667         [ -  + ]:           2 :                 if (fgc_flags & FGC_SCHEMA_GIVEN)
     668                 :           0 :                         return 0;                       /* schema-qualified name */
     669         [ +  + ]:           2 :                 else if (!(fgc_flags & FGC_NAME_EXISTS))
     670                 :           1 :                         return errdetail("There is no operator of that name.");
     671                 :             :                 else
     672                 :           1 :                         return errdetail("An operator of that name exists, but it is not in the search_path.");
     673                 :             :         }
     674                 :             : 
     675                 :             :         /*
     676                 :             :          * Otherwise, the problem must be incorrect argument type(s).
     677                 :             :          */
     678         [ +  + ]:          18 :         if (is_unary_op)
     679                 :             :         {
     680                 :           1 :                 (void) errdetail("No operator of that name accepts the given argument type.");
     681                 :           1 :                 return errhint("You might need to add an explicit type cast.");
     682                 :             :         }
     683                 :             :         else
     684                 :             :         {
     685                 :          17 :                 (void) errdetail("No operator of that name accepts the given argument types.");
     686                 :          17 :                 return errhint("You might need to add explicit type casts.");
     687                 :             :         }
     688                 :          20 : }
     689                 :             : 
     690                 :             : /*
     691                 :             :  * make_op()
     692                 :             :  *              Operator expression construction.
     693                 :             :  *
     694                 :             :  * Transform operator expression ensuring type compatibility.
     695                 :             :  * This is where some type conversion happens.
     696                 :             :  *
     697                 :             :  * last_srf should be a copy of pstate->p_last_srf from just before we
     698                 :             :  * started transforming the operator's arguments; this is used for nested-SRF
     699                 :             :  * detection.  If the caller will throw an error anyway for a set-returning
     700                 :             :  * expression, it's okay to cheat and just pass pstate->p_last_srf.
     701                 :             :  */
     702                 :             : Expr *
     703                 :       53637 : make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
     704                 :             :                 Node *last_srf, int location)
     705                 :             : {
     706                 :       53637 :         Oid                     ltypeId,
     707                 :             :                                 rtypeId;
     708                 :       53637 :         Operator        tup;
     709                 :       53637 :         Form_pg_operator opform;
     710                 :       53637 :         Oid                     actual_arg_types[2];
     711                 :       53637 :         Oid                     declared_arg_types[2];
     712                 :       53637 :         int                     nargs;
     713                 :       53637 :         List       *args;
     714                 :       53637 :         Oid                     rettype;
     715                 :       53637 :         OpExpr     *result;
     716                 :             : 
     717                 :             :         /* Check it's not a postfix operator */
     718         [ +  - ]:       53637 :         if (rtree == NULL)
     719   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     720                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     721                 :             :                                  errmsg("postfix operators are not supported")));
     722                 :             : 
     723                 :             :         /* Select the operator */
     724         [ +  + ]:       53637 :         if (ltree == NULL)
     725                 :             :         {
     726                 :             :                 /* prefix operator */
     727                 :         185 :                 rtypeId = exprType(rtree);
     728                 :         185 :                 ltypeId = InvalidOid;
     729                 :         185 :                 tup = left_oper(pstate, opname, rtypeId, false, location);
     730                 :         185 :         }
     731                 :             :         else
     732                 :             :         {
     733                 :             :                 /* otherwise, binary operator */
     734                 :       53452 :                 ltypeId = exprType(ltree);
     735                 :       53452 :                 rtypeId = exprType(rtree);
     736                 :       53452 :                 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
     737                 :             :         }
     738                 :             : 
     739                 :       53637 :         opform = (Form_pg_operator) GETSTRUCT(tup);
     740                 :             : 
     741                 :             :         /* Check it's not a shell */
     742         [ +  - ]:       53637 :         if (!RegProcedureIsValid(opform->oprcode))
     743   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     744                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     745                 :             :                                  errmsg("operator is only a shell: %s",
     746                 :             :                                                 op_signature_string(opname,
     747                 :             :                                                                                         opform->oprleft,
     748                 :             :                                                                                         opform->oprright)),
     749                 :             :                                  parser_errposition(pstate, location)));
     750                 :             : 
     751                 :             :         /* Do typecasting and build the expression tree */
     752         [ +  + ]:       53637 :         if (ltree == NULL)
     753                 :             :         {
     754                 :             :                 /* prefix operator */
     755                 :         182 :                 args = list_make1(rtree);
     756                 :         182 :                 actual_arg_types[0] = rtypeId;
     757                 :         182 :                 declared_arg_types[0] = opform->oprright;
     758                 :         182 :                 nargs = 1;
     759                 :         182 :         }
     760                 :             :         else
     761                 :             :         {
     762                 :             :                 /* otherwise, binary operator */
     763                 :       53455 :                 args = list_make2(ltree, rtree);
     764                 :       53455 :                 actual_arg_types[0] = ltypeId;
     765                 :       53455 :                 actual_arg_types[1] = rtypeId;
     766                 :       53455 :                 declared_arg_types[0] = opform->oprleft;
     767                 :       53455 :                 declared_arg_types[1] = opform->oprright;
     768                 :       53455 :                 nargs = 2;
     769                 :             :         }
     770                 :             : 
     771                 :             :         /*
     772                 :             :          * enforce consistency with polymorphic argument and return types,
     773                 :             :          * possibly adjusting return type or declared_arg_types (which will be
     774                 :             :          * used as the cast destination by make_fn_arguments)
     775                 :             :          */
     776                 :      107274 :         rettype = enforce_generic_type_consistency(actual_arg_types,
     777                 :       53637 :                                                                                            declared_arg_types,
     778                 :       53637 :                                                                                            nargs,
     779                 :       53637 :                                                                                            opform->oprresult,
     780                 :             :                                                                                            false);
     781                 :             : 
     782                 :             :         /* perform the necessary typecasting of arguments */
     783                 :       53637 :         make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
     784                 :             : 
     785                 :             :         /* and build the expression node */
     786                 :       53637 :         result = makeNode(OpExpr);
     787                 :       53637 :         result->opno = oprid(tup);
     788                 :       53637 :         result->opfuncid = opform->oprcode;
     789                 :       53637 :         result->opresulttype = rettype;
     790                 :       53637 :         result->opretset = get_func_retset(opform->oprcode);
     791                 :             :         /* opcollid and inputcollid will be set by parse_collate.c */
     792                 :       53637 :         result->args = args;
     793                 :       53637 :         result->location = location;
     794                 :             : 
     795                 :             :         /* if it returns a set, check that's OK */
     796         [ +  + ]:       53637 :         if (result->opretset)
     797                 :             :         {
     798                 :           1 :                 check_srf_call_placement(pstate, last_srf, location);
     799                 :             :                 /* ... and remember it for error checks at higher levels */
     800                 :           1 :                 pstate->p_last_srf = (Node *) result;
     801                 :           1 :         }
     802                 :             : 
     803                 :       53637 :         ReleaseSysCache(tup);
     804                 :             : 
     805                 :      107274 :         return (Expr *) result;
     806                 :       53637 : }
     807                 :             : 
     808                 :             : /*
     809                 :             :  * make_scalar_array_op()
     810                 :             :  *              Build expression tree for "scalar op ANY/ALL (array)" construct.
     811                 :             :  */
     812                 :             : Expr *
     813                 :        3278 : make_scalar_array_op(ParseState *pstate, List *opname,
     814                 :             :                                          bool useOr,
     815                 :             :                                          Node *ltree, Node *rtree,
     816                 :             :                                          int location)
     817                 :             : {
     818                 :        3278 :         Oid                     ltypeId,
     819                 :             :                                 rtypeId,
     820                 :             :                                 atypeId,
     821                 :             :                                 res_atypeId;
     822                 :        3278 :         Operator        tup;
     823                 :        3278 :         Form_pg_operator opform;
     824                 :        3278 :         Oid                     actual_arg_types[2];
     825                 :        3278 :         Oid                     declared_arg_types[2];
     826                 :        3278 :         List       *args;
     827                 :        3278 :         Oid                     rettype;
     828                 :        3278 :         ScalarArrayOpExpr *result;
     829                 :             : 
     830                 :        3278 :         ltypeId = exprType(ltree);
     831                 :        3278 :         atypeId = exprType(rtree);
     832                 :             : 
     833                 :             :         /*
     834                 :             :          * The right-hand input of the operator will be the element type of the
     835                 :             :          * array.  However, if we currently have just an untyped literal on the
     836                 :             :          * right, stay with that and hope we can resolve the operator.
     837                 :             :          */
     838         [ +  + ]:        3278 :         if (atypeId == UNKNOWNOID)
     839                 :          37 :                 rtypeId = UNKNOWNOID;
     840                 :             :         else
     841                 :             :         {
     842                 :        3241 :                 rtypeId = get_base_element_type(atypeId);
     843         [ +  + ]:        3241 :                 if (!OidIsValid(rtypeId))
     844   [ +  -  +  - ]:           1 :                         ereport(ERROR,
     845                 :             :                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
     846                 :             :                                          errmsg("op ANY/ALL (array) requires array on right side"),
     847                 :             :                                          parser_errposition(pstate, location)));
     848                 :             :         }
     849                 :             : 
     850                 :             :         /* Now resolve the operator */
     851                 :        3277 :         tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
     852                 :        3277 :         opform = (Form_pg_operator) GETSTRUCT(tup);
     853                 :             : 
     854                 :             :         /* Check it's not a shell */
     855         [ +  - ]:        3277 :         if (!RegProcedureIsValid(opform->oprcode))
     856   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     857                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
     858                 :             :                                  errmsg("operator is only a shell: %s",
     859                 :             :                                                 op_signature_string(opname,
     860                 :             :                                                                                         opform->oprleft,
     861                 :             :                                                                                         opform->oprright)),
     862                 :             :                                  parser_errposition(pstate, location)));
     863                 :             : 
     864                 :        3277 :         args = list_make2(ltree, rtree);
     865                 :        3277 :         actual_arg_types[0] = ltypeId;
     866                 :        3277 :         actual_arg_types[1] = rtypeId;
     867                 :        3277 :         declared_arg_types[0] = opform->oprleft;
     868                 :        3277 :         declared_arg_types[1] = opform->oprright;
     869                 :             : 
     870                 :             :         /*
     871                 :             :          * enforce consistency with polymorphic argument and return types,
     872                 :             :          * possibly adjusting return type or declared_arg_types (which will be
     873                 :             :          * used as the cast destination by make_fn_arguments)
     874                 :             :          */
     875                 :        6554 :         rettype = enforce_generic_type_consistency(actual_arg_types,
     876                 :        3277 :                                                                                            declared_arg_types,
     877                 :             :                                                                                            2,
     878                 :        3277 :                                                                                            opform->oprresult,
     879                 :             :                                                                                            false);
     880                 :             : 
     881                 :             :         /*
     882                 :             :          * Check that operator result is boolean
     883                 :             :          */
     884         [ +  + ]:        3277 :         if (rettype != BOOLOID)
     885   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     886                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
     887                 :             :                                  errmsg("op ANY/ALL (array) requires operator to yield boolean"),
     888                 :             :                                  parser_errposition(pstate, location)));
     889         [ +  - ]:        3276 :         if (get_func_retset(opform->oprcode))
     890   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     891                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
     892                 :             :                                  errmsg("op ANY/ALL (array) requires operator not to return a set"),
     893                 :             :                                  parser_errposition(pstate, location)));
     894                 :             : 
     895                 :             :         /*
     896                 :             :          * Now switch back to the array type on the right, arranging for any
     897                 :             :          * needed cast to be applied.  Beware of polymorphic operators here;
     898                 :             :          * enforce_generic_type_consistency may or may not have replaced a
     899                 :             :          * polymorphic type with a real one.
     900                 :             :          */
     901   [ +  -  +  -  :        3276 :         if (IsPolymorphicType(declared_arg_types[1]))
          +  -  +  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  -  + ]
     902                 :             :         {
     903                 :             :                 /* assume the actual array type is OK */
     904                 :           6 :                 res_atypeId = atypeId;
     905                 :           6 :         }
     906                 :             :         else
     907                 :             :         {
     908                 :        3270 :                 res_atypeId = get_array_type(declared_arg_types[1]);
     909         [ +  - ]:        3270 :                 if (!OidIsValid(res_atypeId))
     910   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     911                 :             :                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
     912                 :             :                                          errmsg("could not find array type for data type %s",
     913                 :             :                                                         format_type_be(declared_arg_types[1])),
     914                 :             :                                          parser_errposition(pstate, location)));
     915                 :             :         }
     916                 :        3276 :         actual_arg_types[1] = atypeId;
     917                 :        3276 :         declared_arg_types[1] = res_atypeId;
     918                 :             : 
     919                 :             :         /* perform the necessary typecasting of arguments */
     920                 :        3276 :         make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
     921                 :             : 
     922                 :             :         /* and build the expression node */
     923                 :        3276 :         result = makeNode(ScalarArrayOpExpr);
     924                 :        3276 :         result->opno = oprid(tup);
     925                 :        3276 :         result->opfuncid = opform->oprcode;
     926                 :        3276 :         result->hashfuncid = InvalidOid;
     927                 :        3276 :         result->negfuncid = InvalidOid;
     928                 :        3276 :         result->useOr = useOr;
     929                 :             :         /* inputcollid will be set by parse_collate.c */
     930                 :        3276 :         result->args = args;
     931                 :        3276 :         result->location = location;
     932                 :             : 
     933                 :        3276 :         ReleaseSysCache(tup);
     934                 :             : 
     935                 :        6552 :         return (Expr *) result;
     936                 :        3276 : }
     937                 :             : 
     938                 :             : 
     939                 :             : /*
     940                 :             :  * Lookaside cache to speed operator lookup.  Possibly this should be in
     941                 :             :  * a separate module under utils/cache/ ?
     942                 :             :  *
     943                 :             :  * The idea here is that the mapping from operator name and given argument
     944                 :             :  * types is constant for a given search path (or single specified schema OID)
     945                 :             :  * so long as the contents of pg_operator and pg_cast don't change.  And that
     946                 :             :  * mapping is pretty expensive to compute, especially for ambiguous operators;
     947                 :             :  * this is mainly because there are a *lot* of instances of popular operator
     948                 :             :  * names such as "=", and we have to check each one to see which is the
     949                 :             :  * best match.  So once we have identified the correct mapping, we save it
     950                 :             :  * in a cache that need only be flushed on pg_operator or pg_cast change.
     951                 :             :  * (pg_cast must be considered because changes in the set of implicit casts
     952                 :             :  * affect the set of applicable operators for any given input datatype.)
     953                 :             :  *
     954                 :             :  * XXX in principle, ALTER TABLE ... INHERIT could affect the mapping as
     955                 :             :  * well, but we disregard that since there's no convenient way to find out
     956                 :             :  * about it, and it seems a pretty far-fetched corner-case anyway.
     957                 :             :  *
     958                 :             :  * Note: at some point it might be worth doing a similar cache for function
     959                 :             :  * lookups.  However, the potential gain is a lot less since (a) function
     960                 :             :  * names are generally not overloaded as heavily as operator names, and
     961                 :             :  * (b) we'd have to flush on pg_proc updates, which are probably a good
     962                 :             :  * deal more common than pg_operator updates.
     963                 :             :  */
     964                 :             : 
     965                 :             : /* The operator cache hashtable */
     966                 :             : static HTAB *OprCacheHash = NULL;
     967                 :             : 
     968                 :             : 
     969                 :             : /*
     970                 :             :  * make_oper_cache_key
     971                 :             :  *              Fill the lookup key struct given operator name and arg types.
     972                 :             :  *
     973                 :             :  * Returns true if successful, false if the search_path overflowed
     974                 :             :  * (hence no caching is possible).
     975                 :             :  *
     976                 :             :  * pstate/location are used only to report the error position; pass NULL/-1
     977                 :             :  * if not available.
     978                 :             :  */
     979                 :             : static bool
     980                 :       66270 : make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname,
     981                 :             :                                         Oid ltypeId, Oid rtypeId, int location)
     982                 :             : {
     983                 :       66270 :         char       *schemaname;
     984                 :       66270 :         char       *opername;
     985                 :             : 
     986                 :             :         /* deconstruct the name list */
     987                 :       66270 :         DeconstructQualifiedName(opname, &schemaname, &opername);
     988                 :             : 
     989                 :             :         /* ensure zero-fill for stable hashing */
     990   [ +  -  +  -  :     1192860 :         MemSet(key, 0, sizeof(OprCacheKey));
          +  -  -  +  +  
                      + ]
     991                 :             : 
     992                 :             :         /* save operator name and input types into key */
     993                 :       66270 :         strlcpy(key->oprname, opername, NAMEDATALEN);
     994                 :       66270 :         key->left_arg = ltypeId;
     995                 :       66270 :         key->right_arg = rtypeId;
     996                 :             : 
     997         [ +  + ]:       66270 :         if (schemaname)
     998                 :             :         {
     999                 :        2029 :                 ParseCallbackState pcbstate;
    1000                 :             : 
    1001                 :             :                 /* search only in exact schema given */
    1002                 :        2029 :                 setup_parser_errposition_callback(&pcbstate, pstate, location);
    1003                 :        2029 :                 key->search_path[0] = LookupExplicitNamespace(schemaname, false);
    1004                 :        2029 :                 cancel_parser_errposition_callback(&pcbstate);
    1005                 :        2029 :         }
    1006                 :             :         else
    1007                 :             :         {
    1008                 :             :                 /* get the active search path */
    1009                 :       64241 :                 if (fetch_search_path_array(key->search_path,
    1010         [ -  + ]:       64241 :                                                                         MAX_CACHED_PATH_LEN) > MAX_CACHED_PATH_LEN)
    1011                 :           0 :                         return false;           /* oops, didn't fit */
    1012                 :             :         }
    1013                 :             : 
    1014                 :       66270 :         return true;
    1015                 :       66270 : }
    1016                 :             : 
    1017                 :             : /*
    1018                 :             :  * find_oper_cache_entry
    1019                 :             :  *
    1020                 :             :  * Look for a cache entry matching the given key.  If found, return the
    1021                 :             :  * contained operator OID, else return InvalidOid.
    1022                 :             :  */
    1023                 :             : static Oid
    1024                 :       66270 : find_oper_cache_entry(OprCacheKey *key)
    1025                 :             : {
    1026                 :       66270 :         OprCacheEntry *oprentry;
    1027                 :             : 
    1028         [ +  + ]:       66270 :         if (OprCacheHash == NULL)
    1029                 :             :         {
    1030                 :             :                 /* First time through: initialize the hash table */
    1031                 :         271 :                 HASHCTL         ctl;
    1032                 :             : 
    1033                 :         271 :                 ctl.keysize = sizeof(OprCacheKey);
    1034                 :         271 :                 ctl.entrysize = sizeof(OprCacheEntry);
    1035                 :         271 :                 OprCacheHash = hash_create("Operator lookup cache", 256,
    1036                 :             :                                                                    &ctl, HASH_ELEM | HASH_BLOBS);
    1037                 :             : 
    1038                 :             :                 /* Arrange to flush cache on pg_operator and pg_cast changes */
    1039                 :         271 :                 CacheRegisterSyscacheCallback(OPERNAMENSP,
    1040                 :             :                                                                           InvalidateOprCacheCallBack,
    1041                 :             :                                                                           (Datum) 0);
    1042                 :         271 :                 CacheRegisterSyscacheCallback(CASTSOURCETARGET,
    1043                 :             :                                                                           InvalidateOprCacheCallBack,
    1044                 :             :                                                                           (Datum) 0);
    1045                 :         271 :         }
    1046                 :             : 
    1047                 :             :         /* Look for an existing entry */
    1048                 :      132540 :         oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
    1049                 :       66270 :                                                                                          key,
    1050                 :             :                                                                                          HASH_FIND, NULL);
    1051         [ +  + ]:       66270 :         if (oprentry == NULL)
    1052                 :        6447 :                 return InvalidOid;
    1053                 :             : 
    1054                 :       59823 :         return oprentry->opr_oid;
    1055                 :       66270 : }
    1056                 :             : 
    1057                 :             : /*
    1058                 :             :  * make_oper_cache_entry
    1059                 :             :  *
    1060                 :             :  * Insert a cache entry for the given key.
    1061                 :             :  */
    1062                 :             : static void
    1063                 :        6426 : make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
    1064                 :             : {
    1065                 :        6426 :         OprCacheEntry *oprentry;
    1066                 :             : 
    1067         [ +  - ]:        6426 :         Assert(OprCacheHash != NULL);
    1068                 :             : 
    1069                 :       12852 :         oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
    1070                 :        6426 :                                                                                          key,
    1071                 :             :                                                                                          HASH_ENTER, NULL);
    1072                 :        6426 :         oprentry->opr_oid = opr_oid;
    1073                 :        6426 : }
    1074                 :             : 
    1075                 :             : /*
    1076                 :             :  * Callback for pg_operator and pg_cast inval events
    1077                 :             :  */
    1078                 :             : static void
    1079                 :        1518 : InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
    1080                 :             : {
    1081                 :        1518 :         HASH_SEQ_STATUS status;
    1082                 :        1518 :         OprCacheEntry *hentry;
    1083                 :             : 
    1084         [ +  - ]:        1518 :         Assert(OprCacheHash != NULL);
    1085                 :             : 
    1086                 :             :         /* Currently we just flush all entries; hard to be smarter ... */
    1087                 :        1518 :         hash_seq_init(&status, OprCacheHash);
    1088                 :             : 
    1089         [ +  + ]:        4454 :         while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
    1090                 :             :         {
    1091                 :        5872 :                 if (hash_search(OprCacheHash,
    1092                 :        2936 :                                                 &hentry->key,
    1093         [ +  - ]:        2936 :                                                 HASH_REMOVE, NULL) == NULL)
    1094   [ #  #  #  # ]:           0 :                         elog(ERROR, "hash table corrupted");
    1095                 :             :         }
    1096                 :        1518 : }
        

Generated by: LCOV version 2.3.2-1