PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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/hsearch.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, SysCacheIdentifier 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 charop_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 50 of file parse_oper.c.

Typedef Documentation

◆ OprCacheEntry

◆ OprCacheKey

Function Documentation

◆ binary_oper_exact()

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

Definition at line 265 of file parse_oper.c.

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

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

Referenced by oper().

◆ compatible_oper()

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

Definition at line 455 of file parse_oper.c.

457{
460
461 /* oper() will find the best available match */
462 optup = oper(pstate, op, arg1, arg2, noError, location);
463 if (optup == (Operator) NULL)
464 return (Operator) NULL; /* must be noError case */
465
466 /* but is it good enough? */
468 if (IsBinaryCoercible(arg1, opform->oprleft) &&
469 IsBinaryCoercible(arg2, opform->oprright))
470 return optup;
471
472 /* nope... */
474
475 if (!noError)
478 errmsg("operator requires run-time type coercion: %s",
480 parser_errposition(pstate, location)));
481
482 return (Operator) NULL;
483}
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
static void * GETSTRUCT(const HeapTupleData *tuple)
static char * errmsg
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:373
const char * op_signature_string(List *op, Oid arg1, Oid arg2)
Definition parse_oper.c:609
END_CATALOG_STRUCT typedef FormData_pg_operator * Form_pg_operator
Definition pg_operator.h:87
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265

References ereport, errcode(), errmsg, ERROR, fb(), Form_pg_operator, 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 492 of file parse_oper.c.

493{
495 Oid result;
496
498 if (optup != NULL)
499 {
500 result = oprid(optup);
502 return result;
503 }
504 return InvalidOid;
505}
Oid oprid(Operator op)
Definition parse_oper.c:241
Operator compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
Definition parse_oper.c:455

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

Referenced by addTargetToSortList(), and ComputeIndexAttrs().

◆ find_oper_cache_entry()

static Oid find_oper_cache_entry ( OprCacheKey key)
static

Definition at line 1026 of file parse_oper.c.

1027{
1029
1030 if (OprCacheHash == NULL)
1031 {
1032 /* First time through: initialize the hash table */
1033 HASHCTL ctl;
1034
1035 ctl.keysize = sizeof(OprCacheKey);
1036 ctl.entrysize = sizeof(OprCacheEntry);
1037 OprCacheHash = hash_create("Operator lookup cache", 256,
1039
1040 /* Arrange to flush cache on pg_operator and pg_cast changes */
1043 (Datum) 0);
1046 (Datum) 0);
1047 }
1048
1049 /* Look for an existing entry */
1051 key,
1052 HASH_FIND, NULL);
1053 if (oprentry == NULL)
1054 return InvalidOid;
1055
1056 return oprentry->opr_oid;
1057}
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
@ HASH_FIND
Definition hsearch.h:108
#define HASH_ELEM
Definition hsearch.h:90
#define HASH_BLOBS
Definition hsearch.h:92
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1816
static void InvalidateOprCacheCallBack(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
static HTAB * OprCacheHash
Definition parse_oper.c:968
uint64_t Datum
Definition postgres.h:70
tree ctl
Definition radixtree.h:1838
Size keysize
Definition hsearch.h:69

References CacheRegisterSyscacheCallback(), ctl, fb(), HASH_BLOBS, hash_create(), HASH_ELEM, HASH_FIND, hash_search(), InvalidateOprCacheCallBack(), InvalidOid, HASHCTL::keysize, 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 183 of file parse_oper.c.

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}
int errhint(const char *fmt,...) pg_attribute_printf(1
char * format_type_be(Oid type_oid)
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

References TypeCacheEntry::eq_opr, ereport, errcode(), errhint(), errmsg, ERROR, fb(), 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,
SysCacheIdentifier  cacheid,
uint32  hashvalue 
)
static

Definition at line 1081 of file parse_oper.c.

1083{
1084 HASH_SEQ_STATUS status;
1086
1088
1089 /* Currently we just flush all entries; hard to be smarter ... */
1090 hash_seq_init(&status, OprCacheHash);
1091
1092 while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
1093 {
1095 &hentry->key,
1096 HASH_REMOVE, NULL) == NULL)
1097 elog(ERROR, "hash table corrupted");
1098 }
1099}
#define Assert(condition)
Definition c.h:943
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
#define elog(elevel,...)
Definition elog.h:228
@ HASH_REMOVE
Definition hsearch.h:110

References Assert, elog, ERROR, fb(), HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), 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 523 of file parse_oper.c.

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

References arg, _FuncCandidateList::args, fb(), find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), 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 102 of file parse_oper.c.

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}

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

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

◆ LookupOperWithArgs()

Oid LookupOperWithArgs ( ObjectWithArgs oper,
bool  noError 
)

