1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +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_clause.c,v 1.16 1998/05/21 03:53:50 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.17 1998/05/29 14:00:19 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@ -25,12 +25,15 @@
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parse_coerce.h"
static TargetEntry *
find_targetlist_entry(ParseState *pstate,
SortGroupBy *sortgroupby, List *tlist);
static void parseFromClause(ParseState *pstate, List *frmList);
/*
* makeRangeTable -
* make a range table with the specified relation (optional) and the
@ -78,8 +81,7 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
if (exprType(qual) != BOOLOID)
{
elog(ERROR,
"where clause must return type bool, not %s",
elog(ERROR, "WHERE clause must return type bool, not type %s",
typeidTypeName(exprType(qual)));
}
return qual;
@ -167,7 +169,7 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
if (real_rtable_pos == test_rtable_pos)
{
if (target_result != NULL)
elog(ERROR, "Order/Group By '%s' is ambiguous", sortgroupby->name);
elog(ERROR, "ORDER/GROUP BY '%s' is ambiguous", sortgroupby->name);
else
target_result = target;
}
@ -175,7 +177,7 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
else
{
if (target_result != NULL)
elog(ERROR, "Order/Group By '%s' is ambiguous", sortgroupby->name);
elog(ERROR, "ORDER/GROUP BY '%s' is ambiguous", sortgroupby->name);
else
target_result = target;
}
@ -372,7 +374,7 @@ transformSortClause(ParseState *pstate,
break;
}
if (i == NIL)
elog(ERROR, "The field specified in the UNIQUE ON clause is not in the targetlist");
elog(ERROR, "All fields in the UNIQUE ON clause must appear in the target list");
foreach(s, sortlist)
{
@ -392,23 +394,29 @@ transformSortClause(ParseState *pstate,
sortlist = lappend(sortlist, sortcl);
}
}
}
return sortlist;
}
/*
* transformUnionClause -
* transform a Union clause
*
/* transformUnionClause()
* Transform a UNION clause.
* Note that the union clause is actually a fully-formed select structure.
* So, it is evaluated as a select, then the resulting target fields
* are matched up to ensure correct types in the results.
* The select clause parsing is done recursively, so the unions are evaluated
* right-to-left. One might want to look at all columns from all clauses before
* trying to coerce, but unless we keep track of the call depth we won't know
* when to do this because of the recursion.
* Let's just try matching in pairs for now (right to left) and see if it works.
* - thomas 1998-05-22
*/
List *
transformUnionClause(List *unionClause, List *targetlist)
{
List *union_list = NIL;
List *union_list = NIL;
QueryTreeList *qlist;
int i;
int i;
if (unionClause)
{
@ -421,13 +429,36 @@ transformUnionClause(List *unionClause, List *targetlist)
List *next_target;
if (length(targetlist) != length(qlist->qtrees[i]->targetList))
elog(ERROR,"Each UNION query must have the same number of columns.");
elog(ERROR,"Each UNION clause must have the same number of columns");
foreach(next_target, qlist->qtrees[i]->targetList)
{
if (((TargetEntry *)lfirst(prev_target))->resdom->restype !=
((TargetEntry *)lfirst(next_target))->resdom->restype)
elog(ERROR,"Each UNION query must have identical target types.");
Oid itype;
Oid otype;
otype = ((TargetEntry *)lfirst(prev_target))->resdom->restype;
itype = ((TargetEntry *)lfirst(next_target))->resdom->restype;
if (itype != otype)
{
Node *expr;
expr = ((TargetEntry *)lfirst(next_target))->expr;
expr = coerce_target_expr(NULL, expr, itype, otype);
if (expr == NULL)
{
elog(ERROR,"Unable to transform %s to %s"
"\n\tEach UNION clause must have compatible target types",
typeidTypeName(itype),
typeidTypeName(otype));
}
((TargetEntry *)lfirst(next_target))->expr = expr;
((TargetEntry *)lfirst(next_target))->resdom->restype = otype;
}
/* both are UNKNOWN? then evaluate as text... */
else if (itype == UNKNOWNOID)
{
((TargetEntry *)lfirst(next_target))->resdom->restype = TEXTOID;
((TargetEntry *)lfirst(prev_target))->resdom->restype = TEXTOID;
}
prev_target = lnext(prev_target);
}
union_list = lappend(union_list, qlist->qtrees[i]);
@ -436,4 +467,4 @@ transformUnionClause(List *unionClause, List *targetlist)
}
else
return NIL;
}
} /* transformUnionClause() */