PostgreSQL Source Code git master
parse_oper.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_coerce.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for parse_oper.c:

Go to the source code of this file.

Data Structures

struct  OprCacheKey
 
struct  OprCacheEntry
 

Macros

#define MAX_CACHED_PATH_LEN   16
 

Typedefs

typedef struct OprCacheKey OprCacheKey
 
typedef struct OprCacheEntry OprCacheEntry
 

Functions

static Oid binary_oper_exact (List *opname, Oid arg1, Oid arg2)
 
static FuncDetailCode oper_select_candidate (int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
 
static void op_error (ParseState *pstate, List *op, Oid arg1, Oid arg2, FuncDetailCode fdresult, int fgc_flags, int location)
 
static int oper_lookup_failure_details (int fgc_flags, bool is_unary_op)
 
static bool make_oper_cache_key (ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
 
static Oid find_oper_cache_entry (OprCacheKey *key)
 
static void make_oper_cache_entry (OprCacheKey *key, Oid opr_oid)
 
static void InvalidateOprCacheCallBack (Datum arg, int cacheid, uint32 hashvalue)
 
Oid LookupOperName (ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
 
Oid LookupOperWithArgs (ObjectWithArgs *oper, bool noError)
 
void get_sort_group_operators (Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
 
Oid oprid (Operator op)
 
Oid oprfuncid (Operator op)
 
Operator oper (ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
 
Operator compatible_oper (ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
 
Oid compatible_oper_opid (List *op, Oid arg1, Oid arg2, bool noError)
 
Operator left_oper (ParseState *pstate, List *op, Oid arg, bool noError, int location)
 
const char * op_signature_string (List *op, Oid arg1, Oid arg2)
 
Exprmake_op (ParseState *pstate, List *opname, Node *ltree, Node *rtree, Node *last_srf, int location)
 
Exprmake_scalar_array_op (ParseState *pstate, List *opname, bool useOr, Node *ltree, Node *rtree, int location)
 

Variables

static HTABOprCacheHash = NULL
 

Macro Definition Documentation

◆ MAX_CACHED_PATH_LEN

#define MAX_CACHED_PATH_LEN   16

Definition at line 49 of file parse_oper.c.

Typedef Documentation

◆ OprCacheEntry

typedef struct OprCacheEntry OprCacheEntry

◆ OprCacheKey

typedef struct OprCacheKey OprCacheKey

Function Documentation

◆ binary_oper_exact()

static Oid binary_oper_exact ( List opname,
Oid  arg1,
Oid  arg2 
)
static

Definition at line 263 of file parse_oper.c.

264{
265 Oid result;
266 bool was_unknown = false;
267
268 /* Unspecified type for one of the arguments? then use the other */
269 if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
270 {
271 arg1 = arg2;
272 was_unknown = true;
273 }
274 else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
275 {
276 arg2 = arg1;
277 was_unknown = true;
278 }
279
280 result = OpernameGetOprid(opname, arg1, arg2);
281 if (OidIsValid(result))
282 return result;
283
284 if (was_unknown)
285 {
286 /* arg1 and arg2 are the same here, need only look at arg1 */
287 Oid basetype = getBaseType(arg1);
288
289 if (basetype != arg1)
290 {
291 result = OpernameGetOprid(opname, basetype, basetype);
292 if (OidIsValid(result))
293 return result;
294 }
295 }
296
297 return InvalidOid;
298}
#define OidIsValid(objectId)
Definition: c.h:774
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2688
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1832
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32

References getBaseType(), InvalidOid, OidIsValid, and OpernameGetOprid().

Referenced by oper().

◆ compatible_oper()

Operator compatible_oper ( ParseState pstate,
List op,
Oid  arg1,
Oid  arg2,
bool  noError,
int  location 
)

Definition at line 453 of file parse_oper.c.

455{
456 Operator optup;
457 Form_pg_operator opform;
458
459 /* oper() will find the best available match */
460 optup = oper(pstate, op, arg1, arg2, noError, location);
461 if (optup == (Operator) NULL)
462 return (Operator) NULL; /* must be noError case */
463
464 /* but is it good enough? */
465 opform = (Form_pg_operator) GETSTRUCT(optup);
466 if (IsBinaryCoercible(arg1, opform->oprleft) &&
467 IsBinaryCoercible(arg2, opform->oprright))
468 return optup;
469
470 /* nope... */
471 ReleaseSysCache(optup);
472
473 if (!noError)
475 (errcode(ERRCODE_UNDEFINED_FUNCTION),
476 errmsg("operator requires run-time type coercion: %s",
477 op_signature_string(op, arg1, arg2)),
478 parser_errposition(pstate, location)));
479
480 return (Operator) NULL;
481}
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
bool IsBinaryCoercible(Oid srctype, Oid targettype)
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:371
const char * op_signature_string(List *op, Oid arg1, Oid arg2)
Definition: parse_oper.c:607
FormData_pg_operator * Form_pg_operator
Definition: pg_operator.h:83
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT(), IsBinaryCoercible(), op_signature_string(), oper(), parser_errposition(), and ReleaseSysCache().

Referenced by compatible_oper_opid().

◆ compatible_oper_opid()

Oid compatible_oper_opid ( List op,
Oid  arg1,
Oid  arg2,
bool  noError 
)

Definition at line 490 of file parse_oper.c.

491{
492 Operator optup;
493 Oid result;
494
495 optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
496 if (optup != NULL)
497 {
498 result = oprid(optup);
499 ReleaseSysCache(optup);
500 return result;
501 }
502 return InvalidOid;
503}
Oid oprid(Operator op)
Definition: parse_oper.c:239
Operator compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
Definition: parse_oper.c:453

References compatible_oper(), InvalidOid, oprid(), and ReleaseSysCache().

Referenced by addTargetToSortList(), and ComputeIndexAttrs().

◆ find_oper_cache_entry()

static Oid find_oper_cache_entry ( OprCacheKey key)
static

Definition at line 1024 of file parse_oper.c.

1025{
1026 OprCacheEntry *oprentry;
1027
1028 if (OprCacheHash == NULL)
1029 {
1030 /* First time through: initialize the hash table */
1031 HASHCTL ctl;
1032
1033 ctl.keysize = sizeof(OprCacheKey);
1034 ctl.entrysize = sizeof(OprCacheEntry);
1035 OprCacheHash = hash_create("Operator lookup cache", 256,
1037
1038 /* Arrange to flush cache on pg_operator and pg_cast changes */
1041 (Datum) 0);
1042 CacheRegisterSyscacheCallback(CASTSOURCETARGET,
1044 (Datum) 0);
1045 }
1046
1047 /* Look for an existing entry */
1048 oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
1049 key,
1050 HASH_FIND, NULL);
1051 if (oprentry == NULL)
1052 return InvalidOid;
1053
1054 return oprentry->opr_oid;
1055}
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
@ HASH_FIND
Definition: hsearch.h:113
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1812
static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: parse_oper.c:1079
static HTAB * OprCacheHash
Definition: parse_oper.c:966
struct OprCacheEntry OprCacheEntry
struct OprCacheKey OprCacheKey
uint64_t Datum
Definition: postgres.h:70
tree ctl
Definition: radixtree.h:1838

References CacheRegisterSyscacheCallback(), ctl, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_FIND, hash_search(), InvalidateOprCacheCallBack(), InvalidOid, sort-test::key, OprCacheEntry::opr_oid, and OprCacheHash.

Referenced by left_oper(), and oper().

◆ get_sort_group_operators()

void get_sort_group_operators ( Oid  argtype,
bool  needLT,
bool  needEQ,
bool  needGT,
Oid ltOpr,
Oid eqOpr,
Oid gtOpr,
bool *  isHashable 
)

Definition at line 181 of file parse_oper.c.

185{
186 TypeCacheEntry *typentry;
187 int cache_flags;
188 Oid lt_opr;
189 Oid eq_opr;
190 Oid gt_opr;
191 bool hashable;
192
193 /*
194 * Look up the operators using the type cache.
195 *
196 * Note: the search algorithm used by typcache.c ensures that the results
197 * are consistent, ie all from matching opclasses.
198 */
199 if (isHashable != NULL)
202 else
204
205 typentry = lookup_type_cache(argtype, cache_flags);
206 lt_opr = typentry->lt_opr;
207 eq_opr = typentry->eq_opr;
208 gt_opr = typentry->gt_opr;
209 hashable = OidIsValid(typentry->hash_proc);
210
211 /* Report errors if needed */
212 if ((needLT && !OidIsValid(lt_opr)) ||
213 (needGT && !OidIsValid(gt_opr)))
215 (errcode(ERRCODE_UNDEFINED_FUNCTION),
216 errmsg("could not identify an ordering operator for type %s",
217 format_type_be(argtype)),
218 errhint("Use an explicit ordering operator or modify the query.")));
219 if (needEQ && !OidIsValid(eq_opr))
221 (errcode(ERRCODE_UNDEFINED_FUNCTION),
222 errmsg("could not identify an equality operator for type %s",
223 format_type_be(argtype))));
224
225 /* Return results as needed */
226 if (ltOpr)
227 *ltOpr = lt_opr;
228 if (eqOpr)
229 *eqOpr = eq_opr;
230 if (gtOpr)
231 *gtOpr = gt_opr;
232 if (isHashable)
233 *isHashable = hashable;
234}
int errhint(const char *fmt,...)
Definition: elog.c:1330
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#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

References TypeCacheEntry::eq_opr, ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), TypeCacheEntry::gt_opr, TypeCacheEntry::hash_proc, lookup_type_cache(), TypeCacheEntry::lt_opr, OidIsValid, TYPECACHE_EQ_OPR, TYPECACHE_GT_OPR, TYPECACHE_HASH_PROC, and TYPECACHE_LT_OPR.

Referenced by addTargetToGroupList(), addTargetToSortList(), init_grouping_targets(), makeSortGroupClauseForSetOp(), and std_typanalyze().

◆ InvalidateOprCacheCallBack()

static void InvalidateOprCacheCallBack ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 1079 of file parse_oper.c.

1080{
1081 HASH_SEQ_STATUS status;
1082 OprCacheEntry *hentry;
1083
1084 Assert(OprCacheHash != NULL);
1085
1086 /* Currently we just flush all entries; hard to be smarter ... */
1087 hash_seq_init(&status, OprCacheHash);
1088
1089 while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
1090 {
1092 &hentry->key,
1093 HASH_REMOVE, NULL) == NULL)
1094 elog(ERROR, "hash table corrupted");
1095 }
1096}
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
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
@ HASH_REMOVE
Definition: hsearch.h:115
OprCacheKey key
Definition: parse_oper.c:62

