From a6c4cfe8e46b9aa21895b06fb18c24798d661867 Mon Sep 17 00:00:00 2001 From: Antonin Houska Date: Mon, 20 Apr 2026 13:30:04 +0200 Subject: [PATCH] Enhance tests for TOAST processing by REPACK. It seems appropriate to test more kinds of TOASTing than we used to. --- .../expected/repack_toast.out | 11 +-- .../injection_points/specs/repack_toast.spec | 71 +++++++++++++++---- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/test/modules/injection_points/expected/repack_toast.out b/src/test/modules/injection_points/expected/repack_toast.out index b56dde134f8..063d730ba8f 100644 --- a/src/test/modules/injection_points/expected/repack_toast.out +++ b/src/test/modules/injection_points/expected/repack_toast.out @@ -10,10 +10,13 @@ step wait_before_lock: REPACK (CONCURRENTLY) repack_test; step change: - UPDATE repack_test SET j=get_long_string() where i=2; - DELETE FROM repack_test WHERE i=3; - INSERT INTO repack_test(i, j) VALUES (4, get_long_string()); - UPDATE repack_test SET i=3 where i=1; + DELETE FROM repack_test WHERE i=1; + INSERT INTO repack_test(i, j) VALUES (1, gen_external()); + UPDATE repack_test SET i=10 where i=2; + UPDATE repack_test SET j=gen_external() where i=3; + UPDATE repack_test SET j=gen_compressible(1) where i=4; + UPDATE repack_test SET j=gen_compressible_external(2) where i=5; + UPDATE repack_test SET j=gen_inline() where i=6; step check2: INSERT INTO relfilenodes(node) diff --git a/src/test/modules/injection_points/specs/repack_toast.spec b/src/test/modules/injection_points/specs/repack_toast.spec index b878b198971..9a6dc2eb124 100644 --- a/src/test/modules/injection_points/specs/repack_toast.spec +++ b/src/test/modules/injection_points/specs/repack_toast.spec @@ -5,17 +5,43 @@ setup { CREATE EXTENSION injection_points; - -- Return a string that needs to be TOASTed. - CREATE FUNCTION get_long_string() + -- Generate text consisting of repeated strings so that it can be + -- compressed easily. + CREATE FUNCTION gen_compressible(seed int) + RETURNS text + LANGUAGE sql IMMUTABLE as $$ + SELECT repeat(md5((seed * 1000)::text), 5000); + $$; + + -- Like above, but too big even after compression. + CREATE FUNCTION gen_compressible_external(seed int) + RETURNS text + LANGUAGE sql IMMUTABLE as $$ + SELECT repeat(md5((seed * 1000)::text), 10000); + $$; + + -- Generate a string of random characters that is not likely to be + -- compressed, but is big enough to be stored externally. + CREATE FUNCTION gen_external() RETURNS text LANGUAGE sql as $$ SELECT string_agg(chr(65 + trunc(25 * random())::int), '') FROM generate_series(1, 2048) s(x); $$; + -- Not compressible like above, but small enough to stay in-line. + CREATE FUNCTION gen_inline() + RETURNS text + LANGUAGE sql as $$ + SELECT string_agg(chr(65 + trunc(25 * random())::int), '') + FROM generate_series(1, 1024) s(x); + $$; + CREATE TABLE repack_test(i int PRIMARY KEY, j text); - INSERT INTO repack_test(i, j) VALUES (1, get_long_string()), - (2, get_long_string()), (3, get_long_string()); + INSERT INTO repack_test(i, j) VALUES + (1, gen_external()), (2, gen_external()), + (3, gen_external()), (4, gen_external()), + (5, gen_external()), (6, gen_external()); CREATE TABLE relfilenodes(node oid); @@ -27,7 +53,10 @@ teardown { DROP TABLE repack_test; DROP EXTENSION injection_points; - DROP FUNCTION get_long_string(); + DROP FUNCTION gen_compressible(int); + DROP FUNCTION gen_compressible_external(int); + DROP FUNCTION gen_external(); + DROP FUNCTION gen_inline(); DROP TABLE relfilenodes; DROP TABLE data_s1; @@ -74,17 +103,29 @@ teardown session s2 step change -# Separately test UPDATE of both plain ("i") and TOASTed ("j") attribute. In -# the first case, the new tuple we get from reorderbuffer.c contains "j" as a -# TOAST pointer, which we need to update so it points to the new heap. In the -# latter case, we receive "j" as "external indirect" value - here we test that -# the decoding worker writes the tuple to a file correctly and that the -# backend executing REPACK manages to restore it. +# Separately test different kinds of UPDATE: +# +# 1. The new tuple we get from reorderbuffer.c contains "j" as a TOAST +# pointer. However, as the TOASTed value stays unchanged, it points to the old +# tuple, so we need to adjust it. +# +# 2. We receive "j" as "external indirect" value - here we test that the +# decoding worker writes the tuple to a file correctly and that the backend +# executing REPACK manages to restore it. +# +# 3. Value of "j" is compressed. +# +# 4. Value of "j" is compressed and externalized. +# +# 5. Value of "j" stays in-line. { - UPDATE repack_test SET j=get_long_string() where i=2; - DELETE FROM repack_test WHERE i=3; - INSERT INTO repack_test(i, j) VALUES (4, get_long_string()); - UPDATE repack_test SET i=3 where i=1; + DELETE FROM repack_test WHERE i=1; + INSERT INTO repack_test(i, j) VALUES (1, gen_external()); + UPDATE repack_test SET i=10 where i=2; + UPDATE repack_test SET j=gen_external() where i=3; + UPDATE repack_test SET j=gen_compressible(1) where i=4; + UPDATE repack_test SET j=gen_compressible_external(2) where i=5; + UPDATE repack_test SET j=gen_inline() where i=6; } # Check the table from the perspective of s2. step check2 -- 2.47.3