Commit e98a4de7 authored by Tom Lane's avatar Tom Lane

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
18ce3a4a 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
parent c40e20a8
...@@ -40,6 +40,7 @@ NamedTuplestoreScanNext(NamedTuplestoreScanState *node) ...@@ -40,6 +40,7 @@ NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
* Get the next tuple from tuplestore. Return NULL if no more tuples. * Get the next tuple from tuplestore. Return NULL if no more tuples.
*/ */
slot = node->ss.ss_ScanTupleSlot; slot = node->ss.ss_ScanTupleSlot;
tuplestore_select_read_pointer(node->relation, node->readptr);
(void) tuplestore_gettupleslot(node->relation, true, false, slot); (void) tuplestore_gettupleslot(node->relation, true, false, slot);
return slot; return slot;
} }
...@@ -116,6 +117,7 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag ...@@ -116,6 +117,7 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
* The new read pointer copies its position from read pointer 0, which * The new read pointer copies its position from read pointer 0, which
* could be anywhere, so explicitly rewind it. * could be anywhere, so explicitly rewind it.
*/ */
tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
tuplestore_rescan(scanstate->relation); tuplestore_rescan(scanstate->relation);
/* /*
......
...@@ -5559,6 +5559,28 @@ LINE 1: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d) ...@@ -5559,6 +5559,28 @@ LINE 1: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
QUERY: 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 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 -- Check type parsing and record fetching from partitioned tables
-- --
CREATE TABLE partitioned_table (a int, b text) PARTITION BY LIST (a); CREATE TABLE partitioned_table (a int, b text) PARTITION BY LIST (a);
......
...@@ -4503,6 +4503,32 @@ ALTER TABLE alter_table_under_transition_tables ...@@ -4503,6 +4503,32 @@ ALTER TABLE alter_table_under_transition_tables
UPDATE alter_table_under_transition_tables UPDATE alter_table_under_transition_tables
SET id = id; 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 -- Check type parsing and record fetching from partitioned tables
-- --
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment