Commit ec1f5f78 authored by Tom Lane's avatar Tom Lane

Fix oversights in flatten_tlistentry and replace_clause_joinvar_refs

that led to CASE expressions not working very well in joined queries.
parent 5729c350
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.28 1999/02/21 03:48:55 scrappy Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.29 1999/05/06 23:07:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,7 +48,7 @@ tlistentry_member(Var *var, List *targetlist) ...@@ -48,7 +48,7 @@ tlistentry_member(Var *var, List *targetlist)
{ {
if (var) if (var)
{ {
List *temp = NIL; List *temp;
foreach(temp, targetlist) foreach(temp, targetlist)
{ {
...@@ -95,7 +95,7 @@ matching_tlist_var(Var *var, List *targetlist) ...@@ -95,7 +95,7 @@ matching_tlist_var(Var *var, List *targetlist)
void void
add_var_to_tlist(RelOptInfo *rel, Var *var) add_var_to_tlist(RelOptInfo *rel, Var *var)
{ {
Expr *oldvar = (Expr *) NULL; Expr *oldvar;
oldvar = matching_tlist_var(var, rel->targetlist); oldvar = matching_tlist_var(var, rel->targetlist);
...@@ -132,7 +132,6 @@ add_var_to_tlist(RelOptInfo *rel, Var *var) ...@@ -132,7 +132,6 @@ add_var_to_tlist(RelOptInfo *rel, Var *var)
TargetEntry * TargetEntry *
create_tl_element(Var *var, int resdomno) create_tl_element(Var *var, int resdomno)
{ {
return makeTargetEntry(makeResdom(resdomno, return makeTargetEntry(makeResdom(resdomno,
var->vartype, var->vartype,
var->vartypmod, var->vartypmod,
...@@ -190,35 +189,24 @@ get_actual_tlist(List *tlist) ...@@ -190,35 +189,24 @@ get_actual_tlist(List *tlist)
* *
* 'var' is the var node * 'var' is the var node
* 'tlist' is the target list * 'tlist' is the target list
* 'dots' is t if we must match dotfields to determine uniqueness
* *
* Returns the resdom entry of the matching var node. * Returns the resdom entry of the matching var node, or NULL if no match.
* *
*/ */
Resdom * Resdom *
tlist_member(Var *var, List *tlist) tlist_member(Var *var, List *tlist)
{ {
List *i = NIL;
TargetEntry *temp_tle = (TargetEntry *) NULL;
TargetEntry *tl_elt = (TargetEntry *) NULL;
if (var) if (var)
{ {
List *i;
foreach(i, tlist) foreach(i, tlist)
{ {
temp_tle = (TargetEntry *) lfirst(i); TargetEntry *tle = (TargetEntry *) lfirst(i);
if (var_equal(var, get_expr(temp_tle))) if (var_equal(var, get_expr(tle)))
{ return tle->resdom;
tl_elt = temp_tle;
break;
} }
} }
if (tl_elt != NULL)
return tl_elt->resdom;
else
return (Resdom *) NULL;
}
return (Resdom *) NULL; return (Resdom *) NULL;
} }
...@@ -228,14 +216,12 @@ tlist_member(Var *var, List *tlist) ...@@ -228,14 +216,12 @@ tlist_member(Var *var, List *tlist)
Resdom * Resdom *
tlist_resdom(List *tlist, Resdom *resnode) tlist_resdom(List *tlist, Resdom *resnode)
{ {
Resdom *resdom = (Resdom *) NULL; List *i;
List *i = NIL;
TargetEntry *temp_tle = (TargetEntry *) NULL;
foreach(i, tlist) foreach(i, tlist)
{ {
temp_tle = (TargetEntry *) lfirst(i); TargetEntry *tle = (TargetEntry *) lfirst(i);
resdom = temp_tle->resdom; Resdom *resdom = tle->resdom;
/* Since resnos are supposed to be unique */ /* Since resnos are supposed to be unique */
if (resnode->resno == resdom->resno) if (resnode->resno == resdom->resno)
return resdom; return resdom;
...@@ -288,7 +274,6 @@ match_varid(Var *test_var, List *tlist) ...@@ -288,7 +274,6 @@ match_varid(Var *test_var, List *tlist)
if (tlvar->varnoold == test_var->varnoold && if (tlvar->varnoold == test_var->varnoold &&
tlvar->varoattno == test_var->varoattno) tlvar->varoattno == test_var->varoattno)
{ {
if (tlvar->vartype == type_var) if (tlvar->vartype == type_var)
return entry; return entry;
} }
...@@ -312,7 +297,7 @@ List * ...@@ -312,7 +297,7 @@ List *
new_unsorted_tlist(List *targetlist) new_unsorted_tlist(List *targetlist)
{ {
List *new_targetlist = (List *) copyObject((Node *) targetlist); List *new_targetlist = (List *) copyObject((Node *) targetlist);
List *x = NIL; List *x;
foreach(x, new_targetlist) foreach(x, new_targetlist)
{ {
...@@ -374,13 +359,10 @@ flatten_tlist(List *tlist) ...@@ -374,13 +359,10 @@ flatten_tlist(List *tlist)
foreach(temp, tlist) foreach(temp, tlist)
{ {
TargetEntry *temp_entry = NULL; TargetEntry *temp_entry = (TargetEntry *) lfirst(temp);
List *vars;
temp_entry = lfirst(temp); tlist_vars = nconc(tlist_vars,
vars = pull_var_clause((Node *) get_expr(temp_entry)); pull_var_clause((Node *) get_expr(temp_entry)));
if (vars != NULL)
tlist_vars = nconc(tlist_vars, vars);
} }
foreach(temp, tlist_vars) foreach(temp, tlist_vars)
...@@ -421,8 +403,8 @@ flatten_tlist(List *tlist) ...@@ -421,8 +403,8 @@ flatten_tlist(List *tlist)
List * List *
flatten_tlist_vars(List *full_tlist, List *flat_tlist) flatten_tlist_vars(List *full_tlist, List *flat_tlist)
{ {
List *x = NIL;
List *result = NIL; List *result = NIL;
List *x;
foreach(x, full_tlist) foreach(x, full_tlist)
{ {
...@@ -450,94 +432,78 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist) ...@@ -450,94 +432,78 @@ flatten_tlist_vars(List *full_tlist, List *flat_tlist)
static Node * static Node *
flatten_tlistentry(Node *tlistentry, List *flat_tlist) flatten_tlistentry(Node *tlistentry, List *flat_tlist)
{ {
List *temp;
if (tlistentry == NULL) if (tlistentry == NULL)
{
return NULL; return NULL;
}
else if (IsA(tlistentry, Var)) else if (IsA(tlistentry, Var))
{ return (Node *) get_expr(match_varid((Var *) tlistentry,
return ((Node *) get_expr(match_varid((Var *) tlistentry, flat_tlist));
flat_tlist))); else if (single_node(tlistentry))
} return tlistentry;
else if (IsA(tlistentry, Iter)) else if (IsA(tlistentry, Iter))
{ {
((Iter *) tlistentry)->iterexpr = flatten_tlistentry((Node *) ((Iter *) tlistentry)->iterexpr, ((Iter *) tlistentry)->iterexpr =
flatten_tlistentry((Node *) ((Iter *) tlistentry)->iterexpr,
flat_tlist); flat_tlist);
return tlistentry; return tlistentry;
} }
else if (single_node(tlistentry)) else if (is_subplan(tlistentry))
{ {
/* do we need to support this case? */
elog(ERROR, "flatten_tlistentry: subplan case not implemented");
return tlistentry; return tlistentry;
} }
else if (is_funcclause(tlistentry)) else if (IsA(tlistentry, Expr))
{ {
Expr *expr = (Expr *) tlistentry; /*
List *temp_result = NIL; * Recursively scan the arguments of an expression.
List *elt = NIL; * NOTE: this must come after is_subplan() case since
* subplan is a kind of Expr node.
foreach(elt, expr->args) */
temp_result = lappend(temp_result, foreach(temp, ((Expr *) tlistentry)->args)
flatten_tlistentry(lfirst(elt), flat_tlist)); lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
return tlistentry;
return ((Node *) make_funcclause((Func *) expr->oper, temp_result));
} }
else if (IsA(tlistentry, Aggref)) else if (IsA(tlistentry, Aggref))
{ {
/* XXX shouldn't this be recursing into the agg's target?
* Seems to work though, so will leave it alone ... tgl 5/99
*/
return tlistentry; return tlistentry;
} }
else if (IsA(tlistentry, ArrayRef)) else if (IsA(tlistentry, ArrayRef))
{ {
ArrayRef *aref = (ArrayRef *) tlistentry; ArrayRef *aref = (ArrayRef *) tlistentry;
List *temp = NIL;
List *elt = NIL;
foreach(elt, aref->refupperindexpr)
temp = lappend(temp, flatten_tlistentry(lfirst(elt), flat_tlist));
aref->refupperindexpr = temp;
temp = NIL;
foreach(elt, aref->reflowerindexpr)
temp = lappend(temp, flatten_tlistentry(lfirst(elt), flat_tlist));
aref->reflowerindexpr = temp;
foreach(temp, aref->refupperindexpr)
lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
foreach(temp, aref->reflowerindexpr)
lfirst(temp) = flatten_tlistentry(lfirst(temp), flat_tlist);
aref->refexpr = flatten_tlistentry(aref->refexpr, flat_tlist); aref->refexpr = flatten_tlistentry(aref->refexpr, flat_tlist);
aref->refassgnexpr = flatten_tlistentry(aref->refassgnexpr,flat_tlist);
aref->refassgnexpr = flatten_tlistentry(aref->refassgnexpr, flat_tlist);
return tlistentry; return tlistentry;
} }
else if (case_clause(tlistentry)) else if (case_clause(tlistentry))
{ {
CaseExpr *cexpr = (CaseExpr *) tlistentry; CaseExpr *cexpr = (CaseExpr *) tlistentry;
List *elt = NIL;
foreach(elt, cexpr->args) foreach(temp, cexpr->args)
{ {
CaseWhen *cwhen = (CaseWhen *)lfirst(elt); CaseWhen *cwhen = (CaseWhen *) lfirst(temp);
cwhen->expr = flatten_tlistentry(cwhen->expr, flat_tlist);
cwhen->result = flatten_tlistentry(cwhen->result, flat_tlist); cwhen->result = flatten_tlistentry(cwhen->result, flat_tlist);
} }
cexpr->defresult = flatten_tlistentry(cexpr->defresult, flat_tlist); cexpr->defresult = flatten_tlistentry(cexpr->defresult, flat_tlist);
return ((Node *) cexpr); return tlistentry;
} }
else else
{ {
Expr *expr, *final; elog(ERROR, "flatten_tlistentry: Cannot handle node type %d",
Var *left, *right; nodeTag(tlistentry));
return tlistentry;
Assert(IsA(tlistentry, Expr));
expr = (Expr *) tlistentry;
left = (Var *) flatten_tlistentry((Node *) get_leftop(expr),
flat_tlist);
right = (Var *) flatten_tlistentry((Node *) get_rightop(expr),
flat_tlist);
final = make_opclause((Oper *) expr->oper, left, right);
final->opType = expr->opType;
final->typeOid = expr->typeOid;
return (Node *)final;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment