*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.7 1998/01/15 19:00:06 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.8 1998/01/21 04:24:34 momjian Exp $
*
*-------------------------------------------------------------------------
*/
* otherwise, we return false
*/
static bool
-nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
+nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum,
+ int sublevels_up)
{
if (node == NULL)
return FALSE;
{
Expr *expr = (Expr *) node;
- return
- nodeThisLockWasTriggered((Node *) expr->args, varno, attnum);
+ return nodeThisLockWasTriggered((Node *) expr->args, varno,
+ attnum, sublevels_up);
}
break;
case T_TargetEntry:
{
TargetEntry *tle = (TargetEntry *) node;
- return
- nodeThisLockWasTriggered(tle->expr, varno, attnum);
+ return nodeThisLockWasTriggered(tle->expr, varno, attnum,
+ sublevels_up);
}
break;
case T_Aggreg:
{
Aggreg *agg = (Aggreg *) node;
- return
- nodeThisLockWasTriggered(agg->target, varno, attnum);
+ return nodeThisLockWasTriggered(agg->target, varno, attnum,
+ sublevels_up);
}
break;
case T_List:
foreach(l, (List *) node)
{
- if (nodeThisLockWasTriggered(lfirst(l), varno, attnum))
+ if (nodeThisLockWasTriggered(lfirst(l), varno, attnum,
+ sublevels_up))
return TRUE;
}
return FALSE;
}
break;
+ case T_SubLink:
+ {
+ SubLink *sublink = (SubLink *) node;
+ Query *query = (Query *)sublink->subselect;
+
+ return nodeThisLockWasTriggered(query->qual, varno, attnum,
+ sublevels_up + 1);
+ }
+ break;
default:
break;
}
Query *parsetree)
{
- if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum))
+ if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum, 0))
return true;
- if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum))
+ if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum, 0))
return true;
return false;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.10 1998/01/09 05:48:17 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.11 1998/01/21 04:24:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "commands/creatinh.h"
#include "access/heapam.h"
-static void
-ApplyRetrieveRule(Query *parsetree, RewriteRule *rule,
+static void ApplyRetrieveRule(Query *parsetree, RewriteRule *rule,
int rt_index, int relation_level, int *modified);
-static List *
-fireRules(Query *parsetree, int rt_index, CmdType event,
+static List *fireRules(Query *parsetree, int rt_index, CmdType event,
bool *instead_flag, List *locks, List **qual_products);
+static void QueryRewriteSubLink(Node *node);
+static List *QueryRewriteOne(Query *parsetree);
static List *deepRewriteQuery(Query *parsetree);
/*
OffsetVarNodes((Node *) info->rule_action->targetList, rt_length);
OffsetVarNodes(info->rule_qual, rt_length);
ChangeVarNodes((Node *) info->rule_action->qual,
- PRS2_CURRENT_VARNO + rt_length, rt_index);
+ PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
ChangeVarNodes((Node *) info->rule_action->targetList,
- PRS2_CURRENT_VARNO + rt_length, rt_index);
+ PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
ChangeVarNodes(info->rule_qual,
- PRS2_CURRENT_VARNO + rt_length, rt_index);
+ PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
/*
* bug here about replace CURRENT -- sort of replace current is
OffsetVarNodes((Node *) rule_action->targetList, rt_length);
OffsetVarNodes(rule_qual, rt_length);
ChangeVarNodes(rule_action->qual,
- PRS2_CURRENT_VARNO + rt_length, rt_index);
+ PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
ChangeVarNodes((Node *) rule_action->targetList,
- PRS2_CURRENT_VARNO + rt_length, rt_index);
- ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index);
+ PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
+ ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
if (relation_level)
{
HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index,
rtable = append(rtable, listCopy(rule_action->rtable));
new_tree->rtable = rtable;
OffsetVarNodes(new_qual, rt_length);
- ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index);
+ ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
}
/* XXX -- where current doesn't work for instead nothing.... yet */
AddNotQual(new_tree, new_qual);
*/
List *
QueryRewrite(Query *parsetree)
+{
+
+ QueryRewriteSubLink(parsetree->qual);
+ return QueryRewriteOne(parsetree);
+}
+
+/*
+ * QueryRewriteSubLink
+ *
+ * This rewrites the SubLink subqueries first, doing the lowest ones first.
+ * We already have code in the main rewrite loops to process correlated
+ * variables from upper queries that exist in subqueries.
+ */
+static void
+QueryRewriteSubLink(Node *node)
+{
+ if (node == NULL)
+ return;
+
+ switch (nodeTag(node))
+ {
+ case T_TargetEntry:
+ break;
+ case T_Aggreg:
+ break;
+ case T_Expr:
+ {
+ Expr *expr = (Expr *) node;
+
+ QueryRewriteSubLink((Node *)expr->args);
+ }
+ break;
+ case T_Var:
+ break;
+ case T_List:
+ {
+ List *l;
+
+ foreach(l, (List *) node)
+ QueryRewriteSubLink(lfirst(l));
+ }
+ break;
+ case T_SubLink:
+ {
+ SubLink *sublink = (SubLink *) node;
+ Query *query = (Query *)sublink->subselect;
+ List *ret;
+
+ /*
+ * Nest down first. We do this so if a rewrite adds a
+ * SubLink we don't process it as part of this loop.
+ */
+ QueryRewriteSubLink((Node *)query->qual);
+
+ ret = QueryRewriteOne(query);
+ if (!ret)
+ sublink->subselect = NULL;
+ else if (lnext(ret) == NIL)
+ sublink->subselect = lfirst(ret);
+ else
+ elog(ERROR,"Don't know how to process subquery that rewrites to multiple queries.");
+ }
+ break;
+ default:
+ /* ignore the others */
+ break;
+ }
+ return;
+}
+
+/*
+ * QueryOneRewrite -
+ * rewrite one query
+ */
+static List *
+QueryRewriteOne(Query *parsetree)
{
numQueryRewriteInvoked = 0;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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);
}
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;
{
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;
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:
}
static void
-ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
+ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
+ int sublevels_up)
{
Node *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);
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;
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
int rt_index,
int attr_num,
int *modified,
- int *badsql)
+ int *badsql,
+ int sublevels_up)
{
Node *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:
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:
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 */
}
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;
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);
}
List *rtable,
List *targetlist,
int rt_index,
- int *modified)
+ int *modified,
+ int sublevels_up)
{
Node *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:
Aggreg *agg = (Aggreg *) node;
nodeHandleViewRule(&(agg->target), rtable, targetlist,
- rt_index, modified);
+ rt_index, modified, sublevels_up);
}
break;
case T_Expr:
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;
{
nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
- modified);
+ modified, 0);
nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
- rt_index, modified);
+ rt_index, modified, 0);
}