Make subqueries rewrite properly.
authorBruce Momjian
Wed, 21 Jan 1998 04:24:46 +0000 (04:24 +0000)
committerBruce Momjian
Wed, 21 Jan 1998 04:24:46 +0000 (04:24 +0000)
src/backend/rewrite/locks.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/include/rewrite/rewriteManip.h

index b0557b042e1ed1f782c67749efd9a94cb886e65a..56bd8e053b76909bb70c8c42e449f3fb2af280b6 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,8 @@
  * 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;
@@ -46,24 +47,24 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
            {
                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:
@@ -72,12 +73,22 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
 
                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;
    }
@@ -96,10 +107,10 @@ thisLockWasTriggered(int varno,
                     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;
index 68f34e6cd5d76dcd2514e952a69e9546f835a606..415ce6e80f8fbcb83492d3bb0d110e321e73256e 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * 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);
 
 /*
@@ -77,11 +77,11 @@ gatherRewriteMeta(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
@@ -292,10 +292,10 @@ ApplyRetrieveRule(Query *parsetree,
    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,
@@ -402,7 +402,7 @@ CopyAndAddQual(Query *parsetree,
        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);
@@ -627,6 +627,82 @@ static int numQueryRewriteInvoked = 0;
  */
 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;
 
index cd5f5e16a4d73c365adbfca5e1e515073ae9b1ce..493e0c4c4aebcfb853231537f54f93aa4df5de15 100644 (file)
@@ -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);
 }
index 175cdd6ca88859d974a6776f6a46c1a6ec81f606..c564dbf1d31b72fb86bf746af537aac4a125c8b5 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteManip.h,v 1.5 1997/11/26 01:14:25 momjian Exp $
+ * $Id: rewriteManip.h,v 1.6 1998/01/21 04:24:46 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,8 @@
 
 /* RewriteManip.c */
 void       OffsetVarNodes(Node *node, int offset);
-void       ChangeVarNodes(Node *node, int old_varno, int new_varno);
+void       ChangeVarNodes(Node *node, int old_varno, int new_varno,
+                           int sublevels_up);
 void       AddQual(Query *parsetree, Node *qual);
 void       AddNotQual(Query *parsetree, Node *qual);
 void       FixResdomTypes(List *user_tlist);