References Assert(), elog, ERROR, HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), OprCacheEntry::key, and OprCacheHash.

Referenced by find_oper_cache_entry().

◆ left_oper()

Operator left_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)

Definition at line 521 of file parse_oper.c.

522{
523 Oid operOid;
525 bool key_ok;
526 int fgc_flags = 0;
528 HeapTuple tup = NULL;
529
530 /*
531 * Try to find the mapping in the lookaside cache.
532 */
533 key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
534
535 if (key_ok)
536 {
537 operOid = find_oper_cache_entry(&key);
538 if (OidIsValid(operOid))
539 {
540 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
541 if (HeapTupleIsValid(tup))
542 return (Operator) tup;
543 }
544 }
545
546 /*
547 * First try for an "exact" match.
548 */
549 operOid = OpernameGetOprid(op, InvalidOid, arg);
550 if (!OidIsValid(operOid))
551 {
552 /*
553 * Otherwise, search for the most suitable candidate.
554 */
555 FuncCandidateList clist;
556
557 /* Get prefix operators of given name */
558 clist = OpernameGetCandidates(op, 'l', false, &fgc_flags);
559
560 /* No operators found? Then fail... */
561 if (clist != NULL)
562 {
563 /*
564 * The returned list has args in the form (0, oprright). Move the
565 * useful data into args[0] to keep oper_select_candidate simple.
566 * XXX we are assuming here that we may scribble on the list!
567 */
568 FuncCandidateList clisti;
569
570 for (clisti = clist; clisti != NULL; clisti = clisti->next)
571 {
572 clisti->args[0] = clisti->args[1];
573 }
574
575 /*
576 * We must run oper_select_candidate even if only one candidate,
577 * otherwise we may falsely return a non-type-compatible operator.
578 */
579 fdresult = oper_select_candidate(1, &arg, clist, &operOid);
580 }
581 }
582
583 if (OidIsValid(operOid))
584 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
585
586 if (HeapTupleIsValid(tup))
587 {
588 if (key_ok)
589 make_oper_cache_entry(&key, operOid);
590 }
591 else if (!noError)
592 op_error(pstate, op, InvalidOid, arg,
593 fdresult, fgc_flags, location);
594
595 return (Operator) tup;
596}
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok, int *fgc_flags)
Definition: namespace.c:1945
FuncDetailCode
Definition: parse_func.h:23
@ FUNCDETAIL_NOTFOUND
Definition: parse_func.h:24
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
Definition: parse_oper.c:1063
static FuncDetailCode oper_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
Definition: parse_oper.c:313
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
Definition: parse_oper.c:980
static void op_error(ParseState *pstate, List *op, Oid arg1, Oid arg2, FuncDetailCode fdresult, int fgc_flags, int location)
Definition: parse_oper.c:627
static Oid find_oper_cache_entry(OprCacheKey *key)
Definition: parse_oper.c:1024
void * arg
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
struct _FuncCandidateList * next
Definition: namespace.h:31
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition: namespace.h:39
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220

References arg, _FuncCandidateList::args, find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, sort-test::key, make_oper_cache_entry(), make_oper_cache_key(), _FuncCandidateList::next, ObjectIdGetDatum(), OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), and SearchSysCache1().

Referenced by generate_operator_name(), and make_op().

◆ LookupOperName()

Oid LookupOperName ( ParseState pstate,
List opername,
Oid  oprleft,
Oid  oprright,
bool  noError,
int  location 
)

Definition at line 100 of file parse_oper.c.

102{
103 Oid result;
104
105 result = OpernameGetOprid(opername, oprleft, oprright);
106 if (OidIsValid(result))
107 return result;
108
109 /* we don't use op_error here because only an exact match is wanted */
110 if (!noError)
111 {
112 if (!OidIsValid(oprright))
114 (errcode(ERRCODE_SYNTAX_ERROR),
115 errmsg("postfix operators are not supported"),
116 parser_errposition(pstate, location)));
117
119 (errcode(ERRCODE_UNDEFINED_FUNCTION),
120 errmsg("operator does not exist: %s",
121 op_signature_string(opername, oprleft, oprright)),
122 parser_errposition(pstate, location)));
123 }
124
125 return InvalidOid;
126}

References ereport, errcode(), errmsg(), ERROR, InvalidOid, OidIsValid, op_signature_string(), OpernameGetOprid(), and parser_errposition().

