*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.72 2000/04/20 00:31:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.73 2000/04/27 20:32:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static void
check_targetlists_are_compatible(List *prev_target, List *current_target)
{
- List *tl,
- *next_target;
+ List *tl;
int prev_len = 0,
next_len = 0;
foreach(tl, prev_target)
if (!((TargetEntry *) lfirst(tl))->resdom->resjunk)
- prev_len++;
+ prev_len++;
- foreach(next_target, current_target)
- if (!((TargetEntry *) lfirst(next_target))->resdom->resjunk)
- next_len++;
+ foreach(tl, current_target)
+ if (!((TargetEntry *) lfirst(tl))->resdom->resjunk)
+ next_len++;
if (prev_len != next_len)
elog(ERROR, "Each UNION | EXCEPT | INTERSECT query must have the same number of columns.");
- foreach(next_target, current_target)
+ foreach(tl, current_target)
{
- Oid itype;
- Oid otype;
+ TargetEntry *next_tle = (TargetEntry *) lfirst(tl);
+ TargetEntry *prev_tle;
+ Oid itype;
+ Oid otype;
+
+ if (next_tle->resdom->resjunk)
+ continue;
- otype = ((TargetEntry *) lfirst(prev_target))->resdom->restype;
- itype = ((TargetEntry *) lfirst(next_target))->resdom->restype;
+ /* This loop must find an entry, since we counted them above. */
+ do
+ {
+ prev_tle = (TargetEntry *) lfirst(prev_target);
+ prev_target = lnext(prev_target);
+ } while (prev_tle->resdom->resjunk);
+
+ itype = next_tle->resdom->restype;
+ otype = prev_tle->resdom->restype;
/* one or both is a NULL column? then don't convert... */
if (otype == InvalidOid)
{
/* propagate a known type forward, if available */
if (itype != InvalidOid)
- ((TargetEntry *) lfirst(prev_target))->resdom->restype = itype;
+ prev_tle->resdom->restype = itype;
#ifdef NOT_USED
else
{
- ((TargetEntry *) lfirst(prev_target))->resdom->restype = UNKNOWNOID;
- ((TargetEntry *) lfirst(next_target))->resdom->restype = UNKNOWNOID;
+ prev_tle->resdom->restype = UNKNOWNOID;
+ next_tle->resdom->restype = UNKNOWNOID;
}
#endif
}
{
Node *expr;
- expr = ((TargetEntry *) lfirst(next_target))->expr;
+ expr = next_tle->expr;
expr = CoerceTargetExpr(NULL, expr, itype, otype, -1);
if (expr == NULL)
{
typeidTypeName(itype),
typeidTypeName(otype));
}
- ((TargetEntry *) lfirst(next_target))->expr = expr;
- ((TargetEntry *) lfirst(next_target))->resdom->restype = otype;
+ next_tle->expr = expr;
+ next_tle->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;
+ next_tle->resdom->restype = TEXTOID;
+ prev_tle->resdom->restype = TEXTOID;
}
- prev_target = lnext(prev_target);
}
}
*sortClause,
*distinctClause;
List *left_expr,
- *right_expr,
*resnames = NIL;
char *op,
*into;
* formulated by the user and he wants the columns named by these
* strings. The transformation to DNF can cause another Select
* Statment to be the top one which uses other names for its columns.
- * Therefore we remeber the original names and attach them to the
+ * Therefore we remember the original names and attach them to the
* targetlist of the new topmost Node at the end of this function
*/
foreach(elist, parsetree->targetList)
{
TargetEntry *tent = (TargetEntry *) lfirst(elist);
- resnames = lappend(resnames, tent->resdom->resname);
+ if (! tent->resdom->resjunk)
+ resnames = lappend(resnames, tent->resdom->resname);
}
/*
if (prev_target)
check_targetlists_are_compatible(prev_target, intersect_node->targetList);
prev_target = intersect_node->targetList;
- /* End of check for corresponding targetlists */
/*
* Transform all nodes remaining into subselects and add them to
*/
check_targetlists_are_compatible(prev_target,
((Query *) lfirst(intersect_list))->targetList);
- /* End of check for corresponding targetlists */
n->subselect = lfirst(intersect_list);
op = "=";
*/
check_targetlists_are_compatible(prev_target,
((Query *) lfirst(((Expr *) lfirst(intersect_list))->args))->targetList);
- /* End of check for corresponding targetlists */
n->subselect = (Node *) lfirst(((Expr *) lfirst(intersect_list))->args);
op = "<>";
{
TargetEntry *tent = (TargetEntry *) lfirst(elist);
- n->lefthand = lappend(n->lefthand, tent->expr);
+ if (! tent->resdom->resjunk)
+ n->lefthand = lappend(n->lefthand, tent->expr);
}
/*
* involved!)
*/
left_expr = n->lefthand;
- right_expr = ((Query *) (n->subselect))->targetList;
n->oper = NIL;
- foreach(elist, left_expr)
+ foreach(elist, ((Query *) (n->subselect))->targetList)
{
- Node *lexpr = lfirst(elist);
- TargetEntry *tent = (TargetEntry *) lfirst(right_expr);
+ TargetEntry *tent = (TargetEntry *) lfirst(elist);
+ Node *lexpr;
Operator optup;
Form_pg_operator opform;
Oper *newop;
+ if (tent->resdom->resjunk)
+ continue;
+
+ lexpr = lfirst(left_expr);
+
optup = oper(op,
exprType(lexpr),
exprType(tent->expr),
n->oper = lappend(n->oper, newop);
- right_expr = lnext(right_expr);
+ left_expr = lnext(left_expr);
}
+ Assert(left_expr == NIL); /* should have used 'em all */
+
/*
* If the Select Query node has aggregates in use add all the
* subselects to the HAVING qual else to the WHERE qual
{
TargetEntry *tent = (TargetEntry *) lfirst(elist);
+ if (tent->resdom->resjunk)
+ continue;
+
tent->resdom->resname = lfirst(resnames);
resnames = lnext(resnames);
}