1
0
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:
Thomas G. Lockhart
1998-05-29 14:00:24 +00:00
parent 329083a97e
commit 8536c96261
8 changed files with 542 additions and 1004 deletions

View File

@ -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, &ltree, &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, &ltree, &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);