Referenced by AggregateCreate(), DefineOpClass(), LookupOperWithArgs(), and OperatorLookup().

◆ LookupOperWithArgs()

Oid LookupOperWithArgs ( ObjectWithArgs oper,
bool  noError 
)

Definition at line 134 of file parse_oper.c.

135{
136 TypeName *oprleft,
137 *oprright;
138 Oid leftoid,
139 rightoid;
140
141 Assert(list_length(oper->objargs) == 2);
142 oprleft = linitial_node(TypeName, oper->objargs);
143 oprright = lsecond_node(TypeName, oper->objargs);
144
145 if (oprleft == NULL)
146 leftoid = InvalidOid;
147 else
148 leftoid = LookupTypeNameOid(NULL, oprleft, noError);
149
150 if (oprright == NULL)
151 rightoid = InvalidOid;
152 else
153 rightoid = LookupTypeNameOid(NULL, oprright, noError);
154
155 return LookupOperName(NULL, oper->objname, leftoid, rightoid,
156 noError, -1);
157}
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition: parse_oper.c:100
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition: parse_type.c:232
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

References Assert(), InvalidOid, linitial_node, list_length(), LookupOperName(), LookupTypeNameOid(), lsecond_node, and oper().

Referenced by AlterOperator(), AlterOpFamilyAdd(), DefineOpClass(), and get_object_address().

◆ make_op()

Expr * make_op ( ParseState pstate,
List opname,
Node ltree,
Node rtree,
Node last_srf,
int  location 
)

Definition at line 703 of file parse_oper.c.

705{
706 Oid ltypeId,
707 rtypeId;
708 Operator tup;
709 Form_pg_operator opform;
710 Oid actual_arg_types[2];
711 Oid declared_arg_types[2];
712 int nargs;
713 List *args;
714 Oid rettype;
715 OpExpr *result;
716
717 /* Check it's not a postfix operator */
718 if (rtree == NULL)
720 (errcode(ERRCODE_SYNTAX_ERROR),
721 errmsg("postfix operators are not supported")));
722
723 /* Select the operator */
724 if (ltree == NULL)
725 {
726 /* prefix operator */
727 rtypeId = exprType(rtree);
728 ltypeId = InvalidOid;
729 tup = left_oper(pstate, opname, rtypeId, false, location);
730 }
731 else
732 {
733 /* otherwise, binary operator */
734 ltypeId = exprType(ltree);
735 rtypeId = exprType(rtree);
736 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
737 }
738
739 opform = (Form_pg_operator) GETSTRUCT(tup);
740
741 /* Check it's not a shell */
742 if (!RegProcedureIsValid(opform->oprcode))
744 (errcode(ERRCODE_UNDEFINED_FUNCTION),
745 errmsg("operator is only a shell: %s",
746 op_signature_string(opname,
747 opform->oprleft,
748 opform->oprright)),
749 parser_errposition(pstate, location)));
750
751 /* Do typecasting and build the expression tree */
752 if (ltree == NULL)
753 {
754 /* prefix operator */
755 args = list_make1(rtree);
756 actual_arg_types[0] = rtypeId;
757 declared_arg_types[0] = opform->oprright;
758 nargs = 1;
759 }
760 else
761 {
762 /* otherwise, binary operator */
763 args = list_make2(ltree, rtree);
764 actual_arg_types[0] = ltypeId;
765 actual_arg_types[1] = rtypeId;
766 declared_arg_types[0] = opform->oprleft;
767 declared_arg_types[1] = opform->oprright;
768 nargs = 2;
769 }
770
771 /*
772 * enforce consistency with polymorphic argument and return types,
773 * possibly adjusting return type or declared_arg_types (which will be
774 * used as the cast destination by make_fn_arguments)
775 */
776 rettype = enforce_generic_type_consistency(actual_arg_types,
777 declared_arg_types,
778 nargs,
779 opform->oprresult,
780 false);
781
782 /* perform the necessary typecasting of arguments */
783 make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
784
785 /* and build the expression node */
786 result = makeNode(OpExpr);
787 result->opno = oprid(tup);
788 result->opfuncid = opform->oprcode;
789 result->opresulttype = rettype;
790 result->opretset = get_func_retset(opform->oprcode);
791 /* opcollid and inputcollid will be set by parse_collate.c */
792 result->args = args;
793 result->location = location;
794
795 /* if it returns a set, check that's OK */
796 if (result->opretset)
797 {
798 check_srf_call_placement(pstate, last_srf, location);
799 /* ... and remember it for error checks at higher levels */
800 pstate->p_last_srf = (Node *) result;
801 }
802
803 ReleaseSysCache(tup);
804
805 return (Expr *) result;
806}
#define RegProcedureIsValid(p)
Definition: c.h:776
bool get_func_retset(Oid funcid)
Definition: lsyscache.c:1909
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)
void make_fn_arguments(ParseState *pstate, List *fargs, Oid *actual_arg_types, Oid *declared_arg_types)
Definition: parse_func.c:1948
void check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
Definition: parse_func.c:2636
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:521
#define list_make1(x1)
Definition: pg_list.h:212
#define list_make2(x1, x2)
Definition: pg_list.h:214
Definition: pg_list.h:54
Definition: nodes.h:135
Oid opno
Definition: primnodes.h:850
List * args
Definition: primnodes.h:868
ParseLoc location
Definition: primnodes.h:871
Node * p_last_srf
Definition: parse_node.h:232
Definition: ltree.h:43

