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 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 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, 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

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

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

Referenced by oper().

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

Definition at line 457 of file parse_oper.c.

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

Referenced by compatible_oper_opid().

459 {
460  Operator optup;
461  Form_pg_operator opform;
462 
463  /* oper() will find the best available match */
464  optup = oper(pstate, op, arg1, arg2, noError, location);
465  if (optup == (Operator) NULL)
466  return (Operator) NULL; /* must be noError case */
467 
468  /* but is it good enough? */
469  opform = (Form_pg_operator) GETSTRUCT(optup);
470  if (IsBinaryCoercible(arg1, opform->oprleft) &&
471  IsBinaryCoercible(arg2, opform->oprright))
472  return optup;
473 
474  /* nope... */
475  ReleaseSysCache(optup);
476 
477  if (!noError)
478  ereport(ERROR,
479  (errcode(ERRCODE_UNDEFINED_FUNCTION),
480  errmsg("operator requires run-time type coercion: %s",
481  op_signature_string(op, 'b', arg1, arg2)),
482  parser_errposition(pstate, location)));
483 
484  return (Operator) NULL;
485 }
#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:688
#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:1160
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
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:377
Oid compatible_oper_opid ( List op,
Oid  arg1,
Oid  arg2,
bool  noError 
)

Definition at line 494 of file parse_oper.c.

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

Referenced by addTargetToSortList(), and ComputeIndexAttrs().

495 {
496  Operator optup;
497  Oid result;
498 
499  optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
500  if (optup != NULL)
501  {
502  result = oprid(optup);
503  ReleaseSysCache(optup);
504  return result;
505  }
506  return InvalidOid;
507 }
Oid oprid(Operator op)
Definition: parse_oper.c:245
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:457
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
static Oid find_oper_cache_entry ( OprCacheKey key)
static

Definition at line 1077 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, OPERNAMENSP, and OprCacheEntry::opr_oid.

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

1078 {
1079  OprCacheEntry *oprentry;
1080 
1081  if (OprCacheHash == NULL)
1082  {
1083  /* First time through: initialize the hash table */
1084  HASHCTL ctl;
1085 
1086  MemSet(&ctl, 0, sizeof(ctl));
1087  ctl.keysize = sizeof(OprCacheKey);
1088  ctl.entrysize = sizeof(OprCacheEntry);
1089  OprCacheHash = hash_create("Operator lookup cache", 256,
1090  &ctl, HASH_ELEM | HASH_BLOBS);
1091 
1092  /* Arrange to flush cache on pg_operator and pg_cast changes */
1095  (Datum) 0);
1098  (Datum) 0);
1099  }
1100 
1101  /* Look for an existing entry */
1102  oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
1103  (void *) key,
1104  HASH_FIND, NULL);
1105  if (oprentry == NULL)
1106  return InvalidOid;
1107 
1108  return oprentry->opr_oid;
1109 }
static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: parse_oper.c:1133
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:863
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
struct OprCacheKey OprCacheKey
struct OprCacheEntry OprCacheEntry
#define HASH_BLOBS
Definition: hsearch.h:88
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
uintptr_t Datum
Definition: postgres.h:372
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
#define InvalidOid
Definition: postgres_ext.h:36
static HTAB * OprCacheHash
Definition: parse_oper.c:1019
void get_sort_group_operators ( Oid  argtype,
bool  needLT,
bool  needEQ,
bool  needGT,
Oid ltOpr,
Oid eqOpr,
Oid gtOpr,
bool isHashable 
)

Definition at line 187 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, OidIsValid, TYPECACHE_EQ_OPR, TYPECACHE_GT_OPR, TYPECACHE_HASH_PROC, and TYPECACHE_LT_OPR.

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

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

Definition at line 1133 of file parse_oper.c.

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

Referenced by find_oper_cache_entry().

1134 {
1136  OprCacheEntry *hentry;
1137 
1138  Assert(OprCacheHash != NULL);
1139 
1140  /* Currently we just flush all entries; hard to be smarter ... */
1141  hash_seq_init(&status, OprCacheHash);
1142 
1143  while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
1144  {
1146  (void *) &hentry->key,
1147  HASH_REMOVE, NULL) == NULL)
1148  elog(ERROR, "hash table corrupted");
1149  }
1150 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
OprCacheKey key
Definition: parse_oper.c:62
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:681
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static HTAB * OprCacheHash
Definition: parse_oper.c:1019
Operator left_oper ( ParseState pstate,
List op,
Oid  arg,
bool  noError,
int  location 
)

Definition at line 604 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, ObjectIdGetDatum, OidIsValid, op_error(), oper_select_candidate(), OpernameGetCandidates(), OpernameGetOprid(), OPEROID, and SearchSysCache1().

