diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-05-01 23:22:43 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-05-01 23:22:43 +0000 |
commit | a65a49429f1a6722a6be4a9784b4e08fab8ca380 (patch) | |
tree | fc407bfe62a483e5e738654feeb344e58c0f3f58 /src/backend/parser/parse_oper.c | |
parent | 82a2881c5b230d62bc811a374503625226be02ae (diff) | |
download | postgresql-a65a49429f1a6722a6be4a9784b4e08fab8ca380.tar.gz postgresql-a65a49429f1a6722a6be4a9784b4e08fab8ca380.zip |
Provide a namespace.c function for lookup of an operator with exact
input datatypes given, and use this before trying OpernameGetCandidates.
This is faster than the old method when there's an exact match, and it
does not seem materially slower when there's not. And it definitely
makes some of the callers cleaner, because they didn't really want to
know about a list of candidates anyway. Per discussion with Atsushi Ogawa.
Diffstat (limited to 'src/backend/parser/parse_oper.c')
-rw-r--r-- | src/backend/parser/parse_oper.c | 188 |
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); |