mirror of
https://github.com/postgres/postgres.git
synced 2025-10-25 13:17:41 +03:00
Fix an oversight in the support for storing/retrieving "minimal tuples" in
TupleTableSlots. We have functions for retrieving a minimal tuple from a slot after storing a regular tuple in it, or vice versa; but these were implemented by converting the internal storage from one format to the other. The problem with that is it invalidates any pass-by-reference Datums that were already fetched from the slot, since they'll be pointing into the just-freed version of the tuple. The known problem cases involve fetching both a whole-row variable and a pass-by-reference value from a slot that is fed from a tuplestore or tuplesort object. The added regression tests illustrate some simple cases, but there may be other failure scenarios traceable to the same bug. Note that the added tests probably only fail on unpatched code if it's built with --enable-cassert; otherwise the bug leads to fetching from freed memory, which will not have been overwritten without additional conditions. Fix by allowing a slot to contain both formats simultaneously; which turns out not to complicate the logic much at all, if anything it seems less contorted than before. Back-patch to 8.2, where minimal tuples were introduced.
This commit is contained in:
@@ -338,3 +338,16 @@ select * from tt;
|
||||
-- note that nextval() gets executed a second time in the rule expansion,
|
||||
-- which is expected.
|
||||
select * from tt_log;
|
||||
|
||||
-- test case for a whole-row-variable bug
|
||||
create function foo1(n integer, out a text, out b text)
|
||||
returns setof record
|
||||
language sql
|
||||
as $$ select 'foo ' || i, 'bar ' || i from generate_series(1,$1) i $$;
|
||||
|
||||
set work_mem='64kB';
|
||||
select t.a, t, t.a from foo1(10000) t limit 1;
|
||||
reset work_mem;
|
||||
select t.a, t, t.a from foo1(10000) t limit 1;
|
||||
|
||||
drop function foo1(n integer);
|
||||
|
||||
@@ -250,6 +250,16 @@ SELECT t1.id, count(t2.*) FROM t AS t1 JOIN t AS t2 ON
|
||||
GROUP BY t1.id
|
||||
ORDER BY t1.id;
|
||||
|
||||
-- this variant tickled a whole-row-variable bug in 8.4devel
|
||||
WITH RECURSIVE t(id, path) AS (
|
||||
VALUES(1,ARRAY[]::integer[])
|
||||
UNION ALL
|
||||
SELECT tree.id, t.path || tree.id
|
||||
FROM tree JOIN t ON (tree.parent_id = t.id)
|
||||
)
|
||||
SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON
|
||||
(t1.id=t2.id);
|
||||
|
||||
--
|
||||
-- test cycle detection
|
||||
--
|
||||
|
||||
Reference in New Issue
Block a user