PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 const char * op_signature_string (List *op, char oprkind, Oid arg1, Oid arg2)
 
static void op_error (ParseState *pstate, List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult, int location)
 
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 LookupOperNameTypeNames (ParseState *pstate, List *opername, TypeName *oprleft, TypeName *oprright, bool noError, int location)
 
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 right_oper (ParseState *pstate, List *op, Oid arg, bool noError, int location)
 
Operator left_oper (ParseState *pstate, List *op, Oid arg, bool noError, int location)
 
Exprmake_op (ParseState *pstate, List *opname, Node *ltree, Node *rtree, 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

#define MAX_CACHED_PATH_LEN   16

Definition at line 49 of file parse_oper.c.

Referenced by make_oper_cache_key().

Typedef Documentation

Function Documentation

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

Definition at line 267 of file parse_oper.c.

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

Referenced by oper().

268 {
269  Oid result;
270  bool was_unknown = false;
271 
272  /* Unspecified type for one of the arguments? then use the other */
273  if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
274  {
275  arg1 = arg2;
276  was_unknown = true;
277  }
278  else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
279  {
280  arg2 = arg1;
281  was_unknown = true;
282  }
283 
284  result = OpernameGetOprid(opname, arg1, arg2);
285  if (OidIsValid(result))
286  return result;
287 
288  if (was_unknown)
289  {
290  /* arg1 and arg2 are the same here, need only look at arg1 */
291  Oid basetype = getBaseType(arg1);
292 
293  if (basetype != arg1)
294  {
295  result = OpernameGetOprid(opname, basetype, basetype);
296  if (OidIsValid(result))
297  return result;
298  }
299  }
300 
301  return InvalidOid;
302 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1444
#define InvalidOid
Definition: postgres_ext.h:36
#define UNKNOWNOID
Definition: pg_type.h:423
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2239
Operator compatible_oper ( ParseState pstate,
List op,
Oid  arg1,
Oid  arg2,
bool  noError,
int  location 
)

Definition at line 455 of file parse_oper.c.

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

Referenced by compatible_oper_opid().

457 {
458  Operator optup;
459  Form_pg_operator opform;
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? */
467  opform = (Form_pg_operator) GETSTRUCT(optup);
468  if (IsBinaryCoercible(arg1, opform->oprleft) &&
469  IsBinaryCoercible(arg2, opform->oprright))
470  return optup;
471 
472  /* nope... */
473  ReleaseSysCache(optup);
474 
475  if (!noError)
476  ereport(ERROR,
477  (errcode(ERRCODE_UNDEFINED_FUNCTION),
478  errmsg("operator requires run-time type coercion: %s",
479  op_signature_string(op, 'b', arg1, arg2)),
480  parser_errposition(pstate, location)));
481 
482  return (Operator) NULL;
483 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
int errcode(int sqlerrcode)
Definition: elog.c:575
static const char * op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
Definition: parse_oper.c:686
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsBinaryCoercible(Oid srctype, Oid targettype)
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define NULL
Definition: c.h:226
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:375
Oid compatible_oper_opid ( List op,
Oid  arg1,
Oid  arg2,
bool  noError 
)

Definition at line 492 of file parse_oper.c.

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

Referenced by addTargetToSortList(), and ComputeIndexAttrs().

493 {
494  Operator optup;
495  Oid result;
496 
497  optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
498  if (optup != NULL)
499  {
500  result = oprid(optup);
501  ReleaseSysCache(optup);
502  return result;
503  }
504  return InvalidOid;
505 }
Oid oprid(Operator op)
Definition: parse_oper.c:243
unsigned int Oid
Definition: postgres_ext.h:31
Operator compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2, bool noError, int location)
Definition: parse_oper.c:455
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
static Oid find_oper_cache_entry ( OprCacheKey key)
static

Definition at line 1066 of file parse_oper.c.

References CacheRegisterSyscacheCallback(), CASTSOURCETARGET, HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_FIND, hash_search(), InvalidateOprCacheCallBack(), InvalidOid, HASHCTL::keysize, MemSet, NULL, OPERNAMENSP, and OprCacheEntry::opr_oid.

Referenced by left_oper(), oper(), and right_oper().

1067 {
1068  OprCacheEntry *oprentry;
1069 
1070  if (OprCacheHash == NULL)
1071  {
1072  /* First time through: initialize the hash table */
1073  HASHCTL ctl;
1074 
1075  MemSet(&ctl, 0, sizeof(ctl));
1076  ctl.keysize = sizeof(OprCacheKey);
1077  ctl.entrysize = sizeof(OprCacheEntry);
1078  OprCacheHash = hash_create("Operator lookup cache", 256,
1079  &ctl, HASH_ELEM | HASH_BLOBS);
1080 
1081  /* Arrange to flush cache on pg_operator and pg_cast changes */
1084  (Datum) 0);
1087  (Datum) 0);
1088  }
1089 
1090  /* Look for an existing entry */
1091  oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
1092  (void *) key,
1093  HASH_FIND, NULL);
1094  if (oprentry == NULL)
1095  return InvalidOid;
1096 
1097  return oprentry->opr_oid;
1098 }
static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: parse_oper.c:1122
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:852
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
struct OprCacheKey OprCacheKey
struct OprCacheEntry OprCacheEntry
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1379
uintptr_t Datum
Definition: postgres.h:374
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
static HTAB * OprCacheHash
Definition: parse_oper.c:1008
void get_sort_group_operators ( Oid  argtype,
bool  needLT,
bool  needEQ,
bool  needGT,
Oid ltOpr,
Oid eqOpr,
Oid gtOpr,
bool isHashable 
)

