mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 00:02:53 -04:00
Remove bogus code in oper_exact --- if it didn't find an exact
match then it tried for a self-commutative operator with the reversed input data types. This is pretty silly; there could never be such an operator, except maybe in binary-compatible-type scenarios, and we have oper_inexact for that. Besides which, the oprsanity regress test would complain about such an operator. Remove nonfunctional code and simplify routine calling convention accordingly.
This commit is contained in:
parent
e8140adb10
commit
a23faeee83
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.30 1999/08/22 20:15:04 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.31 1999/08/23 23:48:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -31,10 +31,6 @@
|
|||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
static void disallow_setop(char *op, Type optype, Node *operand);
|
static void disallow_setop(char *op, Type optype, Node *operand);
|
||||||
static Node *make_operand(char *opname,
|
|
||||||
Node *tree,
|
|
||||||
Oid orig_typeId,
|
|
||||||
Oid true_typeId);
|
|
||||||
|
|
||||||
/* make_parsestate()
|
/* make_parsestate()
|
||||||
* Allocate and initialize a new ParseState.
|
* Allocate and initialize a new ParseState.
|
||||||
@ -58,31 +54,31 @@ make_parsestate(ParseState *parentParseState)
|
|||||||
/* make_operand()
|
/* make_operand()
|
||||||
* Ensure argument type match by forcing conversion of constants.
|
* Ensure argument type match by forcing conversion of constants.
|
||||||
*/
|
*/
|
||||||
static Node *
|
Node *
|
||||||
make_operand(char *opname,
|
make_operand(char *opname,
|
||||||
Node *tree,
|
Node *tree,
|
||||||
Oid orig_typeId,
|
Oid orig_typeId,
|
||||||
Oid true_typeId)
|
Oid target_typeId)
|
||||||
{
|
{
|
||||||
Node *result;
|
Node *result;
|
||||||
Type true_type;
|
Type target_type;
|
||||||
|
|
||||||
if (tree != NULL)
|
if (tree != NULL)
|
||||||
{
|
{
|
||||||
result = tree;
|
result = tree;
|
||||||
true_type = typeidType(true_typeId);
|
target_type = typeidType(target_typeId);
|
||||||
disallow_setop(opname, true_type, result);
|
disallow_setop(opname, target_type, result);
|
||||||
|
|
||||||
/* must coerce? */
|
/* must coerce? */
|
||||||
if (true_typeId != orig_typeId)
|
if (target_typeId != orig_typeId)
|
||||||
result = coerce_type(NULL, tree, orig_typeId, true_typeId, -1);
|
result = coerce_type(NULL, tree, orig_typeId, target_typeId, -1);
|
||||||
}
|
}
|
||||||
/* otherwise, this is a NULL value */
|
/* otherwise, this is a NULL value */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Const *con = makeNode(Const);
|
Const *con = makeNode(Const);
|
||||||
|
|
||||||
con->consttype = true_typeId;
|
con->consttype = target_typeId;
|
||||||
con->constlen = 0;
|
con->constlen = 0;
|
||||||
con->constvalue = (Datum) (struct varlena *) NULL;
|
con->constvalue = (Datum) (struct varlena *) NULL;
|
||||||
con->constisnull = true;
|
con->constisnull = true;
|
||||||
@ -128,47 +124,31 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
|||||||
*right;
|
*right;
|
||||||
Expr *result;
|
Expr *result;
|
||||||
|
|
||||||
|
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
|
||||||
|
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
|
||||||
|
|
||||||
/* right operator? */
|
/* right operator? */
|
||||||
if (rtree == NULL)
|
if (rtree == NULL)
|
||||||
{
|
{
|
||||||
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
|
|
||||||
tup = right_oper(opname, ltypeId);
|
tup = right_oper(opname, ltypeId);
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||||
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
||||||
right = NULL;
|
right = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* left operator? */
|
/* left operator? */
|
||||||
else if (ltree == NULL)
|
else if (ltree == NULL)
|
||||||
{
|
{
|
||||||
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
|
|
||||||
tup = left_oper(opname, rtypeId);
|
tup = left_oper(opname, rtypeId);
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
||||||
left = NULL;
|
left = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* otherwise, binary operator */
|
/* otherwise, binary operator */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* binary operator */
|
tup = oper(opname, ltypeId, rtypeId, FALSE);
|
||||||
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
|
|
||||||
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
|
|
||||||
|
|
||||||
/* check for exact match on this operator... */
|
|
||||||
if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId, <ree, &rtree, TRUE)))
|
|
||||||
{
|
|
||||||
ltypeId = exprType(ltree);
|
|
||||||
rtypeId = exprType(rtree);
|
|
||||||
}
|
|
||||||
/* try to find a match on likely candidates... */
|
|
||||||
else if (!HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId, <ree, &rtree, FALSE)))
|
|
||||||
{
|
|
||||||
/* Won't return from oper_inexact() without a candidate... */
|
|
||||||
}
|
|
||||||
|
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||||
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
||||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.29 1999/07/17 20:17:25 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.30 1999/08/23 23:48:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
static Oid *oper_select_candidate(int nargs, Oid *input_typeids,
|
static Oid *oper_select_candidate(int nargs, Oid *input_typeids,
|
||||||
CandidateList candidates);
|
CandidateList candidates);
|
||||||
|
static Operator oper_exact(char *op, Oid arg1, Oid arg2);
|
||||||
|
static Operator oper_inexact(char *op, Oid arg1, Oid arg2);
|
||||||
static int binary_oper_get_candidates(char *opname,
|
static int binary_oper_get_candidates(char *opname,
|
||||||
Oid leftTypeId,
|
Oid leftTypeId,
|
||||||
Oid rightTypeId,
|
Oid rightTypeId,
|
||||||
@ -376,15 +378,14 @@ oper_select_candidate(int nargs,
|
|||||||
|
|
||||||
|
|
||||||
/* oper_exact()
|
/* oper_exact()
|
||||||
* Given operator, and arguments, return oper struct.
|
* Given operator, and arguments, return oper struct or NULL.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* arg1, arg2: Type IDs
|
* arg1, arg2: Type IDs
|
||||||
*/
|
*/
|
||||||
Operator
|
static Operator
|
||||||
oper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings)
|
oper_exact(char *op, Oid arg1, Oid arg2)
|
||||||
{
|
{
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Node *tree;
|
|
||||||
|
|
||||||
/* Unspecified type for one of the arguments? then use the other */
|
/* Unspecified type for one of the arguments? then use the other */
|
||||||
if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
|
if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
|
||||||
@ -398,51 +399,17 @@ oper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarn
|
|||||||
ObjectIdGetDatum(arg2),
|
ObjectIdGetDatum(arg2),
|
||||||
CharGetDatum('b'));
|
CharGetDatum('b'));
|
||||||
|
|
||||||
/*
|
return (Operator) tup;
|
||||||
* Did not find anything? then try flipping arguments on a commutative
|
|
||||||
* operator...
|
|
||||||
*/
|
|
||||||
if (!HeapTupleIsValid(tup) && (arg1 != arg2))
|
|
||||||
{
|
|
||||||
tup = SearchSysCacheTuple(OPRNAME,
|
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(arg2),
|
|
||||||
ObjectIdGetDatum(arg1),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
|
|
||||||
if (HeapTupleIsValid(tup))
|
|
||||||
{
|
|
||||||
Form_pg_operator opform;
|
|
||||||
|
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
|
||||||
if (opform->oprcom == tup->t_data->t_oid)
|
|
||||||
{
|
|
||||||
if ((ltree != NULL) && (rtree != NULL))
|
|
||||||
{
|
|
||||||
tree = *ltree;
|
|
||||||
*ltree = *rtree;
|
|
||||||
*rtree = tree;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* disable for now... - thomas 1998-05-14 */
|
|
||||||
else
|
|
||||||
tup = NULL;
|
|
||||||
}
|
|
||||||
if (!HeapTupleIsValid(tup) && (!noWarnings))
|
|
||||||
op_error(op, arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tup;
|
|
||||||
} /* oper_exact() */
|
} /* oper_exact() */
|
||||||
|
|
||||||
|
|
||||||
/* oper_inexact()
|
/* oper_inexact()
|
||||||
* Given operator, types of arg1, and arg2, return oper struct.
|
* Given operator, types of arg1, and arg2, return oper struct or NULL.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* arg1, arg2: Type IDs
|
* arg1, arg2: Type IDs
|
||||||
*/
|
*/
|
||||||
Operator
|
static Operator
|
||||||
oper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings)
|
oper_inexact(char *op, Oid arg1, Oid arg2)
|
||||||
{
|
{
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
CandidateList candidates;
|
CandidateList candidates;
|
||||||
@ -458,13 +425,9 @@ oper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWa
|
|||||||
|
|
||||||
ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
|
ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
|
||||||
|
|
||||||
/* No operators found? Then throw error or return null... */
|
/* No operators found? Then return null... */
|
||||||
if (ncandidates == 0)
|
if (ncandidates == 0)
|
||||||
{
|
|
||||||
if (!noWarnings)
|
|
||||||
op_error(op, arg1, arg2);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Or found exactly one? Then proceed... */
|
/* Or found exactly one? Then proceed... */
|
||||||
else if (ncandidates == 1)
|
else if (ncandidates == 1)
|
||||||
@ -493,18 +456,6 @@ oper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
tup = NULL;
|
tup = NULL;
|
||||||
|
|
||||||
/* Could not choose one, for whatever reason... */
|
|
||||||
if (!HeapTupleIsValid(tup))
|
|
||||||
{
|
|
||||||
if (!noWarnings)
|
|
||||||
{
|
|
||||||
elog(ERROR, "Unable to identify an operator '%s' for types '%s' and '%s'"
|
|
||||||
"\n\tYou will have to retype this query using an explicit cast",
|
|
||||||
op, typeTypeName(typeidType(arg1)), typeTypeName(typeidType(arg2)));
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (Operator) tup;
|
return (Operator) tup;
|
||||||
} /* oper_inexact() */
|
} /* oper_inexact() */
|
||||||
@ -521,17 +472,16 @@ oper(char *opname, Oid ltypeId, Oid rtypeId, bool noWarnings)
|
|||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
|
|
||||||
/* check for exact match on this operator... */
|
/* check for exact match on this operator... */
|
||||||
if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId, NULL, NULL, TRUE)))
|
if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/* try to find a match on likely candidates... */
|
/* try to find a match on likely candidates... */
|
||||||
else if (HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId, NULL, NULL, TRUE)))
|
else if (HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (!noWarnings)
|
else if (!noWarnings)
|
||||||
{
|
{
|
||||||
elog(ERROR, "Unable to identify a binary operator '%s' for types %s and %s",
|
op_error(opname, ltypeId, rtypeId);
|
||||||
opname, typeTypeName(typeidType(ltypeId)), typeTypeName(typeidType(rtypeId)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Operator) tup;
|
return (Operator) tup;
|
||||||
@ -741,8 +691,7 @@ op_error(char *op, Oid arg1, Oid arg2)
|
|||||||
"\n\tProbably a bad attribute name", op);
|
"\n\tProbably a bad attribute name", op);
|
||||||
}
|
}
|
||||||
|
|
||||||
elog(ERROR, "There is no operator '%s' for types '%s' and '%s'"
|
elog(ERROR, "Unable to identify an operator '%s' for types '%s' and '%s'"
|
||||||
"\n\tYou will either have to retype this query using an explicit cast,"
|
"\n\tYou will have to retype this query using an explicit cast",
|
||||||
"\n\tor you will have to define the operator using CREATE OPERATOR",
|
|
||||||
op, typeTypeName(tp1), typeTypeName(tp2));
|
op, typeTypeName(tp1), typeTypeName(tp2));
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_node.h,v 1.15 1999/07/19 00:26:17 tgl Exp $
|
* $Id: parse_node.h,v 1.16 1999/08/23 23:48:37 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -33,6 +33,8 @@ typedef struct ParseState
|
|||||||
|
|
||||||
extern ParseState *make_parsestate(ParseState *parentParseState);
|
extern ParseState *make_parsestate(ParseState *parentParseState);
|
||||||
extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
|
extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
|
||||||
|
extern Node *make_operand(char *opname, Node *tree,
|
||||||
|
Oid orig_typeId, Oid target_typeId);
|
||||||
extern Var *make_var(ParseState *pstate, Oid relid, char *refname,
|
extern Var *make_var(ParseState *pstate, Oid relid, char *refname,
|
||||||
char *attrname);
|
char *attrname);
|
||||||
extern ArrayRef *transformArraySubscripts(ParseState *pstate,
|
extern ArrayRef *transformArraySubscripts(ParseState *pstate,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_oper.h,v 1.8 1999/07/15 15:21:27 momjian Exp $
|
* $Id: parse_oper.h,v 1.9 1999/08/23 23:48:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -23,7 +23,4 @@ extern Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
|
|||||||
extern Operator right_oper(char *op, Oid arg);
|
extern Operator right_oper(char *op, Oid arg);
|
||||||
extern Operator left_oper(char *op, Oid arg);
|
extern Operator left_oper(char *op, Oid arg);
|
||||||
|
|
||||||
extern Operator oper_exact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings);
|
|
||||||
extern Operator oper_inexact(char *op, Oid arg1, Oid arg2, Node **ltree, Node **rtree, bool noWarnings);
|
|
||||||
|
|
||||||
#endif /* PARSE_OPER_H */
|
#endif /* PARSE_OPER_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user