aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_oper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_oper.c')
-rw-r--r--src/backend/parser/parse_oper.c188
1 files changed, 90 insertions, 98 deletions
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index e483372e852..b96849cfa28 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.86 2006/03/14 22:48:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.87 2006/05/01 23:22:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,8 +29,7 @@
#include "utils/typcache.h"
-static Oid binary_oper_exact(Oid arg1, Oid arg2,
- FuncCandidateList candidates);
+static Oid binary_oper_exact(List *opname, Oid arg1, Oid arg2);
static FuncDetailCode oper_select_candidate(int nargs,
Oid *input_typeids,
FuncCandidateList candidates,
@@ -64,33 +63,31 @@ Oid
LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
bool noError, int location)
{
- FuncCandidateList clist;
- char oprkind;
-
- if (!OidIsValid(oprleft))
- oprkind = 'l';
- else if (!OidIsValid(oprright))
- oprkind = 'r';
- else
- oprkind = 'b';
-
- clist = OpernameGetCandidates(opername, oprkind);
+ Oid result;
- while (clist)
- {
- if (clist->args[0] == oprleft && clist->args[1] == oprright)
- return clist->oid;
- clist = clist->next;
- }
+ result = OpernameGetOprid(opername, oprleft, oprright);
+ if (OidIsValid(result))
+ return result;
/* we don't use op_error here because only an exact match is wanted */
if (!noError)
+ {
+ char oprkind;
+
+ if (!OidIsValid(oprleft))
+ oprkind = 'l';
+ else if (!OidIsValid(oprright))
+ oprkind = 'r';
+ else
+ oprkind = 'b';
+
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator does not exist: %s",
op_signature_string(opername, oprkind,
oprleft, oprright)),
parser_errposition(pstate, location)));
+ }
return InvalidOid;
}
@@ -387,10 +384,9 @@ oprfuncid(Operator op)
* be reduced to its base type to find an "exact" match.
*/
static Oid
-binary_oper_exact(Oid arg1, Oid arg2,
- FuncCandidateList candidates)
+binary_oper_exact(List *opname, Oid arg1, Oid arg2)
{
- FuncCandidateList cand;
+ Oid result;
bool was_unknown = false;
/* Unspecified type for one of the arguments? then use the other */
@@ -405,11 +401,9 @@ binary_oper_exact(Oid arg1, Oid arg2,
was_unknown = true;
}
- for (cand = candidates; cand != NULL; cand = cand->next)
- {
- if (arg1 == cand->args[0] && arg2 == cand->args[1])
- return cand->oid;
- }
+ result = OpernameGetOprid(opname, arg1, arg2);
+ if (OidIsValid(result))
+ return result;
if (was_unknown)
{
@@ -418,11 +412,9 @@ binary_oper_exact(Oid arg1, Oid arg2,
if (basetype != arg1)
{
- for (cand = candidates; cand != NULL; cand = cand->next)
- {
- if (basetype == cand->args[0] && basetype == cand->args[1])
- return cand->oid;
- }
+ result = OpernameGetOprid(opname, basetype, basetype);
+ if (OidIsValid(result))
+ return result;
}
}
@@ -503,32 +495,33 @@ Operator
oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
bool noError, int location)
{
- FuncCandidateList clist;
- Oid inputOids[2];
Oid operOid;
FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
HeapTuple tup = NULL;
- /* Get binary operators of given name */
- clist = OpernameGetCandidates(opname, 'b');
-
- /* No operators found? Then fail... */
- if (clist != NULL)
+ /*
+ * First try for an "exact" match.
+ */
+ operOid = binary_oper_exact(opname, ltypeId, rtypeId);
+ if (!OidIsValid(operOid))
{
/*
- * Check for an "exact" match.
+ * Otherwise, search for the most suitable candidate.
*/
- operOid = binary_oper_exact(ltypeId, rtypeId, clist);
- if (!OidIsValid(operOid))
- {
- /*
- * Otherwise, search for the most suitable candidate.
- */
+ FuncCandidateList clist;
+ /* Get binary operators of given name */
+ clist = OpernameGetCandidates(opname, 'b');
+
+ /* No operators found? Then fail... */
+ if (clist != NULL)
+ {
/*
* Unspecified type for one of the arguments? then use the other
* (XXX this is probably dead code?)
*/
+ Oid inputOids[2];
+
if (rtypeId == InvalidOid)
rtypeId = ltypeId;
else if (ltypeId == InvalidOid)
@@ -537,12 +530,13 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
inputOids[1] = rtypeId;
fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
}
- if (OidIsValid(operOid))
- tup = SearchSysCache(OPEROID,
- ObjectIdGetDatum(operOid),
- 0, 0, 0);
}
+ if (OidIsValid(operOid))
+ tup = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(operOid),
+ 0, 0, 0);
+
if (!HeapTupleIsValid(tup) && !noError)
op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location);
@@ -627,32 +621,26 @@ compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
Operator
right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
{
- FuncCandidateList clist;
- Oid operOid = InvalidOid;
+ Oid operOid;
FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
HeapTuple tup = NULL;
- /* Find candidates */
- clist = OpernameGetCandidates(op, 'r');
-
- if (clist != NULL)
+ /*
+ * First try for an "exact" match.
+ */
+ operOid = OpernameGetOprid(op, arg, InvalidOid);
+ if (!OidIsValid(operOid))
{
/*
- * First, quickly check to see if there is an exactly matching
- * operator (there can be only one such entry in the list).
+ * Otherwise, search for the most suitable candidate.
*/
- FuncCandidateList clisti;
+ FuncCandidateList clist;
- for (clisti = clist; clisti != NULL; clisti = clisti->next)
- {
- if (arg == clisti->args[0])
- {
- operOid = clisti->oid;
- break;
- }
- }
+ /* Get postfix operators of given name */
+ clist = OpernameGetCandidates(op, 'r');
- if (!OidIsValid(operOid))
+ /* No operators found? Then fail... */
+ if (clist != NULL)
{
/*
* We must run oper_select_candidate even if only one candidate,
@@ -660,12 +648,13 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
*/
fdresult = oper_select_candidate(1, &arg, clist, &operOid);
}
- if (OidIsValid(operOid))
- tup = SearchSysCache(OPEROID,
- ObjectIdGetDatum(operOid),
- 0, 0, 0);
}
+ if (OidIsValid(operOid))
+ tup = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(operOid),
+ 0, 0, 0);
+
if (!HeapTupleIsValid(tup) && !noError)
op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location);
@@ -690,50 +679,53 @@ 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)
{
- FuncCandidateList clist;
- Oid operOid = InvalidOid;
+ Oid operOid;
FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
HeapTuple tup = NULL;
- /* Find candidates */
- clist = OpernameGetCandidates(op, 'l');
-
- if (clist != NULL)
+ /*
+ * First try for an "exact" match.
+ */
+ operOid = OpernameGetOprid(op, InvalidOid, arg);
+ if (!OidIsValid(operOid))
{
/*
- * First, quickly check to see if there is an exactly matching
- * operator (there can be only one such entry in the list).
- *
- * The returned list has args in the form (0, oprright). Move the
- * useful data into args[0] to keep oper_select_candidate simple. XXX
- * we are assuming here that we may scribble on the list!
+ * Otherwise, search for the most suitable candidate.
*/
- FuncCandidateList clisti;
+ FuncCandidateList clist;
+
+ /* Get prefix operators of given name */
+ clist = OpernameGetCandidates(op, 'l');
- for (clisti = clist; clisti != NULL; clisti = clisti->next)
+ /* No operators found? Then fail... */
+ if (clist != NULL)
{
- clisti->args[0] = clisti->args[1];
- if (arg == clisti->args[0])
+ /*
+ * The returned list has args in the form (0, oprright).
+ * Move the useful data into args[0] to keep oper_select_candidate
+ * simple. XXX we are assuming here that we may scribble on the
+ * list!
+ */
+ FuncCandidateList clisti;
+
+ for (clisti = clist; clisti != NULL; clisti = clisti->next)
{
- operOid = clisti->oid;
- break;
+ clisti->args[0] = clisti->args[1];
}
- }
- if (!OidIsValid(operOid))
- {
/*
* We must run oper_select_candidate even if only one candidate,
* otherwise we may falsely return a non-type-compatible operator.
*/
fdresult = oper_select_candidate(1, &arg, clist, &operOid);
}
- if (OidIsValid(operOid))
- tup = SearchSysCache(OPEROID,
- ObjectIdGetDatum(operOid),
- 0, 0, 0);
}
+ if (OidIsValid(operOid))
+ tup = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(operOid),
+ 0, 0, 0);
+
if (!HeapTupleIsValid(tup) && !noError)
op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location);