summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTom Lane2012-04-26 00:20:33 +0000
committerTom Lane2012-04-26 00:20:33 +0000
commit9fa82c980935ef4aee18fabe8da20ae2198b052a (patch)
treec8345ab2665cc49129875f9921d6f6de1b097834 /src/test
parentc62b8eaae11aaa69a2b71bc63f9f78ca72eb412c (diff)
Fix planner's handling of RETURNING lists in writable CTEs.
setrefs.c failed to do "rtoffset" adjustment of Vars in RETURNING lists, which meant they were left with the wrong varnos when the RETURNING list was in a subquery. That was never possible before writable CTEs, of course, but now it's broken. The executor fails to notice any problem because ExecEvalVar just references the ecxt_scantuple for any normal varno; but EXPLAIN breaks when the varno is wrong, as illustrated in a recent complaint from Bartosz Dmytrak. Since the eventual rtoffset of the subquery is not known at the time we are preparing its plan node, the previous scheme of executing set_returning_clause_references() at that time cannot handle this adjustment. Fortunately, it turns out that we don't really need to do it that way, because all the needed information is available during normal setrefs.c execution; we just have to dig it out of the ModifyTable node. So, do that, and get rid of the kluge of early setrefs processing of RETURNING lists. (This is a little bit of a cheat in the case of inherited UPDATE/DELETE, because we are not passing a "root" struct that corresponds exactly to what the subplan was built with. But that doesn't matter, and anyway this is less ugly than early setrefs processing was.) Back-patch to 9.1, where the problem became possible to hit.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/with.out42
-rw-r--r--src/test/regress/sql/with.sql6
2 files changed, 48 insertions, 0 deletions
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index fae92cd37bf..57e178afa94 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -1857,6 +1857,48 @@ SELECT * FROM parent;
42 | new2
(5 rows)
+-- check EXPLAIN VERBOSE for a wCTE with RETURNING
+EXPLAIN (VERBOSE, COSTS OFF)
+WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 )
+DELETE FROM a USING wcte WHERE aa = q2;
+ QUERY PLAN
+--------------------------------------------------
+ Delete on public.a
+ CTE wcte
+ -> Insert on public.int8_tbl
+ Output: int8_tbl.q2
+ -> Result
+ Output: 42::bigint, 47::bigint
+ -> Nested Loop
+ Output: public.a.ctid, wcte.*
+ Join Filter: (public.a.aa = wcte.q2)
+ -> Seq Scan on public.a
+ Output: public.a.ctid, public.a.aa
+ -> CTE Scan on wcte
+ Output: wcte.*, wcte.q2
+ -> Nested Loop
+ Output: public.a.ctid, wcte.*
+ Join Filter: (public.a.aa = wcte.q2)
+ -> Seq Scan on public.b a
+ Output: public.a.ctid, public.a.aa
+ -> CTE Scan on wcte
+ Output: wcte.*, wcte.q2
+ -> Nested Loop
+ Output: public.a.ctid, wcte.*
+ Join Filter: (public.a.aa = wcte.q2)
+ -> Seq Scan on public.c a
+ Output: public.a.ctid, public.a.aa
+ -> CTE Scan on wcte
+ Output: wcte.*, wcte.q2
+ -> Nested Loop
+ Output: public.a.ctid, wcte.*
+ Join Filter: (public.a.aa = wcte.q2)
+ -> Seq Scan on public.d a
+ Output: public.a.ctid, public.a.aa
+ -> CTE Scan on wcte
+ Output: wcte.*, wcte.q2
+(34 rows)
+
-- error cases
-- data-modifying WITH tries to use its own output
WITH RECURSIVE t AS (
diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql
index 1479422c9c6..9c6732b9611 100644
--- a/src/test/regress/sql/with.sql
+++ b/src/test/regress/sql/with.sql
@@ -791,6 +791,12 @@ DELETE FROM parent USING wcte WHERE id = newid;
SELECT * FROM parent;
+-- check EXPLAIN VERBOSE for a wCTE with RETURNING
+
+EXPLAIN (VERBOSE, COSTS OFF)
+WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 )
+DELETE FROM a USING wcte WHERE aa = q2;
+
-- error cases
-- data-modifying WITH tries to use its own output