Definition at line 136 of file parse_oper.c.

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}
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition parse_oper.c:102
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, fb(), 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 705 of file parse_oper.c.

707{
708 Oid ltypeId,
709 rtypeId;
714 int nargs;
715 List *args;
716 Oid rettype;
717 OpExpr *result;
718
719 /* Check it's not a postfix operator */
720 if (rtree == NULL)
723 errmsg("postfix operators are not supported")));
724
725 /* Select the operator */
726 if (ltree == NULL)
727 {
728 /* prefix operator */
731 tup = left_oper(pstate, opname, rtypeId, false, location);
732 }
733 else
734 {
735 /* otherwise, binary operator */
738 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
739 }
740
742
743 /* Check it's not a shell */
744 if (!RegProcedureIsValid(opform->oprcode))
747 errmsg("operator is only a shell: %s",
749 opform->oprleft,
750 opform->oprright)),
751 parser_errposition(pstate, location)));
752
753 /* Do typecasting and build the expression tree */
754 if (ltree == NULL)
755 {
756 /* prefix operator */
759 declared_arg_types[0] = opform->oprright;
760 nargs = 1;
761 }
762 else
763 {
764 /* otherwise, binary operator */
768 declared_arg_types[0] = opform->oprleft;
769 declared_arg_types[1] = opform->oprright;
770 nargs = 2;
771 }
772
773 /*
774 * enforce consistency with polymorphic argument and return types,
775 * possibly adjusting return type or declared_arg_types (which will be
776 * used as the cast destination by make_fn_arguments)
777 */
780 nargs,
781 opform->oprresult,
782 false);
783
784 /* perform the necessary typecasting of arguments */
786
787 /* and build the expression node */
789 result->opno = oprid(tup);
790 result->opfuncid = opform->oprcode;
791 result->opresulttype = rettype;
792 result->opretset = get_func_retset(opform->oprcode);
793 /* opcollid and inputcollid will be set by parse_collate.c */
794 result->args = args;
795 result->location = location;
796
797 /* if it returns a set, check that's OK */
798 if (result->opretset)
799 {
800 check_srf_call_placement(pstate, last_srf, location);
801 /* ... and remember it for error checks at higher levels */
802 pstate->p_last_srf = (Node *) result;
803 }
804
806
807 return (Expr *) result;
808}
#define RegProcedureIsValid(p)
Definition c.h:862
bool get_func_retset(Oid funcid)
Definition lsyscache.c:1962
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)
void check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition parse_oper.c:523
#define list_make1(x1)
Definition pg_list.h:244
#define list_make2(x1, x2)
Definition pg_list.h:246
Definition pg_list.h:54
Definition nodes.h:135
Node * p_last_srf
Definition parse_node.h:252
Definition ltree.h:43

References check_srf_call_placement(), enforce_generic_type_consistency(), ereport, errcode(), errmsg, ERROR, exprType(), fb(), Form_pg_operator, get_func_retset(), GETSTRUCT(), InvalidOid, left_oper(), list_make1, list_make2, make_fn_arguments(), makeNode, op_signature_string(), oper(), oprid(), ParseState::p_last_srf, parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and result.

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 1065 of file parse_oper.c.

1066{
1068
1070
1072 key,
1073 HASH_ENTER, NULL);
1074 oprentry->opr_oid = opr_oid;
1075}
@ HASH_ENTER
Definition hsearch.h:109

References Assert, fb(), HASH_ENTER, hash_search(), 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 982 of file parse_oper.c.

