aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorJan Wieck <JanWieck@Yahoo.com>1999-05-25 13:16:10 +0000
committerJan Wieck <JanWieck@Yahoo.com>1999-05-25 13:16:10 +0000
commitb122e16a1c5030562e4a20f69e7fa2c08cc02658 (patch)
tree184c3d3689eb97d2c429e51ee462094851ca8ad3 /src/backend/rewrite/rewriteHandler.c
parentf4fadbe4db38d479ac7f2fd7195dcaca5fce33d6 (diff)
downloadpostgresql-b122e16a1c5030562e4a20f69e7fa2c08cc02658.tar.gz
postgresql-b122e16a1c5030562e4a20f69e7fa2c08cc02658.zip
Bugfix - Range table entries that are unused after rewriting should
not be marked inFromCl any longer. Otherwise the planner gets confused and joins over them where in fact it does not have to. Adjust hasSubLinks now with a recursive lookup - could be wrong in multi action rules because parse state isn't reset correctly and all actions in the rule are marked hasSubLinks if one of them has. Jan
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c142
1 files changed, 140 insertions, 2 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 26626d0bb8a..7769d722992 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.43 1999/05/17 18:22:19 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.44 1999/05/25 13:16:10 wieck Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1393,6 +1393,129 @@ checkQueryHasAggs(Node *node)
}
+/*
+ * checkQueryHasSubLink -
+ * Queries marked hasAggs 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 FALSE;
+}
+
+
static Node *
FindMatchingTLEntry(List *tlist, char *e_attname)
{
@@ -2116,10 +2239,23 @@ fireRIRrules(Query *parsetree)
while(rt_index < length(parsetree->rtable)) {
++rt_index;
+ rte = nth(rt_index - 1, parsetree->rtable);
+
if (!rangeTableEntry_used((Node *)parsetree, rt_index, 0))
+ {
+ /*
+ * Unused range table entries must not be marked as coming
+ * from a clause. Otherwise the planner will generate
+ * joins over relations that in fact shouldn't be scanned
+ * at all and the result will contain duplicates
+ *
+ * Jan
+ *
+ */
+ rte->inFromCl = FALSE;
continue;
+ }
- rte = nth(rt_index - 1, parsetree->rtable);
rel = heap_openr(rte->relname);
if (rel->rd_rules == NULL) {
heap_close(rel);
@@ -2705,6 +2841,8 @@ BasicQueryRewrite(Query *parsetree)
if (query->hasAggs)
query->hasAggs = checkQueryHasAggs((Node *)(query->targetList))
| checkQueryHasAggs((Node *)(query->havingQual));
+ query->hasSubLinks = checkQueryHasSubLink((Node *)(query->qual))
+ | checkQueryHasSubLink((Node *)(query->havingQual));
results = lappend(results, query);
}
return results;