References generate_unaccent_rules::args, OpExpr::args, check_srf_call_placement(), enforce_generic_type_consistency(), ereport, errcode(), errmsg(), ERROR, exprType(), get_func_retset(), GETSTRUCT(), InvalidOid, left_oper(), list_make1, list_make2, OpExpr::location, make_fn_arguments(), makeNode, op_signature_string(), oper(), OpExpr::opno, oprid(), ParseState::p_last_srf, parser_errposition(), RegProcedureIsValid, and ReleaseSysCache().

Referenced by make_distinct_op(), make_row_comparison_op(), transformAExprIn(), transformAExprNullIf(), and transformAExprOp().

◆ make_oper_cache_entry()

static void make_oper_cache_entry ( OprCacheKey key,
Oid  opr_oid 
)
static

Definition at line 1063 of file parse_oper.c.

1064{
1065 OprCacheEntry *oprentry;
1066
1067 Assert(OprCacheHash != NULL);
1068
1069 oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
1070 key,
1071 HASH_ENTER, NULL);
1072 oprentry->opr_oid = opr_oid;
1073}
@ HASH_ENTER
Definition: hsearch.h:114

References Assert(), HASH_ENTER, hash_search(), sort-test::key, OprCacheEntry::opr_oid, and OprCacheHash.

Referenced by left_oper(), and oper().

◆ make_oper_cache_key()

static bool make_oper_cache_key ( ParseState pstate,
OprCacheKey key,
List opname,
Oid  ltypeId,
Oid  rtypeId,
int  location 
)
static

Definition at line 980 of file parse_oper.c.

