PostgreSQL Source Code git master
Loading...
Searching...
No Matches
parse_oper.c
Go to the documentation of this file.
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
51typedef struct OprCacheKey
52{
54 Oid left_arg; /* Left input OID, or 0 if prefix op */
55 Oid right_arg; /* Right input OID */
58
59typedef struct OprCacheEntry
60{
61 /* the hash lookup key MUST BE FIRST */
63
64 Oid opr_oid; /* OID of the resolved operator */
66
67
72 Oid *operOid);
73static void op_error(ParseState *pstate, List *op,
75 FuncDetailCode fdresult, int fgc_flags, int location);
77static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key,
79 int location);
81static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
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 */
100Oid
101LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
102 bool noError, int location)
103{
104 Oid result;
105
106 result = OpernameGetOprid(opername, oprleft, oprright);
107 if (OidIsValid(result))
108 return result;
109
110 /* we don't use op_error here because only an exact match is wanted */
111 if (!noError)
112 {
113 if (!OidIsValid(oprright))
116 errmsg("postfix operators are not supported"),
117 parser_errposition(pstate, location)));
118
121 errmsg("operator does not exist: %s",
122 op_signature_string(opername, oprleft, oprright)),
123 parser_errposition(pstate, location)));
124 }
125
126 return InvalidOid;
127}
128
129/*
130 * LookupOperWithArgs
131 * Like LookupOperName, but the argument types are specified by
132 * a ObjectWithArgs node.
133 */
134Oid
136{
137 TypeName *oprleft,
138 *oprright;
139 Oid leftoid,
140 rightoid;
141
142 Assert(list_length(oper->objargs) == 2);
143 oprleft = linitial_node(TypeName, oper->objargs);
144 oprright = lsecond_node(TypeName, oper->objargs);
145
146 if (oprleft == NULL)
148 else
150
151 if (oprright == NULL)
153 else
155
156 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 */
181void
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 if (isHashable != NULL)
203 else
205
206 typentry = lookup_type_cache(argtype, cache_flags);
207 lt_opr = typentry->lt_opr;
208 eq_opr = typentry->eq_opr;
209 gt_opr = typentry->gt_opr;
210 hashable = OidIsValid(typentry->hash_proc);
211
212 /* Report errors if needed */
213 if ((needLT && !OidIsValid(lt_opr)) ||
214 (needGT && !OidIsValid(gt_opr)))
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 if (needEQ && !OidIsValid(eq_opr))
223 errmsg("could not identify an equality operator for type %s",
224 format_type_be(argtype))));
225
226 /* Return results as needed */
227 if (ltOpr)
228 *ltOpr = lt_opr;
229 if (eqOpr)
230 *eqOpr = eq_opr;
231 if (gtOpr)
232 *gtOpr = gt_opr;
233 if (isHashable)
234 *isHashable = hashable;
235}
236
237
238/* given operator tuple, return the operator OID */
239Oid
241{
242 return ((Form_pg_operator) GETSTRUCT(op))->oid;
243}
244
245/* given operator tuple, return the underlying function's OID */
246Oid
248{
250
251 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 */
263static Oid
265{
266 Oid result;
267 bool was_unknown = false;
268
269 /* Unspecified type for one of the arguments? then use the other */
270 if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
271 {
272 arg1 = arg2;
273 was_unknown = true;
274 }
275 else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
276 {
277 arg2 = arg1;
278 was_unknown = true;
279 }
280
281 result = OpernameGetOprid(opname, arg1, arg2);
282 if (OidIsValid(result))
283 return result;
284
285 if (was_unknown)
286 {
287 /* arg1 and arg2 are the same here, need only look at arg1 */
289
290 if (basetype != arg1)
291 {
293 if (OidIsValid(result))
294 return result;
295 }
296 }
297
298 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 */
313static FuncDetailCode
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 */
327
328 /* Done if no candidate or only one candidate survives */
329 if (ncandidates == 0)
330 {
332 return FUNCDETAIL_NOTFOUND;
333 }
334 if (ncandidates == 1)
335 {
336 *operOid = candidates->oid;
337 return FUNCDETAIL_NORMAL;
338 }
339
340 /*
341 * Use the same heuristics as for ambiguous functions to resolve the
342 * conflict.
343 */
345
346 if (candidates)
347 {
348 *operOid = candidates->oid;
349 return FUNCDETAIL_NORMAL;
350 }
351
353 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 */
373 bool noError, int location)
374{
375 Oid operOid;
376 OprCacheKey key;
377 bool key_ok;
378 int fgc_flags = 0;
381
382 /*
383 * Try to find the mapping in the lookaside cache.
384 */
385 key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
386
387 if (key_ok)
388 {
390 if (OidIsValid(operOid))
391 {
394 return (Operator) tup;
395 }
396 }
397
398 /*
399 * First try for an "exact" match.
400 */
402 if (!OidIsValid(operOid))
403 {
404 /*
405 * Otherwise, search for the most suitable candidate.
406 */
408
409 /* Get binary operators of given name */
411
412 /* No operators found? Then fail... */
413 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 if (rtypeId == InvalidOid)
423 else if (ltypeId == InvalidOid)
425 inputOids[0] = ltypeId;
426 inputOids[1] = rtypeId;
428 }
429 }
430
431 if (OidIsValid(operOid))
433
435 {
436 if (key_ok)
438 }
439 else if (!noError)
440 op_error(pstate, opname, ltypeId, rtypeId,
441 fdresult, fgc_flags, location);
442
443 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 */
455 bool noError, int location)
456{
459
460 /* oper() will find the best available match */
461 optup = oper(pstate, op, arg1, arg2, noError, location);
462 if (optup == (Operator) NULL)
463 return (Operator) NULL; /* must be noError case */
464
465 /* but is it good enough? */
467 if (IsBinaryCoercible(arg1, opform->oprleft) &&
468 IsBinaryCoercible(arg2, opform->oprright))
469 return optup;
470
471 /* nope... */
473
474 if (!noError)
477 errmsg("operator requires run-time type coercion: %s",
479 parser_errposition(pstate, location)));
480
481 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 */
490Oid
492{
494 Oid result;
495
497 if (optup != NULL)
498 {
499 result = oprid(optup);
501 return result;
502 }
503 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 */
522left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
523{
524 Oid operOid;
525 OprCacheKey key;
526 bool key_ok;
527 int fgc_flags = 0;
530
531 /*
532 * Try to find the mapping in the lookaside cache.
533 */
534 key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
535
536 if (key_ok)
537 {
539 if (OidIsValid(operOid))
540 {
543 return (Operator) tup;
544 }
545 }
546
547 /*
548 * First try for an "exact" match.
549 */
551 if (!OidIsValid(operOid))
552 {
553 /*
554 * Otherwise, search for the most suitable candidate.
555 */
557
558 /* Get prefix operators of given name */
559 clist = OpernameGetCandidates(op, 'l', false, &fgc_flags);
560
561 /* No operators found? Then fail... */
562 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 */
570
571 for (clisti = clist; clisti != NULL; clisti = clisti->next)
572 {
573 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 */
581 }
582 }
583
584 if (OidIsValid(operOid))
586
588 {
589 if (key_ok)
591 }
592 else if (!noError)
593 op_error(pstate, op, InvalidOid, arg,
594 fdresult, fgc_flags, location);
595
596 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 */
607const char *
609{
611
613
614 if (OidIsValid(arg1))
616
618
620
621 return argbuf.data; /* return palloc'd string buffer */
622}
623
624/*
625 * op_error - utility routine to complain about an unresolvable operator
626 */
627static void
629 Oid arg1, Oid arg2,
630 FuncDetailCode fdresult, int fgc_flags, int location)
631{
635 errmsg("operator is not unique: %s",
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
643 errmsg("operator does not exist: %s",
646 parser_errposition(pstate, location)));
647}
648
649/*
650 * Interpret the fgc_flags and issue a suitable detail or hint message.
651 */
652static int
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 */
667 {
669 return 0; /* schema-qualified name */
670 else if (!(fgc_flags & FGC_NAME_EXISTS))
671 return errdetail("There is no operator of that name.");
672 else
673 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 if (is_unary_op)
680 {
681 (void) errdetail("No operator of that name accepts the given argument type.");
682 return errhint("You might need to add an explicit type cast.");
683 }
684 else
685 {
686 (void) errdetail("No operator of that name accepts the given argument types.");
687 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 */
703Expr *
705 Node *last_srf, int location)
706{
707 Oid ltypeId,
708 rtypeId;
713 int nargs;
714 List *args;
715 Oid rettype;
716 OpExpr *result;
717
718 /* Check it's not a postfix operator */
719 if (rtree == NULL)
722 errmsg("postfix operators are not supported")));
723
724 /* Select the operator */
725 if (ltree == NULL)
726 {
727 /* prefix operator */
730 tup = left_oper(pstate, opname, rtypeId, false, location);
731 }
732 else
733 {
734 /* otherwise, binary operator */
737 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
738 }
739
741
742 /* Check it's not a shell */
743 if (!RegProcedureIsValid(opform->oprcode))
746 errmsg("operator is only a shell: %s",
748 opform->oprleft,
749 opform->oprright)),
750 parser_errposition(pstate, location)));
751
752 /* Do typecasting and build the expression tree */
753 if (ltree == NULL)
754 {
755 /* prefix operator */
756 args = list_make1(rtree);
758 declared_arg_types[0] = opform->oprright;
759 nargs = 1;
760 }
761 else
762 {
763 /* otherwise, binary operator */
764 args = list_make2(ltree, rtree);
767 declared_arg_types[0] = opform->oprleft;
768 declared_arg_types[1] = opform->oprright;
769 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 */
779 nargs,
780 opform->oprresult,
781 false);
782
783 /* perform the necessary typecasting of arguments */
785
786 /* and build the expression node */
787 result = makeNode(OpExpr);
788 result->opno = oprid(tup);
789 result->opfuncid = opform->oprcode;
790 result->opresulttype = rettype;
791 result->opretset = get_func_retset(opform->oprcode);
792 /* opcollid and inputcollid will be set by parse_collate.c */
793 result->args = args;
794 result->location = location;
795
796 /* if it returns a set, check that's OK */
797 if (result->opretset)
798 {
799 check_srf_call_placement(pstate, last_srf, location);
800 /* ... and remember it for error checks at higher levels */
801 pstate->p_last_srf = (Node *) result;
802 }
803
805
806 return (Expr *) result;
807}
808
809/*
810 * make_scalar_array_op()
811 * Build expression tree for "scalar op ANY/ALL (array)" construct.
812 */
813Expr *
815 bool useOr,
816 Node *ltree, Node *rtree,
817 int location)
818{
819 Oid ltypeId,
820 rtypeId,
821 atypeId,
827 List *args;
828 Oid rettype;
829 ScalarArrayOpExpr *result;
830
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 if (atypeId == UNKNOWNOID)
841 else
842 {
844 if (!OidIsValid(rtypeId))
847 errmsg("op ANY/ALL (array) requires array on right side"),
848 parser_errposition(pstate, location)));
849 }
850
851 /* Now resolve the operator */
852 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
854
855 /* Check it's not a shell */
856 if (!RegProcedureIsValid(opform->oprcode))
859 errmsg("operator is only a shell: %s",
861 opform->oprleft,
862 opform->oprright)),
863 parser_errposition(pstate, location)));
864
865 args = list_make2(ltree, rtree);
868 declared_arg_types[0] = opform->oprleft;
869 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 */
878 2,
879 opform->oprresult,
880 false);
881
882 /*
883 * Check that operator result is boolean
884 */
885 if (rettype != BOOLOID)
888 errmsg("op ANY/ALL (array) requires operator to yield boolean"),
889 parser_errposition(pstate, location)));
890 if (get_func_retset(opform->oprcode))
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 */
903 {
904 /* assume the actual array type is OK */
906 }
907 else
908 {
913 errmsg("could not find array type for data type %s",
915 parser_errposition(pstate, location)));
916 }
919
920 /* perform the necessary typecasting of arguments */
922
923 /* and build the expression node */
924 result = makeNode(ScalarArrayOpExpr);
925 result->opno = oprid(tup);
926 result->opfuncid = opform->oprcode;
927 result->hashfuncid = InvalidOid;
928 result->negfuncid = InvalidOid;
929 result->useOr = useOr;
930 /* inputcollid will be set by parse_collate.c */
931 result->args = args;
932 result->location = location;
933
935
936 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 */
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 */
980static bool
982 Oid ltypeId, Oid rtypeId, int location)
983{
984 char *schemaname;
985 char *opername;
986
987 /* deconstruct the name list */
988 DeconstructQualifiedName(opname, &schemaname, &opername);
989
990 /* ensure zero-fill for stable hashing */
991 MemSet(key, 0, sizeof(OprCacheKey));
992
993 /* save operator name and input types into key */
994 strlcpy(key->oprname, opername, NAMEDATALEN);
995 key->left_arg = ltypeId;
996 key->right_arg = rtypeId;
997
998 if (schemaname)
999 {
1001
1002 /* search only in exact schema given */
1003 setup_parser_errposition_callback(&pcbstate, pstate, location);
1004 key->search_path[0] = LookupExplicitNamespace(schemaname, false);
1006 }
1007 else
1008 {
1009 /* get the active search path */
1010 if (fetch_search_path_array(key->search_path,
1012 return false; /* oops, didn't fit */
1013 }
1014
1015 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 */
1024static Oid
1026{
1028
1029 if (OprCacheHash == NULL)
1030 {
1031 /* First time through: initialize the hash table */
1032 HASHCTL ctl;
1033
1034 ctl.keysize = sizeof(OprCacheKey);
1035 ctl.entrysize = sizeof(OprCacheEntry);
1036 OprCacheHash = hash_create("Operator lookup cache", 256,
1038
1039 /* Arrange to flush cache on pg_operator and pg_cast changes */
1042 (Datum) 0);
1045 (Datum) 0);
1046 }
1047
1048 /* Look for an existing entry */
1050 key,
1051 HASH_FIND, NULL);
1052 if (oprentry == NULL)
1053 return InvalidOid;
1054
1055 return oprentry->opr_oid;
1056}
1057
1058/*
1059 * make_oper_cache_entry
1060 *
1061 * Insert a cache entry for the given key.
1062 */
1063static void
1065{
1067
1069
1071 key,
1072 HASH_ENTER, NULL);
1073 oprentry->opr_oid = opr_oid;
1074}
1075
1076/*
1077 * Callback for pg_operator and pg_cast inval events
1078 */
1079static void
1081 uint32 hashvalue)
1082{
1083 HASH_SEQ_STATUS status;
1085
1087
1088 /* Currently we just flush all entries; hard to be smarter ... */
1089 hash_seq_init(&status, OprCacheHash);
1090
1091 while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
1092 {
1094 &hentry->key,
1095 HASH_REMOVE, NULL) == NULL)
1096 elog(ERROR, "hash table corrupted");
1097 }
1098}
#define RegProcedureIsValid(p)
Definition c.h:804
#define Assert(condition)
Definition c.h:885
uint32_t uint32
Definition c.h:558
#define MemSet(start, val, len)
Definition c.h:1035
#define OidIsValid(objectId)
Definition c.h:800
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
char * format_type_be(Oid type_oid)
@ HASH_FIND
Definition hsearch.h:113
@ HASH_REMOVE
Definition hsearch.h:115
@ HASH_ENTER
Definition hsearch.h:114
#define HASH_ELEM
Definition hsearch.h:95
#define HASH_BLOBS
Definition hsearch.h:97
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1816
bool get_func_retset(Oid funcid)
Definition lsyscache.c:1892
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:2984
Oid getBaseType(Oid typid)
Definition lsyscache.c:2673
Oid get_array_type(Oid typid)
Definition lsyscache.c:2939
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition namespace.c:1834
char * NameListToString(const List *names)
Definition namespace.c:3666
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition namespace.c:3457
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Definition namespace.c:3373
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok, int *fgc_flags)
Definition namespace.c:1947
int fetch_search_path_array(Oid *sarray, int sarray_len)
Definition namespace.c:4931
#define FGC_NAME_EXISTS
Definition namespace.h:49
#define FGC_SCHEMA_GIVEN
Definition namespace.h:47
#define FGC_NAME_VISIBLE
Definition namespace.h:50
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
#define makeNode(_type_)
Definition nodes.h:161
Oid enforce_generic_type_consistency(const Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
void make_fn_arguments(ParseState *pstate, List *fargs, Oid *actual_arg_types, Oid *declared_arg_types)
FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates)
void check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
int func_match_argtypes(int nargs, Oid *input_typeids, FuncCandidateList raw_candidates, FuncCandidateList *candidates)
FuncDetailCode
Definition parse_func.h:23
@ FUNCDETAIL_MULTIPLE
Definition parse_func.h:25
@ FUNCDETAIL_NORMAL
Definition parse_func.h:26
@ FUNCDETAIL_NOTFOUND
Definition parse_func.h:24
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition parse_node.c:156
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition parse_node.c:140
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
static FuncDetailCode oper_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
Definition parse_oper.c:314
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition parse_oper.c:522
static void InvalidateOprCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
void get_sort_group_operators(Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
Definition parse_oper.c:182
#define MAX_CACHED_PATH_LEN
Definition parse_oper.c:49
static int oper_lookup_failure_details(int fgc_flags, bool is_unary_op)
Definition parse_oper.c:653
Expr * make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, Node *last_srf, int location)
Definition parse_oper.c:704
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition parse_oper.c:101
Expr * make_scalar_array_op(ParseState *pstate, List *opname, bool useOr, Node *ltree, Node *rtree, int location)
Definition parse_oper.c:814
Oid oprfuncid(Operator op)
Definition parse_oper.c:247
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
Definition parse_oper.c:981
static HTAB * OprCacheHash
Definition parse_oper.c:967
Oid oprid(Operator op)
Definition parse_oper.c:240
static void op_error(ParseState *pstate, List *op, Oid arg1, Oid arg2, FuncDetailCode fdresult, int fgc_flags, int location)
Definition parse_oper.c:628
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition parse_oper.c:372
static Oid binary_oper_exact(List *opname, Oid arg1, Oid arg2)
Definition parse_oper.c:264
static Oid find_oper_cache_entry(OprCacheKey *key)
const char * op_signature_string(List *op, Oid arg1, Oid arg2)
Definition parse_oper.c:608
Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
Definition parse_oper.c:491
Operator compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
Definition parse_oper.c:454
Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError)
Definition parse_oper.c:135
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition parse_type.c:232
#define NAMEDATALEN
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial_node(type, l)
Definition pg_list.h:181
#define lsecond_node(type, l)
Definition pg_list.h:186
#define list_make1(x1)
Definition pg_list.h:212
#define list_make2(x1, x2)
Definition pg_list.h:214
END_CATALOG_STRUCT typedef FormData_pg_operator * Form_pg_operator
Definition pg_operator.h:87
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
#define InvalidOid
unsigned int Oid
static int fb(int x)
tree ctl
Definition radixtree.h:1838
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
Size keysize
Definition hsearch.h:75
Definition pg_list.h:54
Definition nodes.h:135
Oid opno
Definition primnodes.h:851
List * args
Definition primnodes.h:869
ParseLoc location
Definition primnodes.h:872
OprCacheKey key
Definition parse_oper.c:62
Oid search_path[MAX_CACHED_PATH_LEN]
Definition parse_oper.c:56
char oprname[NAMEDATALEN]
Definition parse_oper.c:53
Node * p_last_srf
Definition parse_node.h:227
ParseLoc location
Definition primnodes.h:952
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition namespace.h:39
Definition ltree.h:43
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_EQ_OPR
Definition typcache.h:138
#define TYPECACHE_GT_OPR
Definition typcache.h:140
#define TYPECACHE_LT_OPR
Definition typcache.h:139
#define TYPECACHE_HASH_PROC
Definition typcache.h:142