984{
985 char *schemaname;
986 char *opername;
987
988 /* deconstruct the name list */
989 DeconstructQualifiedName(opname, &schemaname, &opername);
990
991 /* ensure zero-fill for stable hashing */
992 MemSet(key, 0, sizeof(OprCacheKey));
993
994 /* save operator name and input types into key */
995 strlcpy(key->oprname, opername, NAMEDATALEN);
996 key->left_arg = ltypeId;
997 key->right_arg = rtypeId;
998
999 if (schemaname)
1000 {
1002
1003 /* search only in exact schema given */
1004 setup_parser_errposition_callback(&pcbstate, pstate, location);
1005 key->search_path[0] = LookupExplicitNamespace(schemaname, false);
1007 }
1008 else
1009 {
1010 /* get the active search path */
1011 if (fetch_search_path_array(key->search_path,
1013 return false; /* oops, didn't fit */
1014 }
1015
1016 return true;
1017}
#define MemSet(start, val, len)
Definition c.h:1107
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
int fetch_search_path_array(Oid *sarray, int sarray_len)
Definition namespace.c:4931
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:50
#define NAMEDATALEN
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45

References cancel_parser_errposition_callback(), DeconstructQualifiedName(), fb(), fetch_search_path_array(), 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 815 of file parse_oper.c.

819{
820 Oid ltypeId,
821 rtypeId,
822 atypeId,
828 List *args;
829 Oid rettype;
831
834
835 /*
836 * The right-hand input of the operator will be the element type of the
837 * array. However, if we currently have just an untyped literal on the
838 * right, stay with that and hope we can resolve the operator.
839 */
840 if (atypeId == UNKNOWNOID)
842 else
843 {
845 if (!OidIsValid(rtypeId))
848 errmsg("op ANY/ALL (array) requires array on right side"),
849 parser_errposition(pstate, location)));
850 }
851
852 /* Now resolve the operator */
853 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
855
856 /* Check it's not a shell */
857 if (!RegProcedureIsValid(opform->oprcode))
860 errmsg("operator is only a shell: %s",
862 opform->oprleft,
863 opform->oprright)),
864 parser_errposition(pstate, location)));
865
869 declared_arg_types[0] = opform->oprleft;
870 declared_arg_types[1] = opform->oprright;
871
872 /*
873 * enforce consistency with polymorphic argument and return types,
874 * possibly adjusting return type or declared_arg_types (which will be
875 * used as the cast destination by make_fn_arguments)
876 */
879 2,
880 opform->oprresult,
881 false);
882
883 /*
884 * Check that operator result is boolean
885 */
886 if (rettype != BOOLOID)
889 errmsg("op ANY/ALL (array) requires operator to yield boolean"),
890 parser_errposition(pstate, location)));
891 if (get_func_retset(opform->oprcode))
894 errmsg("op ANY/ALL (array) requires operator not to return a set"),
895 parser_errposition(pstate, location)));
896
897 /*
898 * Now switch back to the array type on the right, arranging for any
899 * needed cast to be applied. Beware of polymorphic operators here;
900 * enforce_generic_type_consistency may or may not have replaced a
901 * polymorphic type with a real one.
902 */
904 {
905 /* assume the actual array type is OK */
907 }
908 else
909 {
914 errmsg("could not find array type for data type %s",
916 parser_errposition(pstate, location)));
917 }
920
921 /* perform the necessary typecasting of arguments */
923
924 /* and build the expression node */
926 result->opno = oprid(tup);
927 result->opfuncid = opform->oprcode;
928 result->hashfuncid = InvalidOid;
929 result->negfuncid = InvalidOid;
930 result->useOr = useOr;
931 /* inputcollid will be set by parse_collate.c */
932 result->args = args;
933 result->location = location;
934
936
937 return (Expr *) result;
938}
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:3054
Oid get_array_type(Oid typid)
Definition lsyscache.c:3009

References enforce_generic_type_consistency(), ereport, errcode(), errmsg, ERROR, exprType(), fb(), Form_pg_operator, format_type_be(), get_array_type(), get_base_element_type(), get_func_retset(), GETSTRUCT(), InvalidOid, list_make2, make_fn_arguments(), makeNode, OidIsValid, op_signature_string(), oper(), oprid(), parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and result.

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 629 of file parse_oper.c.

632{
636 errmsg("operator is not unique: %s",
638 errdetail("Could not choose a best candidate operator."),
639 errhint("You might need to add explicit type casts."),
640 parser_errposition(pstate, location)));
641 else
644 errmsg("operator does not exist: %s",
647 parser_errposition(pstate, location)));
648}
int errdetail(const char *fmt,...) pg_attribute_printf(1
@ FUNCDETAIL_MULTIPLE
Definition parse_func.h:25
static int oper_lookup_failure_details(int fgc_flags, bool is_unary_op)
Definition parse_oper.c:654

References ereport, errcode(), errdetail(), errhint(), errmsg, ERROR, fb(), 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 609 of file parse_oper.c.

610{
612
614
615 if (OidIsValid(arg1))
617
619
621
622 return argbuf.data; /* return palloc'd string buffer */
623}
char * NameListToString(const List *names)
Definition namespace.c:3666
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(), fb(), 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 373 of file parse_oper.c.

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

References binary_oper_exact(), fb(), find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, 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 654 of file parse_oper.c.

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

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

References fb(), func_match_argtypes(), func_select_candidate(), FUNCDETAIL_MULTIPLE, FUNCDETAIL_NORMAL, FUNCDETAIL_NOTFOUND, and InvalidOid.

Referenced by left_oper(), and oper().

◆ oprfuncid()

Oid oprfuncid ( Operator  op)

Definition at line 248 of file parse_oper.c.

249{
251
252 return pgopform->oprcode;
253}

References fb(), Form_pg_operator, and GETSTRUCT().

◆ oprid()

Variable Documentation

◆ OprCacheHash

HTAB* OprCacheHash = NULL
static