982{
983 char *schemaname;
984 char *opername;
985
986 /* deconstruct the name list */
987 DeconstructQualifiedName(opname, &schemaname, &opername);
988
989 /* ensure zero-fill for stable hashing */
990 MemSet(key, 0, sizeof(OprCacheKey));
991
992 /* save operator name and input types into key */
993 strlcpy(key->oprname, opername, NAMEDATALEN);
994 key->left_arg = ltypeId;
995 key->right_arg = rtypeId;
996
997 if (schemaname)
998 {
999 ParseCallbackState pcbstate;
1000
1001 /* search only in exact schema given */
1002 setup_parser_errposition_callback(&pcbstate, pstate, location);
1003 key->search_path[0] = LookupExplicitNamespace(schemaname, false);
1005 }
1006 else
1007 {
1008 /* get the active search path */
1009 if (fetch_search_path_array(key->search_path,
1011 return false; /* oops, didn't fit */
1012 }
1013
1014 return true;
1015}
#define MemSet(start, val, len)
Definition: c.h:1019
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:3455
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:3371
int fetch_search_path_array(Oid *sarray, int sarray_len)
Definition: namespace.c:4929
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:156
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition: parse_node.c:140
#define MAX_CACHED_PATH_LEN
Definition: parse_oper.c:49
#define NAMEDATALEN
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45

References cancel_parser_errposition_callback(), DeconstructQualifiedName(), fetch_search_path_array(), sort-test::key, LookupExplicitNamespace(), MAX_CACHED_PATH_LEN, MemSet, NAMEDATALEN, setup_parser_errposition_callback(), and strlcpy().

Referenced by left_oper(), and oper().

◆ make_scalar_array_op()

Expr * make_scalar_array_op ( ParseState pstate,
List opname,
bool  useOr,
Node ltree,
Node rtree,
int  location 
)

Definition at line 813 of file parse_oper.c.

817{
818 Oid ltypeId,
819 rtypeId,
820 atypeId,
821 res_atypeId;
822 Operator tup;
823 Form_pg_operator opform;
824 Oid actual_arg_types[2];
825 Oid declared_arg_types[2];
826 List *args;
827 Oid rettype;
828 ScalarArrayOpExpr *result;
829
830 ltypeId = exprType(ltree);
831 atypeId = exprType(rtree);
832
833 /*
834 * The right-hand input of the operator will be the element type of the
835 * array. However, if we currently have just an untyped literal on the
836 * right, stay with that and hope we can resolve the operator.
837 */
838 if (atypeId == UNKNOWNOID)
839 rtypeId = UNKNOWNOID;
840 else
841 {
842 rtypeId = get_base_element_type(atypeId);
843 if (!OidIsValid(rtypeId))
845 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
846 errmsg("op ANY/ALL (array) requires array on right side"),
847 parser_errposition(pstate, location)));
848 }
849
850 /* Now resolve the operator */
851 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
852 opform = (Form_pg_operator) GETSTRUCT(tup);
853
854 /* Check it's not a shell */
855 if (!RegProcedureIsValid(opform->oprcode))
857 (errcode(ERRCODE_UNDEFINED_FUNCTION),
858 errmsg("operator is only a shell: %s",
859 op_signature_string(opname,
860 opform->oprleft,
861 opform->oprright)),
862 parser_errposition(pstate, location)));
863
864 args = list_make2(ltree, rtree);
865 actual_arg_types[0] = ltypeId;
866 actual_arg_types[1] = rtypeId;
867 declared_arg_types[0] = opform->oprleft;
868 declared_arg_types[1] = opform->oprright;
869
870 /*
871 * enforce consistency with polymorphic argument and return types,
872 * possibly adjusting return type or declared_arg_types (which will be
873 * used as the cast destination by make_fn_arguments)
874 */
875 rettype = enforce_generic_type_consistency(actual_arg_types,
876 declared_arg_types,
877 2,
878 opform->oprresult,
879 false);
880
881 /*
882 * Check that operator result is boolean
883 */
884 if (rettype != BOOLOID)
886 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
887 errmsg("op ANY/ALL (array) requires operator to yield boolean"),
888 parser_errposition(pstate, location)));
889 if (get_func_retset(opform->oprcode))
891 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
892 errmsg("op ANY/ALL (array) requires operator not to return a set"),
893 parser_errposition(pstate, location)));
894
895 /*
896 * Now switch back to the array type on the right, arranging for any
897 * needed cast to be applied. Beware of polymorphic operators here;
898 * enforce_generic_type_consistency may or may not have replaced a
899 * polymorphic type with a real one.
900 */
901 if (IsPolymorphicType(declared_arg_types[1]))
902 {
903 /* assume the actual array type is OK */
904 res_atypeId = atypeId;
905 }
906 else
907 {
908 res_atypeId = get_array_type(declared_arg_types[1]);
909 if (!OidIsValid(res_atypeId))
911 (errcode(ERRCODE_UNDEFINED_OBJECT),
912 errmsg("could not find array type for data type %s",
913 format_type_be(declared_arg_types[1])),
914 parser_errposition(pstate, location)));
915 }
916 actual_arg_types[1] = atypeId;
917 declared_arg_types[1] = res_atypeId;
918
919 /* perform the necessary typecasting of arguments */
920 make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
921
922 /* and build the expression node */
923 result = makeNode(ScalarArrayOpExpr);
924 result->opno = oprid(tup);
925 result->opfuncid = opform->oprcode;
926 result->hashfuncid = InvalidOid;
927 result->negfuncid = InvalidOid;
928 result->useOr = useOr;
929 /* inputcollid will be set by parse_collate.c */
930 result->args = args;
931 result->location = location;
932
933 ReleaseSysCache(tup);
934
935 return (Expr *) result;
936}
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2999
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2954
ParseLoc location
Definition: primnodes.h:951