Definition at line 185 of file parse_oper.c.

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

Referenced by addTargetToGroupList(), addTargetToSortList(), std_typanalyze(), and transformSetOperationTree().

189 {
190  TypeCacheEntry *typentry;
191  int cache_flags;
192  Oid lt_opr;
193  Oid eq_opr;
194  Oid gt_opr;
195  bool hashable;
196 
197  /*
198  * Look up the operators using the type cache.
199  *
200  * Note: the search algorithm used by typcache.c ensures that the results
201  * are consistent, ie all from matching opclasses.
202  */
203  if (isHashable != NULL)
206  else
208 
209  typentry = lookup_type_cache(argtype, cache_flags);
210  lt_opr = typentry->lt_opr;
211  eq_opr = typentry->eq_opr;
212  gt_opr = typentry->gt_opr;
213  hashable = OidIsValid(typentry->hash_proc);
214 
215  /* Report errors if needed */
216  if ((needLT && !OidIsValid(lt_opr)) ||
217  (needGT && !OidIsValid(gt_opr)))
218  ereport(ERROR,
219  (errcode(ERRCODE_UNDEFINED_FUNCTION),
220  errmsg("could not identify an ordering operator for type %s",
221  format_type_be(argtype)),
222  errhint("Use an explicit ordering operator or modify the query.")));
223  if (needEQ && !OidIsValid(eq_opr))
224  ereport(ERROR,
225  (errcode(ERRCODE_UNDEFINED_FUNCTION),
226  errmsg("could not identify an equality operator for type %s",
227  format_type_be(argtype))));
228 
229  /* Return results as needed */
230  if (ltOpr)
231  *ltOpr = lt_opr;
232  if (eqOpr)
233  *eqOpr = eq_opr;
234  if (gtOpr)
235  *gtOpr = gt_opr;
236  if (isHashable)
237  *isHashable = hashable;
238 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TYPECACHE_EQ_OPR
Definition: typcache.h:110
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define ERROR
Definition: elog.h:43
#define TYPECACHE_GT_OPR
Definition: typcache.h:112
#define ereport(elevel, rest)
Definition: elog.h:122
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:191
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define TYPECACHE_LT_OPR
Definition: typcache.h:111
#define TYPECACHE_HASH_PROC
Definition: typcache.h:114
static void InvalidateOprCacheCallBack ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 1122 of file parse_oper.c.

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

Referenced by find_oper_cache_entry().

1123 {
1125  OprCacheEntry *hentry;
1126 
1127  Assert(OprCacheHash != NULL);
1128 
1129  /* Currently we just flush all entries; hard to be smarter ... */
1130  hash_seq_init(&status, OprCacheHash);
1131 
1132  while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
1133  {
1135  (void *) &hentry->key,
1136  HASH_REMOVE, NULL) == NULL)
1137  elog(ERROR, "hash table corrupted");
1138  }
1139 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
OprCacheKey key
Definition: parse_oper.c:62
#define ERROR
Definition: elog.h:43
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
static HTAB * OprCacheHash
Definition: parse_oper.c:1008
Operator left_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)

Definition at line 602 of file parse_oper.c.

References _FuncCandidateList::args, find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), _FuncCandidateList::next, NULL, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), OPEROID, and SearchSysCache1.

