|
|
|
@ -7,7 +7,7 @@ |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* IDENTIFICATION |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.33 1999/01/25 18:02:18 momjian Exp $ |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.34 1999/01/26 05:57:14 momjian Exp $ |
|
|
|
|
* |
|
|
|
|
*------------------------------------------------------------------------- |
|
|
|
|
*/ |
|
|
|
@ -945,10 +945,8 @@ check_having_qual_for_vars(Node *clause, List *targetlist_so_far) |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/* Check if the VAR is already contained in the targetlist */ |
|
|
|
|
if (tlist_member((Var *)clause, (List *)targetlist_so_far) == NULL) |
|
|
|
|
{ |
|
|
|
|
add_tl_element(&tmp_rel, (Var *)clause);
|
|
|
|
|
}
|
|
|
|
|
if (tlist_member((Var *) clause, (List *) targetlist_so_far) == NULL) |
|
|
|
|
add_tl_element(&tmp_rel, (Var *) clause); |
|
|
|
|
|
|
|
|
|
return tmp_rel.targetlist; |
|
|
|
|
} |
|
|
|
@ -962,9 +960,7 @@ check_having_qual_for_vars(Node *clause, List *targetlist_so_far) |
|
|
|
|
* arguments... |
|
|
|
|
*/ |
|
|
|
|
foreach(t, ((Expr *) clause)->args) |
|
|
|
|
{ |
|
|
|
|
targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far); |
|
|
|
|
} |
|
|
|
|
return targetlist_so_far; |
|
|
|
|
} |
|
|
|
|
else if (IsA(clause, Aggref)) |
|
|
|
@ -982,13 +978,9 @@ check_having_qual_for_vars(Node *clause, List *targetlist_so_far) |
|
|
|
|
* expression and its index expression... |
|
|
|
|
*/ |
|
|
|
|
foreach(t, aref->refupperindexpr) |
|
|
|
|
{ |
|
|
|
|
targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far); |
|
|
|
|
} |
|
|
|
|
foreach(t, aref->reflowerindexpr) |
|
|
|
|
{ |
|
|
|
|
targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far); |
|
|
|
|
} |
|
|
|
|
targetlist_so_far = check_having_qual_for_vars(aref->refexpr, targetlist_so_far); |
|
|
|
|
targetlist_so_far = check_having_qual_for_vars(aref->refassgnexpr, targetlist_so_far); |
|
|
|
|
|
|
|
|
@ -1011,23 +1003,25 @@ check_having_qual_for_vars(Node *clause, List *targetlist_so_far) |
|
|
|
|
|
|
|
|
|
return targetlist_so_far; |
|
|
|
|
} |
|
|
|
|
else if (IsA(clause, Param) || IsA(clause, Const)) |
|
|
|
|
else if (IsA(clause, Param) ||IsA(clause, Const)) |
|
|
|
|
{ |
|
|
|
|
/* do nothing! */ |
|
|
|
|
return targetlist_so_far; |
|
|
|
|
} |
|
|
|
|
/* If we get to a sublink, then we only have to check the lefthand side of the expression
|
|
|
|
|
* to see if there are any additional VARs */ |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we get to a sublink, then we only have to check the lefthand |
|
|
|
|
* side of the expression to see if there are any additional VARs |
|
|
|
|
*/ |
|
|
|
|
else if (IsA(clause, SubLink)) |
|
|
|
|
{ |
|
|
|
|
foreach(t,((List *)((SubLink *)clause)->lefthand)) |
|
|
|
|
{ |
|
|
|
|
foreach(t, ((List *) ((SubLink *) clause)->lefthand)) |
|
|
|
|
targetlist_so_far = check_having_qual_for_vars(lfirst(t), targetlist_so_far); |
|
|
|
|
} |
|
|
|
|
return targetlist_so_far; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ooops! we can not handle that! |
|
|
|
|
*/ |
|
|
|
@ -1044,7 +1038,8 @@ check_having_qual_for_vars(Node *clause, List *targetlist_so_far) |
|
|
|
|
List * |
|
|
|
|
check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupClause) |
|
|
|
|
{ |
|
|
|
|
List *t, *l1; |
|
|
|
|
List *t, |
|
|
|
|
*l1; |
|
|
|
|
List *agg_list = NIL; |
|
|
|
|
|
|
|
|
|
int contained_in_group_clause = 0; |
|
|
|
@ -1060,8 +1055,8 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
subplanVar = match_varid((Var *) clause, subplanTargetList); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Change the varno & varattno fields of the var node to point to the resdom->resno |
|
|
|
|
* fields of the subplan (lefttree)
|
|
|
|
|
* Change the varno & varattno fields of the var node to point to |
|
|
|
|
* the resdom->resno fields of the subplan (lefttree) |
|
|
|
|
*/ |
|
|
|
|
((Var *) clause)->varattno = subplanVar->resdom->resno; |
|
|
|
|
|
|
|
|
@ -1072,7 +1067,8 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
else if (is_funcclause(clause) || not_clause(clause) || |
|
|
|
|
or_clause(clause) || and_clause(clause)) |
|
|
|
|
{ |
|
|
|
|
int new_length=0, old_length=0; |
|
|
|
|
int new_length = 0, |
|
|
|
|
old_length = 0; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is a function. Recursively call this routine for its |
|
|
|
@ -1080,21 +1076,25 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
*/ |
|
|
|
|
foreach(t, ((Expr *) clause)->args) |
|
|
|
|
{ |
|
|
|
|
old_length=length((List *)agg_list); |
|
|
|
|
old_length = length((List *) agg_list); |
|
|
|
|
|
|
|
|
|
agg_list = nconc(agg_list, |
|
|
|
|
check_having_qual_for_aggs(lfirst(t), subplanTargetList, |
|
|
|
|
groupClause)); |
|
|
|
|
|
|
|
|
|
/* The arguments of OR or AND clauses are comparisons or relations
|
|
|
|
|
* and because we are in the havingQual there must be at least one operand |
|
|
|
|
* using an aggregate function. If so, we will find it and the length of the |
|
|
|
|
* agg_list will be increased after the above call to
|
|
|
|
|
* check_having_qual_for_aggs. If there are no aggregates used, the query |
|
|
|
|
* could have been formulated using the 'where' clause */ |
|
|
|
|
if(((new_length=length((List *)agg_list)) == old_length) || (new_length == 0)) |
|
|
|
|
/*
|
|
|
|
|
* The arguments of OR or AND clauses are comparisons or |
|
|
|
|
* relations and because we are in the havingQual there must |
|
|
|
|
* be at least one operand using an aggregate function. If so, |
|
|
|
|
* we will find it and the length of the agg_list will be |
|
|
|
|
* increased after the above call to |
|
|
|
|
* check_having_qual_for_aggs. If there are no aggregates |
|
|
|
|
* used, the query could have been formulated using the |
|
|
|
|
* 'where' clause |
|
|
|
|
*/ |
|
|
|
|
if (((new_length = length((List *) agg_list)) == old_length) || (new_length == 0)) |
|
|
|
|
{ |
|
|
|
|
elog(ERROR,"This could have been done in a where clause!!"); |
|
|
|
|
elog(ERROR, "This could have been done in a where clause!!"); |
|
|
|
|
return NIL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1156,20 +1156,26 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
|
|
|
|
|
return agg_list; |
|
|
|
|
} |
|
|
|
|
else if (IsA(clause, Param) || IsA(clause, Const)) |
|
|
|
|
else if (IsA(clause, Param) ||IsA(clause, Const)) |
|
|
|
|
{ |
|
|
|
|
/* do nothing! */ |
|
|
|
|
return NIL; |
|
|
|
|
} |
|
|
|
|
/* This is for Sublinks which show up as EXPR nodes. All the other EXPR nodes
|
|
|
|
|
* (funcclauses, and_clauses, or_clauses) were caught above */ |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is for Sublinks which show up as EXPR nodes. All the other |
|
|
|
|
* EXPR nodes (funcclauses, and_clauses, or_clauses) were caught above |
|
|
|
|
*/ |
|
|
|
|
else if (IsA(clause, Expr)) |
|
|
|
|
{ |
|
|
|
|
/* Only the lefthand side of the sublink has to be checked for aggregates
|
|
|
|
|
* to be attached to result_plan->aggs (see planner.c:union_planner() ) |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Only the lefthand side of the sublink has to be checked for |
|
|
|
|
* aggregates to be attached to result_plan->aggs (see |
|
|
|
|
* planner.c:union_planner() ) |
|
|
|
|
*/ |
|
|
|
|
foreach(t,((List *)((SubLink *)((SubPlan *) |
|
|
|
|
((Expr *)clause)->oper)->sublink)->lefthand))
|
|
|
|
|
foreach(t, ((List *) ((SubLink *) ((SubPlan *) |
|
|
|
|
((Expr *) clause)->oper)->sublink)->lefthand)) |
|
|
|
|
{ |
|
|
|
|
agg_list = |
|
|
|
|
nconc(agg_list, |
|
|
|
@ -1181,35 +1187,37 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
{ |
|
|
|
|
List *tmp_ptr; |
|
|
|
|
|
|
|
|
|
foreach(tmp_ptr, ((SubLink *)((SubPlan *) |
|
|
|
|
((Expr *)clause)->oper)->sublink)->oper) |
|
|
|
|
foreach(tmp_ptr, ((SubLink *) ((SubPlan *) |
|
|
|
|
((Expr *) clause)->oper)->sublink)->oper) |
|
|
|
|
{ |
|
|
|
|
agg_list = |
|
|
|
|
nconc(agg_list, |
|
|
|
|
check_having_qual_for_aggs((Node *)lfirst(((Expr *) |
|
|
|
|
check_having_qual_for_aggs((Node *) lfirst(((Expr *) |
|
|
|
|
lfirst(tmp_ptr))->args), |
|
|
|
|
subplanTargetList, groupClause)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* All arguments to the Sublink node are attributes from outside used within
|
|
|
|
|
* the sublink. Here we have to check that only attributes that is grouped for |
|
|
|
|
* are used! */ |
|
|
|
|
foreach(t,((Expr *)clause)->args)
|
|
|
|
|
/*
|
|
|
|
|
* All arguments to the Sublink node are attributes from outside |
|
|
|
|
* used within the sublink. Here we have to check that only |
|
|
|
|
* attributes that is grouped for are used! |
|
|
|
|
*/ |
|
|
|
|
foreach(t, ((Expr *) clause)->args) |
|
|
|
|
{ |
|
|
|
|
contained_in_group_clause = 0; |
|
|
|
|
|
|
|
|
|
foreach(l1,groupClause) |
|
|
|
|
foreach(l1, groupClause) |
|
|
|
|
{ |
|
|
|
|
if (tlist_member(lfirst(t),lcons(((GroupClause *)lfirst(l1))->entry,NIL)) !=
|
|
|
|
|
if (tlist_member(lfirst(t), lcons(((GroupClause *) lfirst(l1))->entry, NIL)) != |
|
|
|
|
NULL) |
|
|
|
|
{ |
|
|
|
|
contained_in_group_clause=1; |
|
|
|
|
} |
|
|
|
|
contained_in_group_clause = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* If the use of the attribute is allowed (i.e. it is in the groupClause)
|
|
|
|
|
* we have to adjust the varnos and varattnos */ |
|
|
|
|
/*
|
|
|
|
|
* If the use of the attribute is allowed (i.e. it is in the |
|
|
|
|
* groupClause) we have to adjust the varnos and varattnos |
|
|
|
|
*/ |
|
|
|
|
if (contained_in_group_clause) |
|
|
|
|
{ |
|
|
|
|
agg_list = |
|
|
|
@ -1219,7 +1227,7 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
elog(ERROR,"You must group by the attribute used from outside!"); |
|
|
|
|
elog(ERROR, "You must group by the attribute used from outside!"); |
|
|
|
|
return NIL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1227,6 +1235,7 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ooops! we can not handle that! |
|
|
|
|
*/ |
|
|
|
@ -1235,4 +1244,5 @@ check_having_qual_for_aggs(Node *clause, List *subplanTargetList, List *groupCla |
|
|
|
|
return NIL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
/***S*H***/ /* End */ |
|
|
|
|
|
|
|
|
|
/***S*H***//* End */ |
|
|
|
|