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

Generated by: LCOV version 2.0-1