mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Make subqueries rewrite properly.
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.10 1998/01/15 19:00:07 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.11 1998/01/21 04:24:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -28,7 +28,8 @@
|
||||
#include "nodes/plannodes.h"
|
||||
#include "optimizer/clauses.h"
|
||||
|
||||
static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node);
|
||||
static void ResolveNew(RewriteInfo *info, List *targetlist,
|
||||
Node **node, int sublevels_up);
|
||||
|
||||
|
||||
|
||||
@ -85,7 +86,7 @@ OffsetVarNodes(Node *node, int offset)
|
||||
}
|
||||
|
||||
void
|
||||
ChangeVarNodes(Node *node, int old_varno, int new_varno)
|
||||
ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
|
||||
{
|
||||
if (node == NULL)
|
||||
return;
|
||||
@ -95,28 +96,29 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) node;
|
||||
|
||||
ChangeVarNodes(tle->expr, old_varno, new_varno);
|
||||
ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Aggreg:
|
||||
{
|
||||
Aggreg *agg = (Aggreg *) node;
|
||||
|
||||
ChangeVarNodes(agg->target, old_varno, new_varno);
|
||||
ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Expr:
|
||||
{
|
||||
Expr *expr = (Expr *) node;
|
||||
|
||||
ChangeVarNodes((Node *) expr->args, old_varno, new_varno);
|
||||
ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
Var *var = (Var *) node;
|
||||
|
||||
if (var->varno == old_varno)
|
||||
if (var->varno == old_varno &&
|
||||
var->varlevelsup == sublevels_up)
|
||||
{
|
||||
var->varno = new_varno;
|
||||
var->varnoold = new_varno;
|
||||
@ -128,9 +130,16 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno)
|
||||
List *l;
|
||||
|
||||
foreach(l, (List *) node)
|
||||
{
|
||||
ChangeVarNodes(lfirst(l), old_varno, new_varno);
|
||||
}
|
||||
ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_SubLink:
|
||||
{
|
||||
SubLink *sublink = (SubLink *) node;
|
||||
Query *query = (Query *)sublink->subselect;
|
||||
|
||||
ChangeVarNodes((Node *)query->qual, old_varno, new_varno,
|
||||
sublevels_up + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -237,7 +246,8 @@ FindMatchingTLEntry(List *tlist, char *e_attname)
|
||||
}
|
||||
|
||||
static void
|
||||
ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
|
||||
ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
|
||||
int sublevels_up)
|
||||
{
|
||||
Node *node = *nodePtr;
|
||||
|
||||
@ -247,20 +257,25 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_TargetEntry:
|
||||
ResolveNew(info, targetlist, &((TargetEntry *) node)->expr);
|
||||
ResolveNew(info, targetlist, &((TargetEntry *) node)->expr,
|
||||
sublevels_up);
|
||||
break;
|
||||
case T_Aggreg:
|
||||
ResolveNew(info, targetlist, &((Aggreg *) node)->target);
|
||||
ResolveNew(info, targetlist, &((Aggreg *) node)->target,
|
||||
sublevels_up);
|
||||
break;
|
||||
case T_Expr:
|
||||
ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)));
|
||||
ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
|
||||
sublevels_up);
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
int this_varno = (int) ((Var *) node)->varno;
|
||||
Node *n;
|
||||
int this_varno = (int) ((Var *) node)->varno;
|
||||
int this_varlevelsup = (int) ((Var *) node)->varlevelsup;
|
||||
Node *n;
|
||||
|
||||
if (this_varno == info->new_varno)
|
||||
if (this_varno == info->new_varno &&
|
||||
this_varlevelsup == sublevels_up)
|
||||
{
|
||||
n = FindMatchingNew(targetlist,
|
||||
((Var *) node)->varattno);
|
||||
@ -288,11 +303,18 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
|
||||
List *l;
|
||||
|
||||
foreach(l, (List *) node)
|
||||
{
|
||||
ResolveNew(info, targetlist, (Node **) &(lfirst(l)));
|
||||
}
|
||||
ResolveNew(info, targetlist, (Node **) &(lfirst(l)),
|
||||
sublevels_up);
|
||||
break;
|
||||
}
|
||||
case T_SubLink:
|
||||
{
|
||||
SubLink *sublink = (SubLink *) node;
|
||||
Query *query = (Query *)sublink->subselect;
|
||||
|
||||
ResolveNew(info, targetlist, (Node **)&(query->qual), sublevels_up + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* ignore the others */
|
||||
break;
|
||||
@ -303,8 +325,8 @@ void
|
||||
FixNew(RewriteInfo *info, Query *parsetree)
|
||||
{
|
||||
ResolveNew(info, parsetree->targetList,
|
||||
(Node **) &(info->rule_action->targetList));
|
||||
ResolveNew(info, parsetree->targetList, &info->rule_action->qual);
|
||||
(Node **) &(info->rule_action->targetList), 0);
|
||||
ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -314,7 +336,8 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
|
||||
int rt_index,
|
||||
int attr_num,
|
||||
int *modified,
|
||||
int *badsql)
|
||||
int *badsql,
|
||||
int sublevels_up)
|
||||
{
|
||||
Node *node = *nodePtr;
|
||||
|
||||
@ -322,24 +345,13 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
|
||||
return;
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_List:
|
||||
{
|
||||
List *i;
|
||||
|
||||
foreach(i, (List *) node)
|
||||
{
|
||||
nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_TargetEntry:
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) node;
|
||||
|
||||
nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
|
||||
rt_index, attr_num, modified, badsql);
|
||||
rt_index, attr_num, modified, badsql,
|
||||
sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Aggreg:
|
||||
@ -347,7 +359,8 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
|
||||
Aggreg *agg = (Aggreg *) node;
|
||||
|
||||
nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
|
||||
rt_index, attr_num, modified, badsql);
|
||||
rt_index, attr_num, modified, badsql,
|
||||
sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Expr:
|
||||
@ -356,18 +369,19 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
|
||||
|
||||
nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql);
|
||||
modified, badsql,
|
||||
sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
int this_varno = (int) ((Var *) node)->varno;
|
||||
NameData name_to_look_for;
|
||||
|
||||
MemSet(name_to_look_for.data, 0, NAMEDATALEN);
|
||||
int this_varno = ((Var *) node)->varno;
|
||||
int this_varattno = ((Var *) node)->varattno;
|
||||
int this_varlevelsup = ((Var *) node)->varlevelsup;
|
||||
|
||||
if (this_varno == rt_index &&
|
||||
((Var *) node)->varattno == attr_num)
|
||||
this_varattno == attr_num &&
|
||||
this_varlevelsup == sublevels_up)
|
||||
{
|
||||
if (((Var *) node)->vartype == 32)
|
||||
{ /* HACK */
|
||||
@ -378,29 +392,50 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
|
||||
}
|
||||
else
|
||||
{
|
||||
NameData name_to_look_for;
|
||||
|
||||
name_to_look_for.data[0] = '\0';
|
||||
namestrcpy(&name_to_look_for,
|
||||
(char *) get_attname(getrelid(this_varno,
|
||||
rtable),
|
||||
attr_num));
|
||||
if (name_to_look_for.data[0])
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
|
||||
if (n == NULL)
|
||||
*nodePtr = make_null(((Var *) node)->vartype);
|
||||
else
|
||||
*nodePtr = n;
|
||||
*modified = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name_to_look_for.data[0])
|
||||
{
|
||||
Node *n;
|
||||
}
|
||||
break;
|
||||
case T_List:
|
||||
{
|
||||
List *i;
|
||||
|
||||
n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
|
||||
if (n == NULL)
|
||||
{
|
||||
*nodePtr = make_null(((Var *) node)->vartype);
|
||||
}
|
||||
else
|
||||
{
|
||||
*nodePtr = n;
|
||||
}
|
||||
*modified = TRUE;
|
||||
foreach(i, (List *) node)
|
||||
{
|
||||
nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql, sublevels_up);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_SubLink:
|
||||
{
|
||||
SubLink *sublink = (SubLink *) node;
|
||||
Query *query = (Query *)sublink->subselect;
|
||||
|
||||
nodeHandleRIRAttributeRule((Node **)&(query->qual), rtable, targetlist,
|
||||
rt_index, attr_num, modified, badsql,
|
||||
sublevels_up + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* ignore the others */
|
||||
break;
|
||||
@ -423,9 +458,9 @@ HandleRIRAttributeRule(Query *parsetree,
|
||||
|
||||
nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
|
||||
targetlist, rt_index, attr_num,
|
||||
modified, badsql);
|
||||
modified, badsql, 0);
|
||||
nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
|
||||
rt_index, attr_num, modified, badsql);
|
||||
rt_index, attr_num, modified, badsql, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -434,7 +469,8 @@ nodeHandleViewRule(Node **nodePtr,
|
||||
List *rtable,
|
||||
List *targetlist,
|
||||
int rt_index,
|
||||
int *modified)
|
||||
int *modified,
|
||||
int sublevels_up)
|
||||
{
|
||||
Node *node = *nodePtr;
|
||||
|
||||
@ -443,24 +479,12 @@ nodeHandleViewRule(Node **nodePtr,
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_List:
|
||||
{
|
||||
List *l;
|
||||
|
||||
foreach(l, (List *) node)
|
||||
{
|
||||
nodeHandleViewRule((Node **) (&(lfirst(l))),
|
||||
rtable, targetlist,
|
||||
rt_index, modified);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_TargetEntry:
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) node;
|
||||
|
||||
nodeHandleViewRule(&(tle->expr), rtable, targetlist,
|
||||
rt_index, modified);
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Aggreg:
|
||||
@ -468,7 +492,7 @@ nodeHandleViewRule(Node **nodePtr,
|
||||
Aggreg *agg = (Aggreg *) node;
|
||||
|
||||
nodeHandleViewRule(&(agg->target), rtable, targetlist,
|
||||
rt_index, modified);
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Expr:
|
||||
@ -477,33 +501,52 @@ nodeHandleViewRule(Node **nodePtr,
|
||||
|
||||
nodeHandleViewRule((Node **) (&(expr->args)),
|
||||
rtable, targetlist,
|
||||
rt_index, modified);
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
break;
|
||||
case T_Var:
|
||||
{
|
||||
Var *var = (Var *) node;
|
||||
int this_varno = var->varno;
|
||||
int this_varlevelsup = var->varlevelsup;
|
||||
Node *n;
|
||||
|
||||
if (this_varno == rt_index)
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_List:
|
||||
{
|
||||
List *l;
|
||||
|
||||
foreach(l, (List *) node)
|
||||
{
|
||||
nodeHandleViewRule((Node **) (&(lfirst(l))),
|
||||
rtable, targetlist,
|
||||
rt_index, modified, sublevels_up);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_SubLink:
|
||||
{
|
||||
SubLink *sublink = (SubLink *) node;
|
||||
Query *query = (Query *)sublink->subselect;
|
||||
|
||||
nodeHandleViewRule((Node **)&(query->qual), rtable, targetlist,
|
||||
rt_index, modified, sublevels_up + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* ignore the others */
|
||||
break;
|
||||
@ -519,7 +562,7 @@ HandleViewRule(Query *parsetree,
|
||||
{
|
||||
|
||||
nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
|
||||
modified);
|
||||
modified, 0);
|
||||
nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
|
||||
rt_index, modified);
|
||||
rt_index, modified, 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user