Referenced by generate_operator_name(), and make_op().

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

Definition at line 140 of file parse_oper.c.

References Assert, InvalidOid, linitial, list_length(), LookupOperName(), LookupTypeNameOid(), lsecond, ObjectWithArgs::objargs, and ObjectWithArgs::objname.

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

141 {
142  TypeName *oprleft,
143  *oprright;
144  Oid leftoid,
145  rightoid;
146 
147  Assert(list_length(oper->objargs) == 2);
148  oprleft = linitial(oper->objargs);
149  oprright = lsecond(oper->objargs);
150 
151  if (oprleft == NULL)
152  leftoid = InvalidOid;
153  else
154  leftoid = LookupTypeNameOid(NULL, oprleft, noError);
155 
156  if (oprright == NULL)
157  rightoid = InvalidOid;
158  else
159  rightoid = LookupTypeNameOid(NULL, oprright, noError);
160 
161  return LookupOperName(NULL, oper->objname, leftoid, rightoid,
162  noError, -1);
163 }
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 lsecond(l)
Definition: pg_list.h:116
#define linitial(l)
Definition: pg_list.h:111
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:681
static int list_length(const List *l)
Definition: pg_list.h:89
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,
Node last_srf,
int  location 
)

Definition at line 747 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, op_signature_string(), oper(), OpExpr::opfuncid, OpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, oprid(), ParseState::p_last_srf, parser_errposition(), RegProcedureIsValid, ReleaseSysCache(), and right_oper().

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

749 {
750  Oid ltypeId,
751  rtypeId;
752  Operator tup;
753  Form_pg_operator opform;
754  Oid actual_arg_types[2];
755  Oid declared_arg_types[2];
756  int nargs;
757  List *args;
758  Oid rettype;
759  OpExpr *result;
760 
761  /* Select the operator */
762  if (rtree == NULL)
763  {
764  /* right operator */
765  ltypeId = exprType(ltree);
766  rtypeId = InvalidOid;
767  tup = right_oper(pstate, opname, ltypeId, false, location);
768  }
769  else if (ltree == NULL)
770  {
771  /* left operator */
772  rtypeId = exprType(rtree);
773  ltypeId = InvalidOid;
774  tup = left_oper(pstate, opname, rtypeId, false, location);
775  }
776  else
777  {
778  /* otherwise, binary operator */
779  ltypeId = exprType(ltree);
780  rtypeId = exprType(rtree);
781  tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
782  }
783 
784  opform = (Form_pg_operator) GETSTRUCT(tup);
785 
786  /* Check it's not a shell */
787  if (!RegProcedureIsValid(opform->oprcode))
788  ereport(ERROR,
789  (errcode(ERRCODE_UNDEFINED_FUNCTION),
790  errmsg("operator is only a shell: %s",
791  op_signature_string(opname,
792  opform->oprkind,
793  opform->oprleft,
794  opform->oprright)),
795  parser_errposition(pstate, location)));
796 
797  /* Do typecasting and build the expression tree */
798  if (rtree == NULL)
799  {
800  /* right operator */
801  args = list_make1(ltree);
802  actual_arg_types[0] = ltypeId;
803  declared_arg_types[0] = opform->oprleft;
804  nargs = 1;
805  }
806  else if (ltree == NULL)
807  {
808  /* left operator */
809  args = list_make1(rtree);
810  actual_arg_types[0] = rtypeId;
811  declared_arg_types[0] = opform->oprright;
812  nargs = 1;
813  }
814  else
815  {
816  /* otherwise, binary operator */
817  args = list_make2(ltree, rtree);
818  actual_arg_types[0] = ltypeId;
819  actual_arg_types[1] = rtypeId;
820  declared_arg_types[0] = opform->oprleft;
821  declared_arg_types[1] = opform->oprright;
822  nargs = 2;
823  }
824 
825  /*
826  * enforce consistency with polymorphic argument and return types,
827  * possibly adjusting return type or declared_arg_types (which will be
828  * used as the cast destination by make_fn_arguments)
829  */
830  rettype = enforce_generic_type_consistency(actual_arg_types,
831  declared_arg_types,
832  nargs,
833  opform->oprresult,
834  false);
835 
836  /* perform the necessary typecasting of arguments */
837  make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
838 
839  /* and build the expression node */
840  result = makeNode(OpExpr);
841  result->opno = oprid(tup);
842  result->opfuncid = opform->oprcode;
843  result->opresulttype = rettype;
844  result->opretset = get_func_retset(opform->oprcode);
845  /* opcollid and inputcollid will be set by parse_collate.c */
846  result->args = args;
847  result->location = location;
848 
849  /* if it returns a set, check that's OK */
850  if (result->opretset)
851  {
852  check_srf_call_placement(pstate, last_srf, location);
853  /* ... and remember it for error checks at higher levels */
854  pstate->p_last_srf = (Node *) result;
855  }
856 
857  ReleaseSysCache(tup);
858 
859  return (Expr *) result;
860 }
#define list_make2(x1, x2)
Definition: pg_list.h:140
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid oprid(Operator op)
Definition: parse_oper.c:245
Definition: nodes.h:510
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:1711
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:688
#define list_make1(x1)
Definition: pg_list.h:139
Oid opresulttype
Definition: primnodes.h:498
#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:604
Operator right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
Definition: parse_oper.c:525
int location
Definition: primnodes.h:503
#define RegProcedureIsValid(p)
Definition: c.h:534
#define ereport(elevel, rest)
Definition: elog.h:122
bool get_func_retset(Oid funcid)
Definition: lsyscache.c:1546
Node * p_last_srf
Definition: parse_node.h:204
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Oid opfuncid
Definition: primnodes.h:497
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:558
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
void check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
Definition: parse_func.c:2111
Oid opno
Definition: primnodes.h:496
List * args
Definition: primnodes.h:502
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:377
Definition: pg_list.h:45
bool opretset
Definition: primnodes.h:499
static void make_oper_cache_entry ( OprCacheKey key,
Oid  opr_oid 
)
static

