LCOV - differential code coverage report
Current view: top level - src/backend/parser - parse_oper.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 92.6 % 282 261 21 1 260 1
Current Date: 2023-04-08 15:15:32 Functions: 94.7 % 19 18 1 1 17
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a