Referenced by generate_operator_name(), and make_op().

603 {
604  Oid operOid;
605  OprCacheKey key;
606  bool key_ok;
608  HeapTuple tup = NULL;
609 
610  /*
611  * Try to find the mapping in the lookaside cache.
612  */
613  key_ok = make_oper_cache_key(pstate, &key, op, InvalidOid, arg, location);
614 
615  if (key_ok)
616  {
617  operOid = find_oper_cache_entry(&key);
618  if (OidIsValid(operOid))
619  {
620  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
621  if (HeapTupleIsValid(tup))
622  return (Operator) tup;
623  }
624  }
625 
626  /*
627  * First try for an "exact" match.
628  */
629  operOid = OpernameGetOprid(op, InvalidOid, arg);
630  if (!OidIsValid(operOid))
631  {
632  /*
633  * Otherwise, search for the most suitable candidate.
634  */
635  FuncCandidateList clist;
636 
637  /* Get prefix operators of given name */
638  clist = OpernameGetCandidates(op, 'l', false);
639 
640  /* No operators found? Then fail... */
641  if (clist != NULL)
642  {
643  /*
644  * The returned list has args in the form (0, oprright). Move the
645  * useful data into args[0] to keep oper_select_candidate simple.
646  * XXX we are assuming here that we may scribble on the list!
647  */
648  FuncCandidateList clisti;
649 
650  for (clisti = clist; clisti != NULL; clisti = clisti->next)
651  {
652  clisti->args[0] = clisti->args[1];
653  }
654 
655  /*
656  * We must run oper_select_candidate even if only one candidate,
657  * otherwise we may falsely return a non-type-compatible operator.
658  */
659  fdresult = oper_select_candidate(1, &arg, clist, &operOid);
660  }
661  }
662 
663  if (OidIsValid(operOid))
664  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
665 
666  if (HeapTupleIsValid(tup))
667  {
668  if (key_ok)
669  make_oper_cache_entry(&key, operOid);
670  }
671  else if (!noError)
672  op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location);
673 
674  return (Operator) tup;
675 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
Definition: namespace.c:1546
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1444
Oid args[FLEXIBLE_ARRAY_MEMBER]
Definition: namespace.h:37
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
FuncDetailCode
Definition: parse_func.h:22
static Oid find_oper_cache_entry(OprCacheKey *key)
Definition: parse_oper.c:1066
struct _FuncCandidateList * next
Definition: namespace.h:30
static void op_error(ParseState *pstate, List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult, int location)
Definition: parse_oper.c:707
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
Definition: parse_oper.c:1106
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
Definition: parse_oper.c:1022
static FuncDetailCode oper_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
Definition: parse_oper.c:317
void * arg
Oid LookupOperName ( ParseState pstate,
List opername,
Oid  oprleft,
Oid  oprright,
bool  noError,
int  location 
)

Definition at line 102 of file parse_oper.c.

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

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

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  char oprkind;
115 
116  if (!OidIsValid(oprleft))
117  oprkind = 'l';
118  else if (!OidIsValid(oprright))
119  oprkind = 'r';
120  else
121  oprkind = 'b';
122 
123  ereport(ERROR,
124  (errcode(ERRCODE_UNDEFINED_FUNCTION),
125  errmsg("operator does not exist: %s",
126  op_signature_string(opername, oprkind,
127  oprleft, oprright)),
128  parser_errposition(pstate, location)));
129  }
130 
131  return InvalidOid;
132 }
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
static const char * op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
Definition: parse_oper.c:686
#define OidIsValid(objectId)
Definition: c.h:533
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1444
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidOid
Definition: postgres_ext.h:36
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid LookupOperNameTypeNames ( ParseState pstate,
List opername,
TypeName oprleft,
TypeName oprright,
bool  noError,
int  location 
)

Definition at line 142 of file parse_oper.c.

References InvalidOid, LookupOperName(), LookupTypeNameOid(), and NULL.

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

145 {
146  Oid leftoid,
147  rightoid;
148 
149  if (oprleft == NULL)
150  leftoid = InvalidOid;
151  else
152  leftoid = LookupTypeNameOid(pstate, oprleft, noError);
153 
154  if (oprright == NULL)
155  rightoid = InvalidOid;
156  else
157  rightoid = LookupTypeNameOid(pstate, oprright, noError);
158 
159  return LookupOperName(pstate, opername, leftoid, rightoid,
160  noError, location);
161 }
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition: parse_oper.c:102
unsigned int Oid
Definition: postgres_ext.h:31
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition: parse_type.c:215
Expr* make_op ( ParseState pstate,
List opname,
Node ltree,
Node rtree,
int  location 
)

