aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/subselect.c11
-rw-r--r--src/backend/optimizer/prep/prepqual.c51
2 files changed, 51 insertions, 11 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 3493bfda245..373b05d42fe 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.35 2000/04/12 17:15:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.36 2000/04/14 00:19:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,6 +136,13 @@ make_subplan(SubLink *slink)
PlannerQueryLevel++; /* we become child */
+ /* Check to see if this node was already processed; if so we have
+ * trouble. Someday should change tree representation so that we can
+ * cope with multiple links to the same subquery, but for now...
+ */
+ if (subquery == NULL)
+ elog(ERROR, "make_subplan: invalid expression structure (subquery already processed?)");
+
/*
* For an EXISTS subplan, tell lower-level planner to expect that only
* the first tuple will be retrieved. For ALL and ANY subplans, we
@@ -194,7 +201,7 @@ make_subplan(SubLink *slink)
node->plan_id = PlannerPlanId++;
node->rtable = subquery->rtable;
node->sublink = slink;
- slink->subselect = NULL; /* cool ?! */
+ slink->subselect = NULL; /* cool ?! see error check above! */
/* make parParam list of params coming from current query level */
foreach(lst, plan->extParam)
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index fae694dc264..fed6f66f6a1 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.24 2000/04/12 17:15:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.25 2000/04/14 00:19:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -656,15 +656,26 @@ or_normalize(List *orlist)
foreach(temp, distributable->args)
{
Expr *andclause = lfirst(temp);
+ List *neworlist;
+
+ /*
+ * We are going to insert the orlist into multiple places in the
+ * result expression. For most expression types, it'd be OK to
+ * just have multiple links to the same subtree, but this fails
+ * badly for SubLinks (and perhaps other cases?). For safety,
+ * we make a distinct copy for each place the orlist is inserted.
+ */
+ if (lnext(temp) == NIL)
+ neworlist = orlist; /* can use original tree at the end */
+ else
+ neworlist = copyObject(orlist);
/*
* pull_ors is needed here in case andclause has a top-level OR.
* Then we recursively apply or_normalize, since there might be an
- * AND subclause in the resulting OR-list. Note: we rely on
- * pull_ors to build a fresh list, and not damage the given
- * orlist.
+ * AND subclause in the resulting OR-list.
*/
- andclause = or_normalize(pull_ors(lcons(andclause, orlist)));
+ andclause = or_normalize(pull_ors(lcons(andclause, neworlist)));
andclauses = lappend(andclauses, andclause);
}
@@ -773,15 +784,26 @@ and_normalize(List *andlist)
foreach(temp, distributable->args)
{
Expr *orclause = lfirst(temp);
+ List *newandlist;
+
+ /*
+ * We are going to insert the andlist into multiple places in the
+ * result expression. For most expression types, it'd be OK to
+ * just have multiple links to the same subtree, but this fails
+ * badly for SubLinks (and perhaps other cases?). For safety,
+ * we make a distinct copy for each place the andlist is inserted.
+ */
+ if (lnext(temp) == NIL)
+ newandlist = andlist; /* can use original tree at the end */
+ else
+ newandlist = copyObject(andlist);
/*
* pull_ands is needed here in case orclause has a top-level AND.
* Then we recursively apply and_normalize, since there might be
- * an OR subclause in the resulting AND-list. Note: we rely on
- * pull_ands to build a fresh list, and not damage the given
- * andlist.
+ * an OR subclause in the resulting AND-list.
*/
- orclause = and_normalize(pull_ands(lcons(orclause, andlist)));
+ orclause = and_normalize(pull_ands(lcons(orclause, newandlist)));
orclauses = lappend(orclauses, orclause);
}
@@ -932,6 +954,17 @@ count_bool_nodes(Expr *qual,
count_bool_nodes(get_notclausearg(qual),
nodes, cnfnodes, dnfnodes);
}
+ else if (contain_subplans((Node *) qual))
+ {
+ /* charge extra for subexpressions containing sub-SELECTs,
+ * to discourage us from rearranging them in a way that might
+ * generate N copies of a subselect rather than one. The magic
+ * constant here interacts with the "4x maximum growth" heuristic
+ * in canonicalize_qual().
+ */
+ *nodes = 1.0;
+ *cnfnodes = *dnfnodes = 25.0;
+ }
else
{
/* anything else counts 1 for my purposes */