LCOV - code coverage report
Current view: top level - src/backend/parser - parse_oper.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 270 290 93.1 %
Date: 2025-09-18 00:17:52 Functions: 19 20 95.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * parse_oper.c
       4             :  *      handle operator things for parser
       5             :  *
       6             :  * Portions Copyright (c) 1996-2025, 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        6122 : LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
     101             :                bool noError, int location)
     102             : {
     103             :     Oid         result;
     104             : 
     105        6122 :     result = OpernameGetOprid(opername, oprleft, oprright);
     106        6122 :     if (OidIsValid(result))
     107        5258 :         return result;
     108             : 
     109             :     /* we don't use op_error here because only an exact match is wanted */
     110         864 :     if (!noError)
     111             :     {
     112          48 :         if (!OidIsValid(oprright))
     113          12 :             ereport(ERROR,
     114             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     115             :                      errmsg("postfix operators are not supported"),
     116             :                      parser_errposition(pstate, location)));
     117             : 
     118          36 :         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             :     }
     124             : 
     125         816 :     return InvalidOid;
     126             : }
     127             : 
     128             : /*
     129             :  * LookupOperWithArgs
     130             :  *      Like LookupOperName, but the argument types are specified by
     131             :  *      a ObjectWithArgs node.
     132             :  */
     133             : Oid
     134        2506 : LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
     135             : {
     136             :     TypeName   *oprleft,
     137             :                *oprright;
     138             :     Oid         leftoid,
     139             :                 rightoid;
     140             : 
     141             :     Assert(list_length(oper->objargs) == 2);
     142        2506 :     oprleft = linitial_node(TypeName, oper->objargs);
     143        2506 :     oprright = lsecond_node(TypeName, oper->objargs);
     144             : 
     145        2506 :     if (oprleft == NULL)
     146          32 :         leftoid = InvalidOid;
     147             :     else
     148        2474 :         leftoid = LookupTypeNameOid(NULL, oprleft, noError);
     149             : 
     150        2500 :     if (oprright == NULL)
     151          12 :         rightoid = InvalidOid;
     152             :     else
     153        2488 :         rightoid = LookupTypeNameOid(NULL, oprright, noError);
     154             : 
     155        2494 :     return LookupOperName(NULL, oper->objname, leftoid, rightoid,
     156             :                           noError, -1);
     157             : }
     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      267526 : 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             :     TypeCacheEntry *typentry;
     187             :     int         cache_flags;
     188             :     Oid         lt_opr;
     189             :     Oid         eq_opr;
     190             :     Oid         gt_opr;
     191             :     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      267526 :     if (isHashable != NULL)
     200      151458 :         cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR |
     201             :             TYPECACHE_HASH_PROC;
     202             :     else
     203      116068 :         cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR;
     204             : 
     205      267526 :     typentry = lookup_type_cache(argtype, cache_flags);
     206      267526 :     lt_opr = typentry->lt_opr;
     207      267526 :     eq_opr = typentry->eq_opr;
     208      267526 :     gt_opr = typentry->gt_opr;
     209      267526 :     hashable = OidIsValid(typentry->hash_proc);
     210             : 
     211             :     /* Report errors if needed */
     212      267526 :     if ((needLT && !OidIsValid(lt_opr)) ||
     213        3504 :         (needGT && !OidIsValid(gt_opr)))
     214           6 :         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      267520 :     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      267520 :     if (ltOpr)
     227      264016 :         *ltOpr = lt_opr;
     228      267520 :     if (eqOpr)
     229      267520 :         *eqOpr = eq_opr;
     230      267520 :     if (gtOpr)
     231        3504 :         *gtOpr = gt_opr;
     232      267520 :     if (isHashable)
     233      151452 :         *isHashable = hashable;
     234      267520 : }
     235             : 
     236             : 
     237             : /* given operator tuple, return the operator OID */
     238             : Oid
     239      699624 : oprid(Operator op)
     240             : {
     241      699624 :     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             : }
     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       81600 : binary_oper_exact(List *opname, Oid arg1, Oid arg2)
     264             : {
     265             :     Oid         result;
     266       81600 :     bool        was_unknown = false;
     267             : 
     268             :     /* Unspecified type for one of the arguments? then use the other */
     269       81600 :     if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
     270             :     {
     271        4288 :         arg1 = arg2;
     272        4288 :         was_unknown = true;
     273             :     }
     274       77312 :     else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
     275             :     {
     276       21136 :         arg2 = arg1;
     277       21136 :         was_unknown = true;
     278             :     }
     279             : 
     280       81600 :     result = OpernameGetOprid(opname, arg1, arg2);
     281       81600 :     if (OidIsValid(result))
     282       63148 :         return result;
     283             : 
     284       18452 :     if (was_unknown)
     285             :     {
     286             :         /* arg1 and arg2 are the same here, need only look at arg1 */
     287        4620 :         Oid         basetype = getBaseType(arg1);
     288             : 
     289        4620 :         if (basetype != arg1)
     290             :         {
     291         316 :             result = OpernameGetOprid(opname, basetype, basetype);
     292         316 :             if (OidIsValid(result))
     293          62 :                 return result;
     294             :         }
     295             :     }
     296             : 
     297       18390 :     return InvalidOid;
     298             : }
     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       18426 : oper_select_candidate(int nargs,
     314             :                       Oid *input_typeids,
     315             :                       FuncCandidateList candidates,
     316             :                       Oid *operOid) /* output argument */
     317             : {
     318             :     int         ncandidates;
     319             : 
     320             :     /*
     321             :      * Delete any candidates that cannot actually accept the given input
     322             :      * types, whether directly or by coercion.
     323             :      */
     324       18426 :     ncandidates = func_match_argtypes(nargs, input_typeids,
     325             :                                       candidates, &candidates);
     326             : 
     327             :     /* Done if no candidate or only one candidate survives */
     328       18426 :     if (ncandidates == 0)
     329             :     {
     330         122 :         *operOid = InvalidOid;
     331         122 :         return FUNCDETAIL_NOTFOUND;
     332             :     }
     333       18304 :     if (ncandidates == 1)
     334             :     {
     335       12320 :         *operOid = candidates->oid;
     336       12320 :         return FUNCDETAIL_NORMAL;
     337             :     }
     338             : 
     339             :     /*
     340             :      * Use the same heuristics as for ambiguous functions to resolve the
     341             :      * conflict.
     342             :      */
     343        5984 :     candidates = func_select_candidate(nargs, input_typeids, candidates);
     344             : 
     345        5984 :     if (candidates)
     346             :     {
     347        5978 :         *operOid = candidates->oid;
     348        5978 :         return FUNCDETAIL_NORMAL;
     349             :     }
     350             : 
     351           6 :     *operOid = InvalidOid;
     352           6 :     return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
     353             : }
     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      698478 : oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
     372             :      bool noError, int location)
     373             : {
     374             :     Oid         operOid;
     375             :     OprCacheKey key;
     376             :     bool        key_ok;
     377      698478 :     int         fgc_flags = 0;
     378      698478 :     FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
     379      698478 :     HeapTuple   tup = NULL;
     380             : 
     381             :     /*
     382             :      * Try to find the mapping in the lookaside cache.
     383             :      */
     384      698478 :     key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
     385             : 
     386      698478 :     if (key_ok)
     387             :     {
     388      698478 :         operOid = find_oper_cache_entry(&key);
     389      698478 :         if (OidIsValid(operOid))
     390             :         {
     391      616878 :             tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     392      616878 :             if (HeapTupleIsValid(tup))
     393      616878 :                 return (Operator) tup;
     394             :         }
     395             :     }
     396             : 
     397             :     /*
     398             :      * First try for an "exact" match.
     399             :      */
     400       81600 :     operOid = binary_oper_exact(opname, ltypeId, rtypeId);
     401       81600 :     if (!OidIsValid(operOid))
     402             :     {
     403             :         /*
     404             :          * Otherwise, search for the most suitable candidate.
     405             :          */
     406             :         FuncCandidateList clist;
     407             : 
     408             :         /* Get binary operators of given name */
     409       18390 :         clist = OpernameGetCandidates(opname, 'b', false, &fgc_flags);
     410             : 
     411             :         /* No operators found? Then fail... */
     412       18390 :         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             :             Oid         inputOids[2];
     419             : 
     420       18390 :             if (rtypeId == InvalidOid)
     421           0 :                 rtypeId = ltypeId;
     422       18390 :             else if (ltypeId == InvalidOid)
     423           0 :                 ltypeId = rtypeId;
     424       18390 :             inputOids[0] = ltypeId;
     425       18390 :             inputOids[1] = rtypeId;
     426       18390 :             fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
     427             :         }
     428             :     }
     429             : 
     430       81600 :     if (OidIsValid(operOid))
     431       81478 :         tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     432             : 
     433       81600 :     if (HeapTupleIsValid(tup))
     434             :     {
     435       81478 :         if (key_ok)
     436       81478 :             make_oper_cache_entry(&key, operOid);
     437             :     }
     438         122 :     else if (!noError)
     439         112 :         op_error(pstate, opname, ltypeId, rtypeId,
     440             :                  fdresult, fgc_flags, location);
     441             : 
     442       81488 :     return (Operator) tup;
     443             : }
     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         568 : compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2,
     454             :                 bool noError, int location)
     455             : {
     456             :     Operator    optup;
     457             :     Form_pg_operator opform;
     458             : 
     459             :     /* oper() will find the best available match */
     460         568 :     optup = oper(pstate, op, arg1, arg2, noError, location);
     461         568 :     if (optup == (Operator) NULL)
     462           0 :         return (Operator) NULL; /* must be noError case */
     463             : 
     464             :     /* but is it good enough? */
     465         568 :     opform = (Form_pg_operator) GETSTRUCT(optup);
     466        1136 :     if (IsBinaryCoercible(arg1, opform->oprleft) &&
     467         568 :         IsBinaryCoercible(arg2, opform->oprright))
     468         568 :         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             : }
     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         568 : compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
     491             : {
     492             :     Operator    optup;
     493             :     Oid         result;
     494             : 
     495         568 :     optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
     496         568 :     if (optup != NULL)
     497             :     {
     498         568 :         result = oprid(optup);
     499         568 :         ReleaseSysCache(optup);
     500         568 :         return result;
     501             :     }
     502           0 :     return InvalidOid;
     503             : }
     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        1298 : left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
     522             : {
     523             :     Oid         operOid;
     524             :     OprCacheKey key;
     525             :     bool        key_ok;
     526        1298 :     int         fgc_flags = 0;
     527        1298 :     FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
     528        1298 :     HeapTuple   tup = NULL;
     529             : 
     530             :     /*
     531             :      * Try to find the mapping in the lookaside cache.
     532             :      */
     533        1298 :     key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
     534             : 
     535        1298 :     if (key_ok)
     536             :     {
     537        1298 :         operOid = find_oper_cache_entry(&key);
     538        1298 :         if (OidIsValid(operOid))
     539             :         {
     540         820 :             tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     541         820 :             if (HeapTupleIsValid(tup))
     542         820 :                 return (Operator) tup;
     543             :         }
     544             :     }
     545             : 
     546             :     /*
     547             :      * First try for an "exact" match.
     548             :      */
     549         478 :     operOid = OpernameGetOprid(op, InvalidOid, arg);
     550         478 :     if (!OidIsValid(operOid))
     551             :     {
     552             :         /*
     553             :          * Otherwise, search for the most suitable candidate.
     554             :          */
     555             :         FuncCandidateList clist;
     556             : 
     557             :         /* Get prefix operators of given name */
     558          48 :         clist = OpernameGetCandidates(op, 'l', false, &fgc_flags);
     559             : 
     560             :         /* No operators found? Then fail... */
     561          48 :         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             :             FuncCandidateList clisti;
     569             : 
     570         118 :             for (clisti = clist; clisti != NULL; clisti = clisti->next)
     571             :             {
     572          82 :                 clisti->args[0] = clisti->args[1];
     573             :             }
     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          36 :             fdresult = oper_select_candidate(1, &arg, clist, &operOid);
     580             :         }
     581             :     }
     582             : 
     583         478 :     if (OidIsValid(operOid))
     584         460 :         tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
     585             : 
     586         478 :     if (HeapTupleIsValid(tup))
     587             :     {
     588         460 :         if (key_ok)
     589         460 :             make_oper_cache_entry(&key, operOid);
     590             :     }
     591          18 :     else if (!noError)
     592          18 :         op_error(pstate, op, InvalidOid, arg,
     593             :                  fdresult, fgc_flags, location);
     594             : 
     595         460 :     return (Operator) tup;
     596             : }
     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         166 : op_signature_string(List *op, Oid arg1, Oid arg2)
     608             : {
     609             :     StringInfoData argbuf;
     610             : 
     611         166 :     initStringInfo(&argbuf);
     612             : 
     613         166 :     if (OidIsValid(arg1))
     614         136 :         appendStringInfo(&argbuf, "%s ", format_type_be(arg1));
     615             : 
     616         166 :     appendStringInfoString(&argbuf, NameListToString(op));
     617             : 
     618         166 :     appendStringInfo(&argbuf, " %s", format_type_be(arg2));
     619             : 
     620         166 :     return argbuf.data;         /* return palloc'd string buffer */
     621             : }
     622             : 
     623             : /*
     624             :  * op_error - utility routine to complain about an unresolvable operator
     625             :  */
     626             : static void
     627         130 : op_error(ParseState *pstate, List *op,
     628             :          Oid arg1, Oid arg2,
     629             :          FuncDetailCode fdresult, int fgc_flags, int location)
     630             : {
     631         130 :     if (fdresult == FUNCDETAIL_MULTIPLE)
     632           6 :         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         124 :         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             : }
     647             : 
     648             : /*
     649             :  * Interpret the fgc_flags and issue a suitable detail or hint message.
     650             :  */
     651             : static int
     652         124 : 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         124 :     if (!(fgc_flags & FGC_NAME_VISIBLE))
     666             :     {
     667          12 :         if (fgc_flags & FGC_SCHEMA_GIVEN)
     668           0 :             return 0;           /* schema-qualified name */
     669          12 :         else if (!(fgc_flags & FGC_NAME_EXISTS))
     670           6 :             return errdetail("There is no operator of that name.");
     671             :         else
     672           6 :             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         112 :     if (is_unary_op)
     679             :     {
     680           6 :         (void) errdetail("No operator of that name accepts the given argument type.");
     681           6 :         return errhint("You might need to add an explicit type cast.");
     682             :     }
     683             :     else
     684             :     {
     685         106 :         (void) errdetail("No operator of that name accepts the given argument types.");
     686         106 :         return errhint("You might need to add explicit type casts.");
     687             :     }
     688             : }
     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      599670 : make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
     704             :         Node *last_srf, int location)
     705             : {
     706             :     Oid         ltypeId,
     707             :                 rtypeId;
     708             :     Operator    tup;
     709             :     Form_pg_operator opform;
     710             :     Oid         actual_arg_types[2];
     711             :     Oid         declared_arg_types[2];
     712             :     int         nargs;
     713             :     List       *args;
     714             :     Oid         rettype;
     715             :     OpExpr     *result;
     716             : 
     717             :     /* Check it's not a postfix operator */
     718      599670 :     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      599670 :     if (ltree == NULL)
     725             :     {
     726             :         /* prefix operator */
     727        1268 :         rtypeId = exprType(rtree);
     728        1268 :         ltypeId = InvalidOid;
     729        1268 :         tup = left_oper(pstate, opname, rtypeId, false, location);
     730             :     }
     731             :     else
     732             :     {
     733             :         /* otherwise, binary operator */
     734      598402 :         ltypeId = exprType(ltree);
     735      598402 :         rtypeId = exprType(rtree);
     736      598402 :         tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
     737             :     }
     738             : 
     739      599540 :     opform = (Form_pg_operator) GETSTRUCT(tup);
     740             : 
     741             :     /* Check it's not a shell */
     742      599540 :     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      599540 :     if (ltree == NULL)
     753             :     {
     754             :         /* prefix operator */
     755        1250 :         args = list_make1(rtree);
     756        1250 :         actual_arg_types[0] = rtypeId;
     757        1250 :         declared_arg_types[0] = opform->oprright;
     758        1250 :         nargs = 1;
     759             :     }
     760             :     else
     761             :     {
     762             :         /* otherwise, binary operator */
     763      598290 :         args = list_make2(ltree, rtree);
     764      598290 :         actual_arg_types[0] = ltypeId;
     765      598290 :         actual_arg_types[1] = rtypeId;
     766      598290 :         declared_arg_types[0] = opform->oprleft;
     767      598290 :         declared_arg_types[1] = opform->oprright;
     768      598290 :         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      599540 :     rettype = enforce_generic_type_consistency(actual_arg_types,
     777             :                                                declared_arg_types,
     778             :                                                nargs,
     779             :                                                opform->oprresult,
     780             :                                                false);
     781             : 
     782             :     /* perform the necessary typecasting of arguments */
     783      599540 :     make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
     784             : 
     785             :     /* and build the expression node */
     786      599534 :     result = makeNode(OpExpr);
     787      599534 :     result->opno = oprid(tup);
     788      599534 :     result->opfuncid = opform->oprcode;
     789      599534 :     result->opresulttype = rettype;
     790      599534 :     result->opretset = get_func_retset(opform->oprcode);
     791             :     /* opcollid and inputcollid will be set by parse_collate.c */
     792      599534 :     result->args = args;
     793      599534 :     result->location = location;
     794             : 
     795             :     /* if it returns a set, check that's OK */
     796      599534 :     if (result->opretset)
     797             :     {
     798           6 :         check_srf_call_placement(pstate, last_srf, location);
     799             :         /* ... and remember it for error checks at higher levels */
     800           6 :         pstate->p_last_srf = (Node *) result;
     801             :     }
     802             : 
     803      599534 :     ReleaseSysCache(tup);
     804             : 
     805      599534 :     return (Expr *) result;
     806             : }
     807             : 
     808             : /*
     809             :  * make_scalar_array_op()
     810             :  *      Build expression tree for "scalar op ANY/ALL (array)" construct.
     811             :  */
     812             : Expr *
     813       35460 : make_scalar_array_op(ParseState *pstate, List *opname,
     814             :                      bool useOr,
     815             :                      Node *ltree, Node *rtree,
     816             :                      int location)
     817             : {
     818             :     Oid         ltypeId,
     819             :                 rtypeId,
     820             :                 atypeId,
     821             :                 res_atypeId;
     822             :     Operator    tup;
     823             :     Form_pg_operator opform;
     824             :     Oid         actual_arg_types[2];
     825             :     Oid         declared_arg_types[2];
     826             :     List       *args;
     827             :     Oid         rettype;
     828             :     ScalarArrayOpExpr *result;
     829             : 
     830       35460 :     ltypeId = exprType(ltree);
     831       35460 :     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       35460 :     if (atypeId == UNKNOWNOID)
     839         222 :         rtypeId = UNKNOWNOID;
     840             :     else
     841             :     {
     842       35238 :         rtypeId = get_base_element_type(atypeId);
     843       35238 :         if (!OidIsValid(rtypeId))
     844           6 :             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       35454 :     tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
     852       35454 :     opform = (Form_pg_operator) GETSTRUCT(tup);
     853             : 
     854             :     /* Check it's not a shell */
     855       35454 :     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       35454 :     args = list_make2(ltree, rtree);
     865       35454 :     actual_arg_types[0] = ltypeId;
     866       35454 :     actual_arg_types[1] = rtypeId;
     867       35454 :     declared_arg_types[0] = opform->oprleft;
     868       35454 :     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       35454 :     rettype = enforce_generic_type_consistency(actual_arg_types,
     876             :                                                declared_arg_types,
     877             :                                                2,
     878             :                                                opform->oprresult,
     879             :                                                false);
     880             : 
     881             :     /*
     882             :      * Check that operator result is boolean
     883             :      */
     884       35454 :     if (rettype != BOOLOID)
     885           6 :         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       35448 :     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       35448 :     if (IsPolymorphicType(declared_arg_types[1]))
     902             :     {
     903             :         /* assume the actual array type is OK */
     904          40 :         res_atypeId = atypeId;
     905             :     }
     906             :     else
     907             :     {
     908       35408 :         res_atypeId = get_array_type(declared_arg_types[1]);
     909       35408 :         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       35448 :     actual_arg_types[1] = atypeId;
     917       35448 :     declared_arg_types[1] = res_atypeId;
     918             : 
     919             :     /* perform the necessary typecasting of arguments */
     920       35448 :     make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
     921             : 
     922             :     /* and build the expression node */
     923       35448 :     result = makeNode(ScalarArrayOpExpr);
     924       35448 :     result->opno = oprid(tup);
     925       35448 :     result->opfuncid = opform->oprcode;
     926       35448 :     result->hashfuncid = InvalidOid;
     927       35448 :     result->negfuncid = InvalidOid;
     928       35448 :     result->useOr = useOr;
     929             :     /* inputcollid will be set by parse_collate.c */
     930       35448 :     result->args = args;
     931       35448 :     result->location = location;
     932             : 
     933       35448 :     ReleaseSysCache(tup);
     934             : 
     935       35448 :     return (Expr *) result;
     936             : }
     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      699776 : make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname,
     981             :                     Oid ltypeId, Oid rtypeId, int location)
     982             : {
     983             :     char       *schemaname;
     984             :     char       *opername;
     985             : 
     986             :     /* deconstruct the name list */
     987      699776 :     DeconstructQualifiedName(opname, &schemaname, &opername);
     988             : 
     989             :     /* ensure zero-fill for stable hashing */
     990    12595968 :     MemSet(key, 0, sizeof(OprCacheKey));
     991             : 
     992             :     /* save operator name and input types into key */
     993      699776 :     strlcpy(key->oprname, opername, NAMEDATALEN);
     994      699776 :     key->left_arg = ltypeId;
     995      699776 :     key->right_arg = rtypeId;
     996             : 
     997      699776 :     if (schemaname)
     998             :     {
     999             :         ParseCallbackState pcbstate;
    1000             : 
    1001             :         /* search only in exact schema given */
    1002       16076 :         setup_parser_errposition_callback(&pcbstate, pstate, location);
    1003       16076 :         key->search_path[0] = LookupExplicitNamespace(schemaname, false);
    1004       16076 :         cancel_parser_errposition_callback(&pcbstate);
    1005             :     }
    1006             :     else
    1007             :     {
    1008             :         /* get the active search path */
    1009      683700 :         if (fetch_search_path_array(key->search_path,
    1010             :                                     MAX_CACHED_PATH_LEN) > MAX_CACHED_PATH_LEN)
    1011           0 :             return false;       /* oops, didn't fit */
    1012             :     }
    1013             : 
    1014      699776 :     return true;
    1015             : }
    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      699776 : find_oper_cache_entry(OprCacheKey *key)
    1025             : {
    1026             :     OprCacheEntry *oprentry;
    1027             : 
    1028      699776 :     if (OprCacheHash == NULL)
    1029             :     {
    1030             :         /* First time through: initialize the hash table */
    1031             :         HASHCTL     ctl;
    1032             : 
    1033       11140 :         ctl.keysize = sizeof(OprCacheKey);
    1034       11140 :         ctl.entrysize = sizeof(OprCacheEntry);
    1035       11140 :         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       11140 :         CacheRegisterSyscacheCallback(OPERNAMENSP,
    1040             :                                       InvalidateOprCacheCallBack,
    1041             :                                       (Datum) 0);
    1042       11140 :         CacheRegisterSyscacheCallback(CASTSOURCETARGET,
    1043             :                                       InvalidateOprCacheCallBack,
    1044             :                                       (Datum) 0);
    1045             :     }
    1046             : 
    1047             :     /* Look for an existing entry */
    1048      699776 :     oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
    1049             :                                              key,
    1050             :                                              HASH_FIND, NULL);
    1051      699776 :     if (oprentry == NULL)
    1052       82078 :         return InvalidOid;
    1053             : 
    1054      617698 :     return oprentry->opr_oid;
    1055             : }
    1056             : 
    1057             : /*
    1058             :  * make_oper_cache_entry
    1059             :  *
    1060             :  * Insert a cache entry for the given key.
    1061             :  */
    1062             : static void
    1063       81938 : make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
    1064             : {
    1065             :     OprCacheEntry *oprentry;
    1066             : 
    1067             :     Assert(OprCacheHash != NULL);
    1068             : 
    1069       81938 :     oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
    1070             :                                              key,
    1071             :                                              HASH_ENTER, NULL);
    1072       81938 :     oprentry->opr_oid = opr_oid;
    1073       81938 : }
    1074             : 
    1075             : /*
    1076             :  * Callback for pg_operator and pg_cast inval events
    1077             :  */
    1078             : static void
    1079       13078 : InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
    1080             : {
    1081             :     HASH_SEQ_STATUS status;
    1082             :     OprCacheEntry *hentry;
    1083             : 
    1084             :     Assert(OprCacheHash != NULL);
    1085             : 
    1086             :     /* Currently we just flush all entries; hard to be smarter ... */
    1087       13078 :     hash_seq_init(&status, OprCacheHash);
    1088             : 
    1089       29864 :     while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
    1090             :     {
    1091       16786 :         if (hash_search(OprCacheHash,
    1092       16786 :                         &hentry->key,
    1093             :                         HASH_REMOVE, NULL) == NULL)
    1094           0 :             elog(ERROR, "hash table corrupted");
    1095             :     }
    1096       13078 : }

Generated by: LCOV version 1.16