aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-07-18 21:40:57 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-07-18 21:40:57 +0000
commitd514ea3fda5b5d89cc5a9386f10ac315c4e18486 (patch)
tree87569e5141bd855d8bc4773178e17a7e25e62bb0 /src
parentcdedfe6af1c426b28b2e0ff522d5d88f195a5d47 (diff)
downloadpostgresql-d514ea3fda5b5d89cc5a9386f10ac315c4e18486.tar.gz
postgresql-d514ea3fda5b5d89cc5a9386f10ac315c4e18486.zip
Fix an old thinko in SS_make_initplan_from_plan, which is used when optimizing
a MIN or MAX aggregate call into an indexscan: the initplan is being made at the current query nesting level and so we shouldn't increment query_level. Though usually harmless, this mistake could lead to bogus "plan should not reference subplan's variable" failures on complex queries. Per bug report from David Sanchez i Gregori.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/subselect.c16
-rw-r--r--src/test/regress/expected/subselect.out22
-rw-r--r--src/test/regress/sql/subselect.sql15
3 files changed, 46 insertions, 7 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 27db5c0433f..6a41138d3b2 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
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.122 2007/02/27 01:11:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.123 2007/07/18 21:40:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1328,11 +1328,14 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
Param *prm;
/*
- * Set up for a new level of subquery. This is just to keep
- * SS_finalize_plan from becoming confused; we don't bother with making
- * a whole new PlannerInfo struct.
+ * We must run SS_finalize_plan(), since that's normally done before a
+ * subplan gets put into the initplan list. However it will try to attach
+ * any pre-existing initplans to this one, which we don't want (they are
+ * siblings not children of this initplan). So, a quick kluge to hide
+ * them. (This is something else that could perhaps be cleaner if we did
+ * extParam/allParam processing in setrefs.c instead of here? See notes
+ * for materialize_finished_plan.)
*/
- root->query_level++;
saved_init_plans = root->init_plans;
root->init_plans = NIL;
@@ -1341,8 +1344,7 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
*/
SS_finalize_plan(root, plan);
- /* Return to outer subquery context */
- root->query_level--;
+ /* Restore outer initplan list */
root->init_plans = saved_init_plans;
/*
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 5f50ba6e00d..a37489b4956 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -386,3 +386,25 @@ select f1, ss1 as relabel from
-2147483647 | 0
(5 rows)
+--
+-- Test cases involving PARAM_EXEC parameters and min/max index optimizations.
+-- Per bug report from David Sanchez i Gregori.
+--
+select * from (
+ select max(unique1) from tenk1 as a
+ where exists (select 1 from tenk1 as b where b.thousand = a.unique2)
+) ss;
+ max
+------
+ 9997
+(1 row)
+
+select * from (
+ select min(unique1) from tenk1 as a
+ where not exists (select 1 from tenk1 as b where b.unique2 = 10000)
+) ss;
+ min
+-----
+ 0
+(1 row)
+
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index 3c501f1d1ba..4f824c05f76 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -236,3 +236,18 @@ select * from shipped_view;
select f1, ss1 as relabel from
(select *, (select sum(f1) from int4_tbl b where f1 >= a.f1) as ss1
from int4_tbl a) ss;
+
+--
+-- Test cases involving PARAM_EXEC parameters and min/max index optimizations.
+-- Per bug report from David Sanchez i Gregori.
+--
+
+select * from (
+ select max(unique1) from tenk1 as a
+ where exists (select 1 from tenk1 as b where b.thousand = a.unique2)
+) ss;
+
+select * from (
+ select min(unique1) from tenk1 as a
+ where not exists (select 1 from tenk1 as b where b.unique2 = 10000)
+) ss;