References generate_unaccent_rules::args, ScalarArrayOpExpr::args, enforce_generic_type_consistency(), ereport, errcode(), errmsg(), ERROR, exprType(), format_type_be(), get_array_type(), get_base_element_type(), get_func_retset(), GETSTRUCT(), InvalidOid, list_make2, ScalarArrayOpExpr::location, make_fn_arguments(), makeNode, OidIsValid, op_signature_string(), oper(), ScalarArrayOpExpr::opno, oprid(), parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and ScalarArrayOpExpr::useOr.

Referenced by transformAExprIn(), transformAExprOpAll(), and transformAExprOpAny().

◆ op_error()

static void op_error ( ParseState pstate,
List op,
Oid  arg1,
Oid  arg2,
FuncDetailCode  fdresult,
int  fgc_flags,
int  location 
)
static

Definition at line 627 of file parse_oper.c.

630{
631 if (fdresult == FUNCDETAIL_MULTIPLE)
633 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
634 errmsg("operator is not unique: %s",
635 op_signature_string(op, arg1, arg2)),
636 errdetail("Could not choose a best candidate operator."),
637 errhint("You might need to add explicit type casts."),
638 parser_errposition(pstate, location)));
639 else
641 (errcode(ERRCODE_UNDEFINED_FUNCTION),
642 errmsg("operator does not exist: %s",
643 op_signature_string(op, arg1, arg2)),
644 oper_lookup_failure_details(fgc_flags, (!arg1 || !arg2)),
645 parser_errposition(pstate, location)));
646}
int errdetail(const char *fmt,...)
Definition: elog.c:1216
@ FUNCDETAIL_MULTIPLE
Definition: parse_func.h:25
static int oper_lookup_failure_details(int fgc_flags, bool is_unary_op)
Definition: parse_oper.c:652

References ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, FUNCDETAIL_MULTIPLE, op_signature_string(), oper_lookup_failure_details(), and parser_errposition().

Referenced by left_oper(), and oper().

◆ op_signature_string()

const char * op_signature_string ( List op,
Oid  arg1,
Oid  arg2 
)

Definition at line 607 of file parse_oper.c.

608{
609 StringInfoData argbuf;
610
611 initStringInfo(&argbuf);
612
613 if (OidIsValid(arg1))
614 appendStringInfo(&argbuf, "%s ", format_type_be(arg1));
615
617
618 appendStringInfo(&argbuf, " %s", format_type_be(arg2));
619
620 return argbuf.data; /* return palloc'd string buffer */
621}
char * NameListToString(const List *names)
Definition: namespace.c:3664
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

References appendStringInfo(), appendStringInfoString(), StringInfoData::data, format_type_be(), initStringInfo(), NameListToString(), and OidIsValid.

Referenced by compatible_oper(), LookupOperName(), make_op(), make_scalar_array_op(), op_error(), and ValidateOperatorReference().

◆ oper()

Operator oper ( ParseState pstate,
List opname,
Oid  ltypeId,
Oid  rtypeId,
bool  noError,
int  location 
)

Definition at line 371 of file parse_oper.c.

373{
374 Oid operOid;
376 bool key_ok;
377 int fgc_flags = 0;
379 HeapTuple tup = NULL;
380
381 /*
382 * Try to find the mapping in the lookaside cache.
383 */
384 key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
385
386 if (key_ok)
387 {
388 operOid = find_oper_cache_entry(&key);
389 if (OidIsValid(operOid))
390 {
391 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
392 if (HeapTupleIsValid(tup))
393 return (Operator) tup;
394 }
395 }
396
397 /*
398 * First try for an "exact" match.
399 */
400 operOid = binary_oper_exact(opname, ltypeId, rtypeId);
401 if (!OidIsValid(operOid))
402 {
403 /*
404 * Otherwise, search for the most suitable candidate.
405 */
406 FuncCandidateList clist;
407
408 /* Get binary operators of given name */
409 clist = OpernameGetCandidates(opname, 'b', false, &fgc_flags);
410
411 /* No operators found? Then fail... */
412 if (clist != NULL)
413 {
414 /*
415 * Unspecified type for one of the arguments? then use the other
416 * (XXX this is probably dead code?)
417 */
418 Oid inputOids[2];
419
420 if (rtypeId == InvalidOid)
421 rtypeId = ltypeId;
422 else if (ltypeId == InvalidOid)
423 ltypeId = rtypeId;
424 inputOids[0] = ltypeId;
425 inputOids[1] = rtypeId;
426 fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
427 }
428 }
429
430 if (OidIsValid(operOid))
431 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
432
433 if (HeapTupleIsValid(tup))
434 {
435 if (key_ok)
436 make_oper_cache_entry(&key, operOid);
437 }
438 else if (!noError)
439 op_error(pstate, opname, ltypeId, rtypeId,
440 fdresult, fgc_flags, location);
441
442 return (Operator) tup;
443}
static Oid binary_oper_exact(List *opname, Oid arg1, Oid arg2)
Definition: parse_oper.c:263