Definition at line 1117 of file parse_oper.c.

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

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

1118 {
1119  OprCacheEntry *oprentry;
1120 
1121  Assert(OprCacheHash != NULL);
1122 
1123  oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
1124  (void *) key,
1125  HASH_ENTER, NULL);
1126  oprentry->opr_oid = opr_oid;
1127 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
#define Assert(condition)
Definition: c.h:681
static HTAB * OprCacheHash
Definition: parse_oper.c:1019
static bool make_oper_cache_key ( ParseState pstate,
OprCacheKey key,
List opname,
Oid  ltypeId,
Oid  rtypeId,
int  location 
)
static

Definition at line 1033 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().

1035 {
1036  char *schemaname;
1037  char *opername;
1038 
1039  /* deconstruct the name list */
1040  DeconstructQualifiedName(opname, &schemaname, &opername);
1041 
1042  /* ensure zero-fill for stable hashing */
1043  MemSet(key, 0, sizeof(OprCacheKey));
1044 
1045  /* save operator name and input types into key */
1046  strlcpy(key->oprname, opername, NAMEDATALEN);
1047  key->left_arg = ltypeId;
1048  key->right_arg = rtypeId;
1049 
1050  if (schemaname)
1051  {
1052  ParseCallbackState pcbstate;
1053 
1054  /* search only in exact schema given */
1055  setup_parser_errposition_callback(&pcbstate, pstate, location);
1056  key->search_path[0] = LookupExplicitNamespace(schemaname, false);
1058  }
1059  else
1060  {
1061  /* get the active search path */
1064  return false; /* oops, didn't fit */
1065  }
1066 
1067  return true;
1068 }
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2853
Oid left_arg
Definition: parse_oper.c:54
#define MemSet(start, val, len)
Definition: c.h:863
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2769
int fetch_search_path_array(Oid *sarray, int sarray_len)
Definition: namespace.c:4208
#define NAMEDATALEN
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:161
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:145
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 867 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().

