mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Do type conversion to match columns in UNION clauses.
Currently force the type to match the _first_ select in the union. Move oper_select_candidate() from parse_func.c to parse_oper.c. Throw error inside of oper_inexact() if no match for binary operators. Check more carefully that types can be coerced even if there is only one candidate operator in oper_inexact(). Fix up error messages for more uniform look. Remove unused code. Fix up comments.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.15 1998/05/09 23:29:53 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.16 1998/05/29 14:00:21 thomas Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,6 +25,7 @@
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_relation.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/lsyscache.h"
|
||||
@ -36,13 +37,10 @@ make_operand(char *opname,
|
||||
Oid orig_typeId,
|
||||
Oid true_typeId);
|
||||
|
||||
/*
|
||||
* make_parsestate() --
|
||||
* allocate and initialize a new ParseState.
|
||||
* the CALLER is responsible for freeing the ParseState* returned
|
||||
*
|
||||
/* make_parsestate()
|
||||
* Allocate and initialize a new ParseState.
|
||||
* The CALLER is responsible for freeing the ParseState* returned.
|
||||
*/
|
||||
|
||||
ParseState *
|
||||
make_parsestate(ParseState *parentParseState)
|
||||
{
|
||||
@ -58,11 +56,6 @@ make_parsestate(ParseState *parentParseState)
|
||||
}
|
||||
|
||||
|
||||
extern
|
||||
Node *
|
||||
coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId);
|
||||
|
||||
|
||||
/* make_operand()
|
||||
* Ensure argument type match by forcing conversion of constants.
|
||||
*/
|
||||
@ -74,10 +67,6 @@ make_operand(char *opname,
|
||||
{
|
||||
Node *result;
|
||||
Type true_type;
|
||||
#if FALSE
|
||||
Datum val;
|
||||
Oid infunc;
|
||||
#endif
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_operand: constructing operand for '%s' %s->%s\n",
|
||||
@ -133,36 +122,6 @@ disallow_setop(char *op, Type optype, Node *operand)
|
||||
}
|
||||
|
||||
|
||||
/* CoerceType()
|
||||
* Try to force type of node.
|
||||
*/
|
||||
Oid CoerceType(Oid typeId, Node *node);
|
||||
|
||||
Oid
|
||||
CoerceType(Oid typeId, Node *node)
|
||||
{
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Const:
|
||||
{
|
||||
Const *con = (Const *) node;
|
||||
|
||||
#ifdef PARSEDEBUG
|
||||
printf( "Convert node %d to text\n", nodeTag(node));
|
||||
#endif
|
||||
|
||||
typeId = TEXTOID;
|
||||
con->consttype = typeId;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return typeId;
|
||||
} /* CoerceType() */
|
||||
|
||||
|
||||
/* make_op()
|
||||
* Operator construction.
|
||||
*
|
||||
@ -174,7 +133,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
||||
{
|
||||
Oid ltypeId,
|
||||
rtypeId;
|
||||
Operator temp;
|
||||
Operator tup;
|
||||
OperatorTupleForm opform;
|
||||
Oper *newop;
|
||||
Node *left,
|
||||
@ -185,8 +144,8 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
||||
if (rtree == NULL)
|
||||
{
|
||||
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
|
||||
temp = right_oper(opname, ltypeId);
|
||||
opform = (OperatorTupleForm) GETSTRUCT(temp);
|
||||
tup = right_oper(opname, ltypeId);
|
||||
opform = (OperatorTupleForm) GETSTRUCT(tup);
|
||||
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
||||
right = NULL;
|
||||
|
||||
@ -196,11 +155,11 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
||||
else if (ltree == NULL)
|
||||
{
|
||||
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
|
||||
temp = left_oper(opname, rtypeId);
|
||||
tup = left_oper(opname, rtypeId);
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_op: returned from left_oper() with structure at %p\n", (void *)temp);
|
||||
printf("make_op: returned from left_oper() with structure at %p\n", (void *)tup);
|
||||
#endif
|
||||
opform = (OperatorTupleForm) GETSTRUCT(temp);
|
||||
opform = (OperatorTupleForm) GETSTRUCT(tup);
|
||||
#ifdef PARSEDEBUG
|
||||
printf("make_op: calling make_operand()\n");
|
||||
#endif
|
||||
@ -212,80 +171,28 @@ printf("make_op: calling make_operand()\n");
|
||||
/* otherwise, binary operator */
|
||||
else
|
||||
{
|
||||
|
||||
#define CONVERTIBLE_TYPE(t) ( (t) == INT2OID || \
|
||||
(t) == INT4OID || \
|
||||
(t) == OIDOID || \
|
||||
(t) == FLOAT4OID || \
|
||||
(t) == FLOAT8OID || \
|
||||
(t) == CASHOID)
|
||||
|
||||
/* binary operator */
|
||||
ltypeId = (ltree == NULL) ? UNKNOWNOID : exprType(ltree);
|
||||
rtypeId = (rtree == NULL) ? UNKNOWNOID : exprType(rtree);
|
||||
|
||||
#if FALSE
|
||||
/* Both operands of unknown type?
|
||||
* Then they are strings and we should force at least one to text
|
||||
* - thomas 1998-03-16
|
||||
*/
|
||||
ltypeId = exprType(ltree);
|
||||
rtypeId = exprType(rtree);
|
||||
|
||||
if ((ltypeId == UNKNOWNOID)
|
||||
&& (rtypeId == UNKNOWNOID))
|
||||
/* check for exact match on this operator... */
|
||||
if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId, <ree, &rtree, TRUE)))
|
||||
{
|
||||
#ifdef PARSEDEBUG
|
||||
printf( "Convert left-hand constant to text for node %d\n", nodeTag(ltree));
|
||||
#endif
|
||||
|
||||
ltypeId = CoerceType(TEXTOID, ltree);
|
||||
ltypeId = exprType(ltree);
|
||||
rtypeId = exprType(rtree);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FALSE
|
||||
/*
|
||||
* convert constant when using a const of a numeric type and a
|
||||
* non-const of another numeric type
|
||||
*/
|
||||
if (CONVERTIBLE_TYPE(ltypeId) && nodeTag(ltree) != T_Const &&
|
||||
CONVERTIBLE_TYPE(rtypeId) && nodeTag(rtree) == T_Const &&
|
||||
!((Const *) rtree)->constiscast)
|
||||
/* try to find a match on likely candidates... */
|
||||
else if (!HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId, <ree, &rtree, FALSE)))
|
||||
{
|
||||
outfunc = typeidOutfunc(rtypeId);
|
||||
infunc = typeidInfunc(ltypeId);
|
||||
outstr = (char *) fmgr(outfunc, ((Const *) rtree)->constvalue);
|
||||
((Const *) rtree)->constvalue = (Datum) fmgr(infunc, outstr, -1);
|
||||
pfree(outstr);
|
||||
((Const *) rtree)->consttype = rtypeId = ltypeId;
|
||||
newtype = typeidType(rtypeId);
|
||||
((Const *) rtree)->constlen = typeLen(newtype);
|
||||
((Const *) rtree)->constbyval = typeByVal(newtype);
|
||||
/* Won't return from oper_inexact() without a candidate... */
|
||||
}
|
||||
|
||||
if (CONVERTIBLE_TYPE(rtypeId) && nodeTag(rtree) != T_Const &&
|
||||
CONVERTIBLE_TYPE(ltypeId) && nodeTag(ltree) == T_Const &&
|
||||
!((Const *) ltree)->constiscast)
|
||||
{
|
||||
outfunc = typeidOutfunc(ltypeId);
|
||||
infunc = typeidInfunc(rtypeId);
|
||||
outstr = (char *) fmgr(outfunc, ((Const *) ltree)->constvalue);
|
||||
((Const *) ltree)->constvalue = (Datum) fmgr(infunc, outstr, -1);
|
||||
pfree(outstr);
|
||||
((Const *) ltree)->consttype = ltypeId = rtypeId;
|
||||
newtype = typeidType(ltypeId);
|
||||
((Const *) ltree)->constlen = typeLen(newtype);
|
||||
((Const *) ltree)->constbyval = typeByVal(newtype);
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = oper(opname, ltypeId, rtypeId, false);
|
||||
opform = (OperatorTupleForm) GETSTRUCT(temp);
|
||||
opform = (OperatorTupleForm) GETSTRUCT(tup);
|
||||
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
||||
}
|
||||
|
||||
newop = makeOper(oprid(temp), /* opno */
|
||||
newop = makeOper(oprid(tup), /* opno */
|
||||
InvalidOid, /* opid */
|
||||
opform->oprresult, /* operator result type */
|
||||
0,
|
||||
@ -304,7 +211,7 @@ printf( "Convert left-hand constant to text for node %d\n", nodeTag(ltree));
|
||||
result->args = lcons(left, lcons(right, NIL));
|
||||
|
||||
return result;
|
||||
}
|
||||
} /* make_op() */
|
||||
|
||||
|
||||
Var *
|
||||
@ -538,7 +445,7 @@ make_const(Value *value)
|
||||
default:
|
||||
{
|
||||
if (nodeTag(value) != T_Null)
|
||||
elog(NOTICE, "unknown type : %d\n", nodeTag(value));
|
||||
elog(NOTICE, "make_const: unknown type %d\n", nodeTag(value));
|
||||
|
||||
/* null const */
|
||||
con = makeConst(0, 0, (Datum) NULL, true, false, false, false);
|
||||
|
Reference in New Issue
Block a user