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