aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-02-27 15:56:51 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2018-02-27 15:56:51 -0500
commite98a4de7d23a54a6c861795ad8e920a59613e08b (patch)
tree1186827ec34fec9cd236338cca7536a8bce76dcc /src
parentc40e20a83ce521b5b5403b08dde05b0f0641d77f (diff)
downloadpostgresql-e98a4de7d23a54a6c861795ad8e920a59613e08b.tar.gz
postgresql-e98a4de7d23a54a6c861795ad8e920a59613e08b.zip
Use the correct tuplestore read pointer in a NamedTuplestoreScan.
Tom Kazimiers reported that transition tables don't work correctly when they are scanned by more than one executor node. That's because commit 18ce3a4ab allocated separate read pointers for each executor node, as it must, but failed to make them active at the appropriate times. Repair. Thomas Munro Discussion: https://postgr.es/m/20180224034748.bixarv6632vbxgeb%40dewberry.localdomain
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/nodeNamedtuplestorescan.c2
-rw-r--r--src/test/regress/expected/plpgsql.out22
-rw-r--r--src/test/regress/sql/plpgsql.sql26
3 files changed, 50 insertions, 0 deletions
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
index 4d898b1f83e..b260ad25948 100644
--- a/src/backend/executor/nodeNamedtuplestorescan.c
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -40,6 +40,7 @@ NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
* Get the next tuple from tuplestore. Return NULL if no more tuples.
*/
slot = node->ss.ss_ScanTupleSlot;
+ tuplestore_select_read_pointer(node->relation, node->readptr);
(void) tuplestore_gettupleslot(node->relation, true, false, slot);
return slot;
}
@@ -116,6 +117,7 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
* The new read pointer copies its position from read pointer 0, which
* could be anywhere, so explicitly rewind it.
*/
+ tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
tuplestore_rescan(scanstate->relation);
/*
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index d294e536345..722715049c9 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -5559,6 +5559,28 @@ LINE 1: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
QUERY: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
CONTEXT: PL/pgSQL function alter_table_under_transition_tables_upd_func() line 3 at RAISE
--
+-- Test multiple reference to a transition table
+--
+CREATE TABLE multi_test (i int);
+INSERT INTO multi_test VALUES (1);
+CREATE OR REPLACE FUNCTION multi_test_trig() RETURNS trigger
+LANGUAGE plpgsql AS $$
+BEGIN
+ RAISE NOTICE 'count = %', (SELECT COUNT(*) FROM new_test);
+ RAISE NOTICE 'count union = %',
+ (SELECT COUNT(*)
+ FROM (SELECT * FROM new_test UNION ALL SELECT * FROM new_test) ss);
+ RETURN NULL;
+END$$;
+CREATE TRIGGER my_trigger AFTER UPDATE ON multi_test
+ REFERENCING NEW TABLE AS new_test OLD TABLE as old_test
+ FOR EACH STATEMENT EXECUTE PROCEDURE multi_test_trig();
+UPDATE multi_test SET i = i;
+NOTICE: count = 1
+NOTICE: count union = 2
+DROP TABLE multi_test;
+DROP FUNCTION multi_test_trig();
+--
-- Check type parsing and record fetching from partitioned tables
--
CREATE TABLE partitioned_table (a int, b text) PARTITION BY LIST (a);
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index f17cf0b49bf..f405d157bba 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -4504,6 +4504,32 @@ UPDATE alter_table_under_transition_tables
SET id = id;
--
+-- Test multiple reference to a transition table
+--
+
+CREATE TABLE multi_test (i int);
+INSERT INTO multi_test VALUES (1);
+
+CREATE OR REPLACE FUNCTION multi_test_trig() RETURNS trigger
+LANGUAGE plpgsql AS $$
+BEGIN
+ RAISE NOTICE 'count = %', (SELECT COUNT(*) FROM new_test);
+ RAISE NOTICE 'count union = %',
+ (SELECT COUNT(*)
+ FROM (SELECT * FROM new_test UNION ALL SELECT * FROM new_test) ss);
+ RETURN NULL;
+END$$;
+
+CREATE TRIGGER my_trigger AFTER UPDATE ON multi_test
+ REFERENCING NEW TABLE AS new_test OLD TABLE as old_test
+ FOR EACH STATEMENT EXECUTE PROCEDURE multi_test_trig();
+
+UPDATE multi_test SET i = i;
+
+DROP TABLE multi_test;
+DROP FUNCTION multi_test_trig();
+
+--
-- Check type parsing and record fetching from partitioned tables
--