Definition at line 740 of file parse_oper.c.

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, NULL, op_signature_string(), oper(), OpExpr::opfuncid, OpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, oprid(), parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and right_oper().

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

742 {
743  Oid ltypeId,
744  rtypeId;
745  Operator tup;
746  Form_pg_operator opform;
747  Oid actual_arg_types[2];
748  Oid declared_arg_types[2];
749  int nargs;
750  List *args;
751  Oid rettype;
752  OpExpr *result;
753 
754  /* Select the operator */
755  if (rtree == NULL)
756  {
757  /* right operator */
758  ltypeId = exprType(ltree);
759  rtypeId = InvalidOid;
760  tup = right_oper(pstate, opname, ltypeId, false, location);
761  }
762  else if (ltree == NULL)
763  {
764  /* left operator */
765  rtypeId = exprType(rtree);
766  ltypeId = InvalidOid;
767  tup = left_oper(pstate, opname, rtypeId, false, location);
768  }
769  else
770  {
771  /* otherwise, binary operator */
772  ltypeId = exprType(ltree);
773  rtypeId = exprType(rtree);
774  tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
775  }
776 
777  opform = (Form_pg_operator) GETSTRUCT(tup);
778 
779  /* Check it's not a shell */
780  if (!RegProcedureIsValid(opform->oprcode))
781  ereport(ERROR,
782  (errcode(ERRCODE_UNDEFINED_FUNCTION),
783  errmsg("operator is only a shell: %s",
784  op_signature_string(opname,
785  opform->oprkind,
786  opform->oprleft,
787  opform->oprright)),
788  parser_errposition(pstate, location)));
789 
790  /* Do typecasting and build the expression tree */
791  if (rtree == NULL)
792  {
793  /* right operator */
794  args = list_make1(ltree);
795  actual_arg_types[0] = ltypeId;
796  declared_arg_types[0] = opform->oprleft;
797  nargs = 1;
798  }
799  else if (ltree == NULL)
800  {
801  /* left operator */
802  args = list_make1(rtree);
803  actual_arg_types[0] = rtypeId;
804  declared_arg_types[0] = opform->oprright;
805  nargs = 1;
806  }
807  else
808  {
809  /* otherwise, binary operator */
810  args = list_make2(ltree, rtree);
811  actual_arg_types[0] = ltypeId;
812  actual_arg_types[1] = rtypeId;
813  declared_arg_types[0] = opform->oprleft;
814  declared_arg_types[1] = opform->oprright;
815  nargs = 2;
816  }
817 
818  /*
819  * enforce consistency with polymorphic argument and return types,
820  * possibly adjusting return type or declared_arg_types (which will be
821  * used as the cast destination by make_fn_arguments)
822  */
823  rettype = enforce_generic_type_consistency(actual_arg_types,
824  declared_arg_types,
825  nargs,
826  opform->oprresult,
827  false);
828 
829  /* perform the necessary typecasting of arguments */
830  make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
831 
832  /* and build the expression node */
833  result = makeNode(OpExpr);
834  result->opno = oprid(tup);
835  result->opfuncid = opform->oprcode;
836  result->opresulttype = rettype;
837  result->opretset = get_func_retset(opform->oprcode);
838  /* opcollid and inputcollid will be set by parse_collate.c */
839  result->args = args;
840  result->location = location;
841 
842  /* if it returns a set, check that's OK */
843  if (result->opretset)
844  check_srf_call_placement(pstate, location);
845 
846  ReleaseSysCache(tup);
847 
848  return (Expr *) result;
849 }
#define list_make2(x1, x2)
Definition: pg_list.h:134
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid oprid(Operator op)
Definition: parse_oper.c:243
int errcode(int sqlerrcode)
Definition: elog.c:575
void make_fn_arguments(ParseState *pstate, List *fargs, Oid *actual_arg_types, Oid *declared_arg_types)
Definition: parse_func.c:1693
unsigned int Oid
Definition: postgres_ext.h:31
static const char * op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
Definition: parse_oper.c:686
#define list_make1(x1)
Definition: pg_list.h:133
Oid opresulttype
Definition: primnodes.h:475
#define ERROR
Definition: elog.h:43
Oid enforce_generic_type_consistency(Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
Operator left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:602
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:523
int location
Definition: primnodes.h:480
#define RegProcedureIsValid(p)
Definition: c.h:535
#define ereport(elevel, rest)
Definition: elog.h:122
bool get_func_retset(Oid funcid)
Definition: lsyscache.c:1514
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Oid opfuncid
Definition: primnodes.h:474
void check_srf_call_placement(ParseState *pstate, int location)
Definition: parse_func.c:2058
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid opno
Definition: primnodes.h:473
List * args
Definition: primnodes.h:479
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:375
Definition: pg_list.h:45
bool opretset
Definition: primnodes.h:476
static void make_oper_cache_entry ( OprCacheKey key,
Oid  opr_oid 
)
static

Definition at line 1106 of file parse_oper.c.

References Assert, HASH_ENTER, hash_search(), NULL, and OprCacheEntry::opr_oid.

Referenced by left_oper(), oper(), and right_oper().

1107 {
1108  OprCacheEntry *oprentry;
1109 
1110  Assert(OprCacheHash != NULL);
1111 
1112  oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
1113  (void *) key,
1114  HASH_ENTER, NULL);
1115  oprentry->opr_oid = opr_oid;
1116 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static HTAB * OprCacheHash
Definition: parse_oper.c:1008
static bool make_oper_cache_key ( ParseState pstate,
OprCacheKey key,
List opname,
Oid  ltypeId,
Oid  rtypeId,
int  location 
)
static

Definition at line 1022 of file parse_oper.c.

References cancel_parser_errposition_callback(), DeconstructQualifiedName(), fetch_search_path_array(), OprCacheKey::left_arg, LookupExplicitNamespace(), MAX_CACHED_PATH_LEN, MemSet, NAMEDATALEN, OprCacheKey::oprname, OprCacheKey::right_arg, OprCacheKey::search_path, setup_parser_errposition_callback(), and strlcpy().

Referenced by left_oper(), oper(), and right_oper().

1024 {
1025  char *schemaname;
1026  char *opername;
1027 
1028  /* deconstruct the name list */
1029  DeconstructQualifiedName(opname, &schemaname, &opername);
1030 
1031  /* ensure zero-fill for stable hashing */
1032  MemSet(key, 0, sizeof(OprCacheKey));
1033 
1034  /* save operator name and input types into key */
1035  strlcpy(key->oprname, opername, NAMEDATALEN);
1036  key->left_arg = ltypeId;
1037  key->right_arg = rtypeId;
1038 
1039  if (schemaname)
1040  {
1041  ParseCallbackState pcbstate;
1042 
1043  /* search only in exact schema given */
1044  setup_parser_errposition_callback(&pcbstate, pstate, location);
1045  key->search_path[0] = LookupExplicitNamespace(schemaname, false);
1047  }
1048  else
1049  {
1050  /* get the active search path */
1053  return false; /* oops, didn't fit */
1054  }
1055 
1056  return true;
1057 }
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2687
Oid left_arg
Definition: parse_oper.c:54
#define MemSet(start, val, len)
Definition: c.h:852
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2603
int fetch_search_path_array(Oid *sarray, int sarray_len)
Definition: namespace.c:4058
#define NAMEDATALEN
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:159
Oid search_path[MAX_CACHED_PATH_LEN]
Definition: parse_oper.c:56
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition: parse_node.c:143
char oprname[NAMEDATALEN]
Definition: parse_oper.c:53
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
Oid right_arg
Definition: parse_oper.c:55
#define MAX_CACHED_PATH_LEN
Definition: parse_oper.c:49
Expr* make_scalar_array_op ( ParseState pstate,
List opname,
bool  useOr,
Node ltree,
Node rtree,
int  location 
)

Definition at line 856 of file parse_oper.c.

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

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

860 {
861  Oid ltypeId,
862  rtypeId,
863  atypeId,
864  res_atypeId;
865  Operator tup;
866  Form_pg_operator opform;
867  Oid actual_arg_types[2];
868  Oid declared_arg_types[2];
869  List *args;
870  Oid rettype;
871  ScalarArrayOpExpr *result;
872 
873  ltypeId = exprType(ltree);
874  atypeId = exprType(rtree);
875 
876  /*
877  * The right-hand input of the operator will be the element type of the
878  * array. However, if we currently have just an untyped literal on the
879  * right, stay with that and hope we can resolve the operator.
880  */
881  if (atypeId == UNKNOWNOID)
882  rtypeId = UNKNOWNOID;
883  else
884  {
885  rtypeId = get_base_element_type(atypeId);
886  if (!OidIsValid(rtypeId))
887  ereport(ERROR,
888  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
889  errmsg("op ANY/ALL (array) requires array on right side"),
890  parser_errposition(pstate, location)));
891  }
892 
893  /* Now resolve the operator */
894  tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
895  opform = (Form_pg_operator) GETSTRUCT(tup);
896 
897  /* Check it's not a shell */
898  if (!RegProcedureIsValid(opform->oprcode))
899  ereport(ERROR,
900  (errcode(ERRCODE_UNDEFINED_FUNCTION),
901  errmsg("operator is only a shell: %s",
902  op_signature_string(opname,
903  opform->oprkind,
904  opform->oprleft,
905  opform->oprright)),
906  parser_errposition(pstate, location)));
907 
908  args = list_make2(ltree, rtree);
909  actual_arg_types[0] = ltypeId;
910  actual_arg_types[1] = rtypeId;
911  declared_arg_types[0] = opform->oprleft;
912  declared_arg_types[1] = opform->oprright;
913 
914  /*
915  * enforce consistency with polymorphic argument and return types,
916  * possibly adjusting return type or declared_arg_types (which will be
917  * used as the cast destination by make_fn_arguments)
918  */
919  rettype = enforce_generic_type_consistency(actual_arg_types,
920  declared_arg_types,
921  2,
922  opform->oprresult,
923  false);
924 
925  /*
926  * Check that operator result is boolean
927  */
928  if (rettype != BOOLOID)
929  ereport(ERROR,
930  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
931  errmsg("op ANY/ALL (array) requires operator to yield boolean"),
932  parser_errposition(pstate, location)));
933  if (get_func_retset(opform->oprcode))
934  ereport(ERROR,
935  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
936  errmsg("op ANY/ALL (array) requires operator not to return a set"),
937  parser_errposition(pstate, location)));
938 
939  /*
940  * Now switch back to the array type on the right, arranging for any
941  * needed cast to be applied. Beware of polymorphic operators here;
942  * enforce_generic_type_consistency may or may not have replaced a
943  * polymorphic type with a real one.
944  */
945  if (IsPolymorphicType(declared_arg_types[1]))
946  {
947  /* assume the actual array type is OK */
948  res_atypeId = atypeId;
949  }
950  else
951  {
952  res_atypeId = get_array_type(declared_arg_types[1]);
953  if (!OidIsValid(res_atypeId))
954  ereport(ERROR,
955  (errcode(ERRCODE_UNDEFINED_OBJECT),
956  errmsg("could not find array type for data type %s",
957  format_type_be(declared_arg_types[1])),
958  parser_errposition(pstate, location)));
959  }
960  actual_arg_types[1] = atypeId;
961  declared_arg_types[1] = res_atypeId;
962 
963  /* perform the necessary typecasting of arguments */
964  make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
965 
966  /* and build the expression node */
967  result = makeNode(ScalarArrayOpExpr);
968  result->opno = oprid(tup);
969  result->opfuncid = opform->oprcode;
970  result->useOr = useOr;
971  /* inputcollid will be set by parse_collate.c */
972  result->args = args;
973  result->location = location;
974 
975  ReleaseSysCache(tup);
976 
977  return (Expr *) result;
978 }
#define list_make2(x1, x2)
Definition: pg_list.h:134
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid oprid(Operator op)
Definition: parse_oper.c:243
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2480
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
void make_fn_arguments(ParseState *pstate, List *fargs, Oid *actual_arg_types, Oid *declared_arg_types)
Definition: parse_func.c:1693
unsigned int Oid
Definition: postgres_ext.h:31
static const char * op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
Definition: parse_oper.c:686
#define OidIsValid(objectId)
Definition: c.h:533
#define ERROR
Definition: elog.h:43
#define IsPolymorphicType(typid)
Definition: pg_type.h:733
Oid enforce_generic_type_consistency(Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
#define RegProcedureIsValid(p)
Definition: c.h:535
#define ereport(elevel, rest)
Definition: elog.h:122
bool get_func_retset(Oid funcid)
Definition: lsyscache.c:1514
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define makeNode(_type_)
Definition: nodes.h:556
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
#define BOOLOID
Definition: pg_type.h:288
#define UNKNOWNOID
Definition: pg_type.h:423
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2525
int errmsg(const char *fmt,...)
Definition: elog.c:797
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:375
Definition: pg_list.h:45
static void op_error ( ParseState pstate,
List op,
char  oprkind,
Oid  arg1,
Oid  arg2,
FuncDetailCode  fdresult,
int  location 
)
static

Definition at line 707 of file parse_oper.c.

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

Referenced by left_oper(), oper(), and right_oper().

710 {
711  if (fdresult == FUNCDETAIL_MULTIPLE)
712  ereport(ERROR,
713  (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
714  errmsg("operator is not unique: %s",
715  op_signature_string(op, oprkind, arg1, arg2)),
716  errhint("Could not choose a best candidate operator. "
717  "You might need to add explicit type casts."),
718  parser_errposition(pstate, location)));
719  else
720  ereport(ERROR,
721  (errcode(ERRCODE_UNDEFINED_FUNCTION),
722  errmsg("operator does not exist: %s",
723  op_signature_string(op, oprkind, arg1, arg2)),
724  errhint("No operator matches the given name and argument type(s). "
725  "You might need to add explicit type casts."),
726  parser_errposition(pstate, location)));
727 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
static const char * op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
Definition: parse_oper.c:686
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
int errmsg(const char *fmt,...)
Definition: elog.c:797
static const char * op_signature_string ( List op,
char  oprkind,
Oid  arg1,
Oid  arg2 
)
static

Definition at line 686 of file parse_oper.c.

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

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

687 {
688  StringInfoData argbuf;
689 
690  initStringInfo(&argbuf);
691 
692  if (oprkind != 'l')
693  appendStringInfo(&argbuf, "%s ", format_type_be(arg1));
694 
696 
697  if (oprkind != 'r')
698  appendStringInfo(&argbuf, " %s", format_type_be(arg2));
699 
700  return argbuf.data; /* return palloc'd string buffer */
701 }
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:110
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:189
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
char * NameListToString(List *names)
Definition: namespace.c:2897
Operator oper ( ParseState pstate,
List opname,
Oid  ltypeId,
Oid  rtypeId,
bool  noError,
int  location 
)

Definition at line 375 of file parse_oper.c.

References binary_oper_exact(), find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), NULL, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OPEROID, and SearchSysCache1.

Referenced by compatible_oper(), generate_operator_name(), make_op(), make_scalar_array_op(), makeOperatorDependencies(), pushOperator(), tsquery_opr_selec(), tsqueryrecv(), and XactLockTableWait().

377 {
378  Oid operOid;
379  OprCacheKey key;
380  bool key_ok;
382  HeapTuple tup = NULL;
383 
384  /*
385  * Try to find the mapping in the lookaside cache.
386  */
387  key_ok = make_oper_cache_key(pstate, &key, opname, ltypeId, rtypeId, location);
388 
389  if (key_ok)
390  {
391  operOid = find_oper_cache_entry(&key);
392  if (OidIsValid(operOid))
393  {
394  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
395  if (HeapTupleIsValid(tup))
396  return (Operator) tup;
397  }
398  }
399 
400  /*
401  * First try for an "exact" match.
402  */
403  operOid = binary_oper_exact(opname, ltypeId, rtypeId);
404  if (!OidIsValid(operOid))
405  {
406  /*
407  * Otherwise, search for the most suitable candidate.
408  */
409  FuncCandidateList clist;
410 
411  /* Get binary operators of given name */
412  clist = OpernameGetCandidates(opname, 'b', false);
413 
414  /* No operators found? Then fail... */
415  if (clist != NULL)
416  {
417  /*
418  * Unspecified type for one of the arguments? then use the other
419  * (XXX this is probably dead code?)
420  */
421  Oid inputOids[2];
422 
423  if (rtypeId == InvalidOid)
424  rtypeId = ltypeId;
425  else if (ltypeId == InvalidOid)
426  ltypeId = rtypeId;
427  inputOids[0] = ltypeId;
428  inputOids[1] = rtypeId;
429  fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
430  }
431  }
432 
433  if (OidIsValid(operOid))
434  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
435 
436  if (HeapTupleIsValid(tup))
437  {
438  if (key_ok)
439  make_oper_cache_entry(&key, operOid);
440  }
441  else if (!noError)
442  op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location);
443 
444  return (Operator) tup;
445 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
Definition: namespace.c:1546
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
FuncDetailCode
Definition: parse_func.h:22
static Oid find_oper_cache_entry(OprCacheKey *key)
Definition: parse_oper.c:1066
static Oid binary_oper_exact(List *opname, Oid arg1, Oid arg2)
Definition: parse_oper.c:267
static void op_error(ParseState *pstate, List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult, int location)
Definition: parse_oper.c:707
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
Definition: parse_oper.c:1106
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
Definition: parse_oper.c:1022
static FuncDetailCode oper_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
Definition: parse_oper.c:317
static FuncDetailCode oper_select_candidate ( int  nargs,
Oid input_typeids,
FuncCandidateList  candidates,
Oid operOid 
)
static

Definition at line 317 of file parse_oper.c.

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

Referenced by left_oper(), oper(), and right_oper().

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  */
328  ncandidates = func_match_argtypes(nargs, input_typeids,
329  candidates, &candidates);
330 
331  /* Done if no candidate or only one candidate survives */
332  if (ncandidates == 0)
333  {
334  *operOid = InvalidOid;
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  */
347  candidates = func_select_candidate(nargs, input_typeids, candidates);
348 
349  if (candidates)
350  {
351  *operOid = candidates->oid;
352  return FUNCDETAIL_NORMAL;
353  }
354 
355  *operOid = InvalidOid;
356  return FUNCDETAIL_MULTIPLE; /* failed to select a best candidate */
357 }
int func_match_argtypes(int nargs, Oid *input_typeids, FuncCandidateList raw_candidates, FuncCandidateList *candidates)
Definition: parse_func.c:792
#define InvalidOid
Definition: postgres_ext.h:36
FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates)
Definition: parse_func.c:877
Oid oprfuncid ( Operator  op)