871 {
872  Oid ltypeId,
873  rtypeId,
874  atypeId,
875  res_atypeId;
876  Operator tup;
877  Form_pg_operator opform;
878  Oid actual_arg_types[2];
879  Oid declared_arg_types[2];
880  List *args;
881  Oid rettype;
882  ScalarArrayOpExpr *result;
883 
884  ltypeId = exprType(ltree);
885  atypeId = exprType(rtree);
886 
887  /*
888  * The right-hand input of the operator will be the element type of the
889  * array. However, if we currently have just an untyped literal on the
890  * right, stay with that and hope we can resolve the operator.
891  */
892  if (atypeId == UNKNOWNOID)
893  rtypeId = UNKNOWNOID;
894  else
895  {
896  rtypeId = get_base_element_type(atypeId);
897  if (!OidIsValid(rtypeId))
898  ereport(ERROR,
899  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
900  errmsg("op ANY/ALL (array) requires array on right side"),
901  parser_errposition(pstate, location)));
902  }
903 
904  /* Now resolve the operator */
905  tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
906  opform = (Form_pg_operator) GETSTRUCT(tup);
907 
908  /* Check it's not a shell */
909  if (!RegProcedureIsValid(opform->oprcode))
910  ereport(ERROR,
911  (errcode(ERRCODE_UNDEFINED_FUNCTION),
912  errmsg("operator is only a shell: %s",
913  op_signature_string(opname,
914  opform->oprkind,
915  opform->oprleft,
916  opform->oprright)),
917  parser_errposition(pstate, location)));
918 
919  args = list_make2(ltree, rtree);
920  actual_arg_types[0] = ltypeId;
921  actual_arg_types[1] = rtypeId;
922  declared_arg_types[0] = opform->oprleft;
923  declared_arg_types[1] = opform->oprright;
924 
925  /*
926  * enforce consistency with polymorphic argument and return types,
927  * possibly adjusting return type or declared_arg_types (which will be
928  * used as the cast destination by make_fn_arguments)
929  */
930  rettype = enforce_generic_type_consistency(actual_arg_types,
931  declared_arg_types,
932  2,
933  opform->oprresult,
934  false);
935 
936  /*
937  * Check that operator result is boolean
938  */
939  if (rettype != BOOLOID)
940  ereport(ERROR,
941  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
942  errmsg("op ANY/ALL (array) requires operator to yield boolean"),
943  parser_errposition(pstate, location)));
944  if (get_func_retset(opform->oprcode))
945  ereport(ERROR,
946  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
947  errmsg("op ANY/ALL (array) requires operator not to return a set"),
948  parser_errposition(pstate, location)));
949 
950  /*
951  * Now switch back to the array type on the right, arranging for any
952  * needed cast to be applied. Beware of polymorphic operators here;
953  * enforce_generic_type_consistency may or may not have replaced a
954  * polymorphic type with a real one.
955  */
956  if (IsPolymorphicType(declared_arg_types[1]))
957  {
958  /* assume the actual array type is OK */
959  res_atypeId = atypeId;
960  }
961  else
962  {
963  res_atypeId = get_array_type(declared_arg_types[1]);
964  if (!OidIsValid(res_atypeId))
965  ereport(ERROR,
966  (errcode(ERRCODE_UNDEFINED_OBJECT),
967  errmsg("could not find array type for data type %s",
968  format_type_be(declared_arg_types[1])),
969  parser_errposition(pstate, location)));
970  }
971  actual_arg_types[1] = atypeId;
972  declared_arg_types[1] = res_atypeId;
973 
974  /* perform the necessary typecasting of arguments */
975  make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
976 
977  /* and build the expression node */
978  result = makeNode(ScalarArrayOpExpr);
979  result->opno = oprid(tup);
980  result->opfuncid = opform->oprcode;
981  result->useOr = useOr;
982  /* inputcollid will be set by parse_collate.c */
983  result->args = args;
984  result->location = location;
985 
986  ReleaseSysCache(tup);
987 
988  return (Expr *) result;
989 }
#define list_make2(x1, x2)
Definition: pg_list.h:140
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid oprid(Operator op)
Definition: parse_oper.c:245
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2512
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:1711
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:688
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
#define IsPolymorphicType(typid)
Definition: pg_type.h:745
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:534
#define ereport(elevel, rest)
Definition: elog.h:122
bool get_func_retset(Oid funcid)
Definition: lsyscache.c:1546
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define makeNode(_type_)
Definition: nodes.h:558
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
#define BOOLOID
Definition: pg_type.h:288
#define UNKNOWNOID
Definition: pg_type.h:431
FormData_pg_operator* Form_pg_operator
Definition: pg_operator.h:57
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
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:377
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 709 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().

712 {
713  if (fdresult == FUNCDETAIL_MULTIPLE)
714  ereport(ERROR,
715  (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
716  errmsg("operator is not unique: %s",
717  op_signature_string(op, oprkind, arg1, arg2)),
718  errhint("Could not choose a best candidate operator. "
719  "You might need to add explicit type casts."),
720  parser_errposition(pstate, location)));
721  else
722  ereport(ERROR,
723  (errcode(ERRCODE_UNDEFINED_FUNCTION),
724  errmsg("operator does not exist: %s",
725  op_signature_string(op, oprkind, arg1, arg2)),
726  (!arg1 || !arg2) ?
727  errhint("No operator matches the given name and argument type. "
728  "You might need to add an explicit type cast.") :
729  errhint("No operator matches the given name and argument types. "
730  "You might need to add explicit type casts."),
731  parser_errposition(pstate, location)));
732 }
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:688
#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:111
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 688 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().

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

Definition at line 377 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(), 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().

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

Definition at line 319 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().

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

Definition at line 252 of file parse_oper.c.

References GETSTRUCT.

253 {
255 
256  return pgopform->oprcode;
257 }
#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 525 of file parse_oper.c.

References 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(), OPEROID, and SearchSysCache1().

Referenced by generate_operator_name(), and make_op().

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

Variable Documentation

HTAB* OprCacheHash = NULL
static

Definition at line 1019 of file parse_oper.c.