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