References binary_oper_exact(), find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, sort-test::key, make_oper_cache_entry(), make_oper_cache_key(), ObjectIdGetDatum(), OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), and SearchSysCache1().

Referenced by compatible_oper(), Do_MultiXactIdWait(), generate_operator_name(), LookupOperWithArgs(), make_op(), make_SAOP_expr(), make_scalar_array_op(), makeOperatorDependencies(), multi_sort_add_dimension(), MultiXactIdWait(), pushOperator(), tsquery_opr_selec(), tsqueryrecv(), and XactLockTableWait().

◆ oper_lookup_failure_details()

static int oper_lookup_failure_details ( int  fgc_flags,
bool  is_unary_op 
)
static

Definition at line 652 of file parse_oper.c.

653{
654 /*
655 * If not FGC_NAME_VISIBLE, we shouldn't raise the question of whether the
656 * arguments are wrong. If the operator name was not schema-qualified,
657 * it's helpful to distinguish between doesn't-exist-anywhere and
658 * not-in-search-path; but if it was, there's really nothing to add to the
659 * basic "operator does not exist" message.
660 *
661 * Note: we passed missing_ok = false to OpernameGetCandidates, so there's
662 * no need to consider FGC_SCHEMA_EXISTS here: we'd have already thrown an
663 * error if an explicitly-given schema doesn't exist.
664 */
665 if (!(fgc_flags & FGC_NAME_VISIBLE))
666 {
667 if (fgc_flags & FGC_SCHEMA_GIVEN)
668 return 0; /* schema-qualified name */
669 else if (!(fgc_flags & FGC_NAME_EXISTS))
670 return errdetail("There is no operator of that name.");
671 else
672 return errdetail("An operator of that name exists, but it is not in the search_path.");
673 }
674
675 /*
676 * Otherwise, the problem must be incorrect argument type(s).
677 */
678 if (is_unary_op)
679 {
680 (void) errdetail("No operator of that name accepts the given argument type.");
681 return errhint("You might need to add an explicit type cast.");
682 }
683 else
684 {
685 (void) errdetail("No operator of that name accepts the given argument types.");
686 return errhint("You might need to add explicit type casts.");
687 }
688}
#define FGC_NAME_EXISTS
Definition: namespace.h:49
#define FGC_SCHEMA_GIVEN
Definition: namespace.h:47
#define FGC_NAME_VISIBLE
Definition: namespace.h:50

References errdetail(), errhint(), FGC_NAME_EXISTS, FGC_NAME_VISIBLE, and FGC_SCHEMA_GIVEN.

Referenced by op_error().

◆ oper_select_candidate()

static FuncDetailCode oper_select_candidate ( int  nargs,
Oid input_typeids,
FuncCandidateList  candidates,
Oid operOid 
)
static

Definition at line 313 of file parse_oper.c.

317{
318 int ncandidates;
319
320 /*
321 * Delete any candidates that cannot actually accept the given input
322 * types, whether directly or by coercion.
323 */
324 ncandidates = func_match_argtypes(nargs, input_typeids,
325 candidates, &candidates);
326
327 /* Done if no candidate or only one candidate survives */
328 if (ncandidates == 0)
329 {
330 *operOid = InvalidOid;
331 return FUNCDETAIL_NOTFOUND;
332 }
333 if (ncandidates == 1)
334 {
335 *operOid = candidates->oid;
336 return FUNCDETAIL_NORMAL;
337 }
338
339 /*
340 * Use the same heuristics as for ambiguous functions to resolve the
341 * conflict.
342 */
343 candidates = func_select_candidate(nargs, input_typeids, candidates);
344
345 if (candidates)
346 {
347 *operOid = candidates->oid;
348 return FUNCDETAIL_NORMAL;
349 }
350
351 *operOid = InvalidOid;
352 return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
353}
FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates)
Definition: parse_func.c:1121
int func_match_argtypes(int nargs, Oid *input_typeids, FuncCandidateList raw_candidates, FuncCandidateList *candidates)
Definition: parse_func.c:1036
@ FUNCDETAIL_NORMAL
Definition: parse_func.h:26

References func_match_argtypes(), func_select_candidate(), FUNCDETAIL_MULTIPLE, FUNCDETAIL_NORMAL, FUNCDETAIL_NOTFOUND, InvalidOid, and _FuncCandidateList::oid.

Referenced by left_oper(), and oper().

◆ oprfuncid()

Oid oprfuncid ( Operator  op)

Definition at line 246 of file parse_oper.c.

247{
249
250 return pgopform->oprcode;
251}

References GETSTRUCT().

◆ oprid()

Variable Documentation

◆ OprCacheHash

HTAB* OprCacheHash = NULL
static