OSDN Git Service

Replace rewriter's checkQueryHasAggs and checkQueryHasSubLink
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Jun 1999 01:26:56 +0000 (01:26 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Jun 1999 01:26:56 +0000 (01:26 +0000)
with expression_tree_walker-based code.  The former failed to cope with
expressions containing SubLinks, and the latter returned TRUE for both
SubLinks and Aggrefs (cut-and-paste bug?).  There is a lot more scope for
using expression_tree_walker in this module, but I'll restrain myself
until the 6.6 split occurs from touching not-demonstrably-broken code.

src/backend/rewrite/rewriteHandler.c

index 37cd175..e14452a 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.46 1999/05/26 12:55:46 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.47 1999/06/21 01:26:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,6 +29,7 @@
 #include "parser/parse_target.h"
 
 #include "parser/analyze.h"
+#include "optimizer/clauses.h"
 #include "optimizer/prep.h"
 
 #include "rewrite/rewriteSupport.h"
@@ -60,6 +61,9 @@ static void modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr);
 static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree);
 static void modifyAggrefQual(Node **nodePtr, Query *parsetree);
 static bool checkQueryHasAggs(Node *node);
+static bool checkQueryHasAggs_walker(Node *node, void *context);
+static bool checkQueryHasSubLink(Node *node);
+static bool checkQueryHasSubLink_walker(Node *node, void *context);
 static Query *fireRIRrules(Query *parsetree);
 static Query *Except_Intersect_Rewrite(Query *parsetree);
 static void check_targetlists_are_compatible(List *prev_target,
@@ -1302,242 +1306,41 @@ modifyAggrefQual(Node **nodePtr, Query *parsetree)
 static bool
 checkQueryHasAggs(Node *node)
 {
-       if (node == NULL)
-               return FALSE;
-
-       switch (nodeTag(node))
-       {
-               case T_TargetEntry:
-                       {
-                               TargetEntry *tle = (TargetEntry *) node;
-
-                               return checkQueryHasAggs((Node *) (tle->expr));
-                       }
-                       break;
-
-               case T_Aggref:
-                       return TRUE;
-
-               case T_Expr:
-                       {
-                               Expr       *exp = (Expr *) node;
-
-                               return checkQueryHasAggs((Node *) (exp->args));
-                       }
-                       break;
-
-               case T_Iter:
-                       {
-                               Iter       *iter = (Iter *) node;
-
-                               return checkQueryHasAggs((Node *) (iter->iterexpr));
-                       }
-                       break;
-
-               case T_ArrayRef:
-                       {
-                               ArrayRef   *ref = (ArrayRef *) node;
-
-                               if (checkQueryHasAggs((Node *) (ref->refupperindexpr)))
-                                       return TRUE;
-
-                               if (checkQueryHasAggs((Node *) (ref->reflowerindexpr)))
-                                       return TRUE;
-
-                               if (checkQueryHasAggs((Node *) (ref->refexpr)))
-                                       return TRUE;
-
-                               if (checkQueryHasAggs((Node *) (ref->refassgnexpr)))
-                                       return TRUE;
-
-                               return FALSE;
-                       }
-                       break;
-
-               case T_Var:
-                       return FALSE;
-
-               case T_Param:
-                       return FALSE;
-
-               case T_Const:
-                       return FALSE;
-
-               case T_List:
-                       {
-                               List       *l;
-
-                               foreach(l, (List *) node)
-                               {
-                                       if (checkQueryHasAggs((Node *) lfirst(l)))
-                                               return TRUE;
-                               }
-                               return FALSE;
-                       }
-                       break;
-
-               case T_CaseExpr:
-                       {
-                               CaseExpr   *exp = (CaseExpr *) node;
-
-                               if (checkQueryHasAggs((Node *) (exp->args)))
-                                       return TRUE;
-
-                               if (checkQueryHasAggs((Node *) (exp->defresult)))
-                                       return TRUE;
-
-                               return FALSE;
-                       }
-                       break;
-
-               case T_CaseWhen:
-                       {
-                               CaseWhen   *when = (CaseWhen *) node;
-
-                               if (checkQueryHasAggs((Node *) (when->expr)))
-                                       return TRUE;
-
-                               if (checkQueryHasAggs((Node *) (when->result)))
-                                       return TRUE;
-
-                               return FALSE;
-                       }
-                       break;
-
-               default:
-                       elog(NOTICE, "unknown node tag %d in checkQueryHasAggs()", nodeTag(node));
-                       elog(NOTICE, "Node is: %s", nodeToString(node));
-                       break;
-
-
-       }
-
-       return FALSE;
+       return checkQueryHasAggs_walker(node, NULL);
 }
 
+static bool
+checkQueryHasAggs_walker(Node *node, void *context)
+{
+       if (node == NULL)
+               return false;
+       if (IsA(node, Aggref))
+               return true;                    /* abort the tree traversal and return true */
+       return expression_tree_walker(node, checkQueryHasAggs_walker, context);
+}
 
 /*
  * checkQueryHasSubLink -
- *     Queries marked hasAggs might not have them any longer after
+ *     Queries marked hasSubLinks might not have them any longer after
  *     rewriting. Check it.
  */
 static bool
 checkQueryHasSubLink(Node *node)
 {
-       if (node == NULL)
-               return FALSE;
-
-       switch (nodeTag(node))
-       {
-               case T_TargetEntry:
-                       {
-                               TargetEntry *tle = (TargetEntry *) node;
-
-                               return checkQueryHasSubLink((Node *) (tle->expr));
-                       }
-                       break;
-
-               case T_Aggref:
-                       return TRUE;
-
-               case T_Expr:
-                       {
-                               Expr       *exp = (Expr *) node;
-
-                               return checkQueryHasSubLink((Node *) (exp->args));
-                       }
-                       break;
-
-               case T_Iter:
-                       {
-                               Iter       *iter = (Iter *) node;
-
-                               return checkQueryHasSubLink((Node *) (iter->iterexpr));
-                       }
-                       break;
-
-               case T_ArrayRef:
-                       {
-                               ArrayRef   *ref = (ArrayRef *) node;
-
-                               if (checkQueryHasSubLink((Node *) (ref->refupperindexpr)))
-                                       return TRUE;
-
-                               if (checkQueryHasSubLink((Node *) (ref->reflowerindexpr)))
-                                       return TRUE;
-
-                               if (checkQueryHasSubLink((Node *) (ref->refexpr)))
-                                       return TRUE;
-
-                               if (checkQueryHasSubLink((Node *) (ref->refassgnexpr)))
-                                       return TRUE;
-
-                               return FALSE;
-                       }
-                       break;
-
-               case T_Var:
-                       return FALSE;
-
-               case T_Param:
-                       return FALSE;
-
-               case T_Const:
-                       return FALSE;
-
-               case T_List:
-                       {
-                               List       *l;
-
-                               foreach(l, (List *) node)
-                               {
-                                       if (checkQueryHasSubLink((Node *) lfirst(l)))
-                                               return TRUE;
-                               }
-                               return FALSE;
-                       }
-                       break;
-
-               case T_CaseExpr:
-                       {
-                               CaseExpr   *exp = (CaseExpr *) node;
-
-                               if (checkQueryHasSubLink((Node *) (exp->args)))
-                                       return TRUE;
-
-                               if (checkQueryHasSubLink((Node *) (exp->defresult)))
-                                       return TRUE;
-
-                               return FALSE;
-                       }
-                       break;
-
-               case T_CaseWhen:
-                       {
-                               CaseWhen   *when = (CaseWhen *) node;
-
-                               if (checkQueryHasSubLink((Node *) (when->expr)))
-                                       return TRUE;
-
-                               if (checkQueryHasSubLink((Node *) (when->result)))
-                                       return TRUE;
-
-                               return FALSE;
-                       }
-                       break;
-
-               case T_SubLink:
-                       return TRUE;
-
-               default:
-                       elog(NOTICE, "unknown node tag %d in checkQueryHasSubLink()", nodeTag(node));
-                       elog(NOTICE, "Node is: %s", nodeToString(node));
-                       break;
-
-
-       }
+       return checkQueryHasSubLink_walker(node, NULL);
+}
 
-       return FALSE;
+static bool
+checkQueryHasSubLink_walker(Node *node, void *context)
+{
+       if (node == NULL)
+               return false;
+       if (IsA(node, SubLink))
+               return true;                    /* abort the tree traversal and return true */
+       /* Note: we assume the tree has not yet been rewritten by subselect.c,
+        * therefore we will find bare SubLink nodes and not SUBPLAN nodes.
+        */
+       return expression_tree_walker(node, checkQueryHasSubLink_walker, context);
 }