* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.150 2009/06/11 14:48:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.151 2009/07/06 02:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
break;
case T_CteScan:
- context.paramids =
- bms_add_member(context.paramids,
- ((CteScan *) plan)->cteParam);
+ {
+ /*
+ * You might think we should add the node's cteParam to
+ * paramids, but we shouldn't because that param is just a
+ * linkage mechanism for multiple CteScan nodes for the same
+ * CTE; it is never used for changed-param signaling. What
+ * we have to do instead is to find the referenced CTE plan
+ * and incorporate its external paramids, so that the correct
+ * things will happen if the CTE references outer-level
+ * variables. See test cases for bug #4902.
+ */
+ int plan_id = ((CteScan *) plan)->ctePlanId;
+ Plan *cteplan;
+
+ /* so, do this ... */
+ if (plan_id < 1 || plan_id > list_length(root->glob->subplans))
+ elog(ERROR, "could not find plan for CteScan referencing plan ID %d",
+ plan_id);
+ cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
+ context.paramids =
+ bms_add_members(context.paramids, cteplan->extParam);
+
+#ifdef NOT_USED
+ /* ... but not this */
+ context.paramids =
+ bms_add_member(context.paramids,
+ ((CteScan *) plan)->cteParam);
+#endif
+ }
break;
case T_WorkTableScan:
LINE 2: (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
^
HINT: Cast the output of the non-recursive term to the correct type.
+--
+-- test for bug #4902
+--
+with cte(foo) as ( values(42) ) values((select foo from cte));
+ column1
+---------
+ 42
+(1 row)
+
+with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q;
+ foo
+-----
+ 42
+(1 row)
+
+-- test CTE referencing an outer-level variable (to see that changed-parameter
+-- signaling still works properly after fixing this bug)
+select ( with cte(foo) as ( values(f1) )
+ select (select foo from cte) )
+from int4_tbl;
+ ?column?
+-------------
+ 0
+ 123456
+ -123456
+ 2147483647
+ -2147483647
+(5 rows)
+
+select ( with cte(foo) as ( values(f1) )
+ values((select foo from cte)) )
+from int4_tbl;
+ ?column?
+-------------
+ 0
+ 123456
+ -123456
+ 2147483647
+ -2147483647
+(5 rows)
+
UNION ALL
SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
SELECT * FROM foo;
+
+--
+-- test for bug #4902
+--
+with cte(foo) as ( values(42) ) values((select foo from cte));
+with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q;
+
+-- test CTE referencing an outer-level variable (to see that changed-parameter
+-- signaling still works properly after fixing this bug)
+select ( with cte(foo) as ( values(f1) )
+ select (select foo from cte) )
+from int4_tbl;
+
+select ( with cte(foo) as ( values(f1) )
+ values((select foo from cte)) )
+from int4_tbl;