aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>1999-06-21 01:26:56 +0000
committerTom Lane <tgl@sss.pgh.pa.us>1999-06-21 01:26:56 +0000
commit1f2c6f4f48203dbeaec0bf55a48ae25150d52d35 (patch)
treeb8eed6d4740af291416d8e2d9762e907b2c65a39 /src/backend/rewrite/rewriteHandler.c
parentfd8e580bb7e2793621b14662122ac5cd647b7fb1 (diff)
downloadpostgresql-1f2c6f4f48203dbeaec0bf55a48ae25150d52d35.tar.gz
postgresql-1f2c6f4f48203dbeaec0bf55a48ae25150d52d35.zip
Replace rewriter's checkQueryHasAggs and checkQueryHasSubLink
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.
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c255
1 files changed, 29 insertions, 226 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 37cd175ef5f..e14452ac726 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -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);
}