Definition at line 250 of file parse_oper.c.

References GETSTRUCT.

251 {
253 
254  return pgopform->oprcode;
255 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
Operator right_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)

Definition at line 523 of file parse_oper.c.

References find_oper_cache_entry(), FUNCDETAIL_NOTFOUND, HeapTupleIsValid, InvalidOid, make_oper_cache_entry(), make_oper_cache_key(), NULL, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), OPEROID, and SearchSysCache1.

Referenced by generate_operator_name(), and make_op().

524 {
525  Oid operOid;
526  OprCacheKey key;
527  bool key_ok;
529  HeapTuple tup = NULL;
530 
531  /*
532  * Try to find the mapping in the lookaside cache.
533  */
534  key_ok = make_oper_cache_key(pstate, &key, op, arg, InvalidOid, location);
535 
536  if (key_ok)
537  {
538  operOid = find_oper_cache_entry(&key);
539  if (OidIsValid(operOid))
540  {
541  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
542  if (HeapTupleIsValid(tup))
543  return (Operator) tup;
544  }
545  }
546 
547  /*
548  * First try for an "exact" match.
549  */
550  operOid = OpernameGetOprid(op, arg, InvalidOid);
551  if (!OidIsValid(operOid))
552  {
553  /*
554  * Otherwise, search for the most suitable candidate.
555  */
556  FuncCandidateList clist;
557 
558  /* Get postfix operators of given name */
559  clist = OpernameGetCandidates(op, 'r', false);
560 
561  /* No operators found? Then fail... */
562  if (clist != NULL)
563  {
564  /*
565  * We must run oper_select_candidate even if only one candidate,
566  * otherwise we may falsely return a non-type-compatible operator.
567  */
568  fdresult = oper_select_candidate(1, &arg, clist, &operOid);
569  }
570  }
571 
572  if (OidIsValid(operOid))
573  tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
574 
575  if (HeapTupleIsValid(tup))
576  {
577  if (key_ok)
578  make_oper_cache_entry(&key, operOid);
579  }
580  else if (!noError)
581  op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location);
582 
583  return (Operator) tup;
584 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
FuncCandidateList OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
Definition: namespace.c:1546
Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
Definition: namespace.c:1444
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
FuncDetailCode
Definition: parse_func.h:22
static Oid find_oper_cache_entry(OprCacheKey *key)
Definition: parse_oper.c:1066
static void op_error(ParseState *pstate, List *op, char oprkind, Oid arg1, Oid arg2, FuncDetailCode fdresult, int location)
Definition: parse_oper.c:707
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
Definition: parse_oper.c:1106
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
static bool make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId, int location)
Definition: parse_oper.c:1022
static FuncDetailCode oper_select_candidate(int nargs, Oid *input_typeids, FuncCandidateList candidates, Oid *operOid)
Definition: parse_oper.c:317
void * arg

Variable Documentation

HTAB* OprCacheHash = NULL
static

Definition at line 1008 of file parse_oper.c.