1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

1) Queries using the having clause on base tables should work well

now. Here some tested features, (examples included in the patch):

1.1) Subselects in the having clause 1.2) Double nested subselects
1.3) Subselects used in the where clause and in the having clause
     simultaneously 1.4) Union Selects using having 1.5) Indexes
on the base relations are used correctly 1.6) Unallowed Queries
are prevented (e.g. qualifications in the
     having clause that belong to the where clause) 1.7) Insert
into as select

2) Queries using the having clause on view relations also work
   but there are some restrictions:

2.1) Create View as Select ... Having ...; using base tables in
the select 2.1.1) The Query rewrite system:

2.1.2) Why are only simple queries allowed against a view from 2.1)
? 2.2) Select ... from testview1, testview2, ... having...; 3) Bug
in ExecMergeJoin ??


Regards Stefan
This commit is contained in:
Bruce Momjian
1998-07-19 05:49:26 +00:00
parent 916710fc91
commit 460b20a43f
13 changed files with 997 additions and 537 deletions

View File

@ -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);
}