diff options
Diffstat (limited to 'src/backend/rewrite')
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 36 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteManip.c | 149 |
2 files changed, 161 insertions, 24 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 97c468a9389..aff40937edb 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.16 1998/06/15 19:29:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.17 1998/07/19 05:49:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -342,23 +342,41 @@ ApplyRetrieveRule(Query *parsetree, OffsetVarNodes(rule_action->qual, rt_length); OffsetVarNodes((Node *) rule_action->targetList, rt_length); OffsetVarNodes(rule_qual, rt_length); + + OffsetVarNodes((Node *) rule_action->groupClause, rt_length); + OffsetVarNodes((Node *) rule_action->havingQual, rt_length); + ChangeVarNodes(rule_action->qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); ChangeVarNodes((Node *) rule_action->targetList, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0); + + ChangeVarNodes((Node *) rule_action->groupClause, + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); + ChangeVarNodes((Node *) rule_action->havingQual, + PRS2_CURRENT_VARNO + rt_length, rt_index, 0); + if (relation_level) { - HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index, - modified); + HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index, + modified); } else { - HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList, - rt_index, rule->attrno, modified, &badsql); + HandleRIRAttributeRule(parsetree, rtable, rule_action->targetList, + rt_index, rule->attrno, modified, &badsql); } - if (*modified && !badsql) - AddQual(parsetree, rule_action->qual); + if (*modified && !badsql) { + AddQual(parsetree, rule_action->qual); + /* This will only work if the query made to the view defined by the following + * groupClause groups by the same attributes or does not use group at all! */ + if (parsetree->groupClause == NULL) + parsetree->groupClause=rule_action->groupClause; + AddHavingQual(parsetree, rule_action->havingQual); + parsetree->hasAggs = (rule_action->hasAggs || parsetree->hasAggs); + parsetree->hasSubLinks = (rule_action->hasSubLinks || parsetree->hasSubLinks); + } } static List * @@ -680,6 +698,8 @@ List * QueryRewrite(Query *parsetree) { QueryRewriteSubLink(parsetree->qual); + QueryRewriteSubLink(parsetree->havingQual); + return QueryRewriteOne(parsetree); } @@ -730,6 +750,8 @@ QueryRewriteSubLink(Node *node) * SubLink we don't process it as part of this loop. */ QueryRewriteSubLink((Node *) query->qual); + + QueryRewriteSubLink((Node *) query->havingQual); ret = QueryRewriteOne(query); if (!ret) diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 0c124a36389..7606698afdf 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.14 1998/06/15 19:29:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.15 1998/07/19 05:49:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -55,6 +55,14 @@ OffsetVarNodes(Node *node, int offset) OffsetVarNodes(agg->target, offset); } break; + /* This has to be done to make queries using groupclauses work on views */ + case T_GroupClause: + { + GroupClause *group = (GroupClause *) node; + + OffsetVarNodes((Node *)(group->entry), offset); + } + break; case T_Expr: { Expr *expr = (Expr *) node; @@ -78,6 +86,22 @@ OffsetVarNodes(Node *node, int offset) OffsetVarNodes(lfirst(l), offset); } break; + case T_SubLink: + { + SubLink *sublink = (SubLink *) node; + + /* We also have to adapt the variables used in sublink->lefthand + * and sublink->oper */ + OffsetVarNodes((Node *)(sublink->lefthand), offset); + + /* Make sure the first argument of sublink->oper points to the + * same var as sublink->lefthand does otherwise we will + * run into troubles using aggregates (aggno will not be + * set correctly) */ + lfirst(((Expr *) lfirst(sublink->oper))->args) = + lfirst(sublink->lefthand); + } + break; default: /* ignore the others */ break; @@ -105,6 +129,16 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up) ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up); } break; + /* This has to be done to make queries using groupclauses work on views */ + case T_GroupClause: + { + GroupClause *group = (GroupClause *) node; + + ChangeVarNodes((Node *)(group->entry),old_varno, new_varno, + sublevels_up); + } + break; + case T_Expr: { Expr *expr = (Expr *) node; @@ -122,6 +156,8 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up) var->varno = new_varno; var->varnoold = new_varno; } + if (var->varlevelsup > 0) OffsetVarNodes((Node *)var,3); + } break; case T_List: @@ -139,6 +175,18 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up) ChangeVarNodes((Node *) query->qual, old_varno, new_varno, sublevels_up + 1); + + /* We also have to adapt the variables used in sublink->lefthand + * and sublink->oper */ + ChangeVarNodes((Node *) (sublink->lefthand), old_varno, new_varno, + sublevels_up); + + /* Make sure the first argument of sublink->oper points to the + * same var as sublink->lefthand does otherwise we will + * run into troubles using aggregates (aggno will not be + * set correctly */ + /* lfirst(((Expr *) lfirst(sublink->oper))->args) = + lfirst(sublink->lefthand); */ } break; default: @@ -165,6 +213,26 @@ AddQual(Query *parsetree, Node *qual) (Node *) make_andclause(makeList(parsetree->qual, copy, -1)); } +/* Adds the given havingQual to the one already contained in the parsetree just as + * AddQual does for the normal 'where' qual */ +void +AddHavingQual(Query *parsetree, Node *havingQual) +{ + Node *copy, *old; + + if (havingQual == NULL) + return; + + copy = copyObject(havingQual); + old = parsetree->havingQual; + if (old == NULL) + parsetree->havingQual = copy; + else + parsetree->havingQual = + (Node *) make_andclause(makeList(parsetree->havingQual, copy, -1)); +} + + void AddNotQual(Query *parsetree, Node *qual) { @@ -485,9 +553,18 @@ nodeHandleViewRule(Node **nodePtr, Aggreg *agg = (Aggreg *) node; nodeHandleViewRule(&(agg->target), rtable, targetlist, - rt_index, modified, sublevels_up); + rt_index, modified, sublevels_up); } break; + /* This has to be done to make queries using groupclauses work on views */ + case T_GroupClause: + { + GroupClause *group = (GroupClause *) node; + + nodeHandleViewRule((Node **) (&(group->entry)), rtable, targetlist, + rt_index, modified, sublevels_up); + } + break; case T_Expr: { Expr *expr = (Expr *) node; @@ -503,20 +580,40 @@ nodeHandleViewRule(Node **nodePtr, int this_varno = var->varno; int this_varlevelsup = var->varlevelsup; Node *n; - + if (this_varno == rt_index && - this_varlevelsup == sublevels_up) - { - n = FindMatchingTLEntry(targetlist, - get_attname(getrelid(this_varno, - rtable), - var->varattno)); - if (n == NULL) - *nodePtr = make_null(((Var *) node)->vartype); - else - *nodePtr = n; - *modified = TRUE; - } + this_varlevelsup == sublevels_up) + { + n = FindMatchingTLEntry(targetlist, + get_attname(getrelid(this_varno, + rtable), + var->varattno)); + if (n == NULL) + { + *nodePtr = make_null(((Var *) node)->vartype); + } + + else + /* This is a hack: The varlevelsup of the orignal + * variable and the new one should be the same. + * Normally we adapt the node by changing a pointer + * to point to a var contained in 'targetlist'. + * In the targetlist all varlevelsups are 0 + * so if we want to change it to the original value + * we have to copy the node before! (Maybe this will + * cause troubles with some sophisticated queries on + * views?) */ + { + if(this_varlevelsup>0){ + *nodePtr = copyObject(n); + } + else { + *nodePtr = n; + } + ((Var *)*nodePtr)->varlevelsup = this_varlevelsup; + } + *modified = TRUE; + } break; } case T_List: @@ -537,7 +634,20 @@ nodeHandleViewRule(Node **nodePtr, Query *query = (Query *) sublink->subselect; nodeHandleViewRule((Node **) &(query->qual), rtable, targetlist, - rt_index, modified, sublevels_up + 1); + rt_index, modified, sublevels_up + 1); + + /* We also have to adapt the variables used in sublink->lefthand + * and sublink->oper */ + nodeHandleViewRule((Node **) &(sublink->lefthand), rtable, + targetlist, rt_index, modified, sublevels_up); + + /* Make sure the first argument of sublink->oper points to the + * same var as sublink->lefthand does otherwise we will + * run into troubles using aggregates (aggno will not be + * set correctly */ + pfree(lfirst(((Expr *) lfirst(sublink->oper))->args)); + lfirst(((Expr *) lfirst(sublink->oper))->args) = + lfirst(sublink->lefthand); } break; default: @@ -553,9 +663,14 @@ HandleViewRule(Query *parsetree, int rt_index, int *modified) { - nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index, modified, 0); nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist, rt_index, modified, 0); + /* The variables in the havingQual and groupClause also have to be adapted */ + nodeHandleViewRule(&parsetree->havingQual, rtable, targetlist, rt_index, + modified, 0); + nodeHandleViewRule((Node **) (&(parsetree->groupClause)), rtable, targetlist, rt_index, + modified, 0); } + |