0002-Add-compressed-TOAST-test-to-repack_toast.patch
application/octet-stream
Filename: 0002-Add-compressed-TOAST-test-to-repack_toast.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch 0002
| File | + | − |
|---|---|---|
| src/test/modules/injection_points/expected/repack_toast.out | 57 | 0 |
| src/test/modules/injection_points/specs/repack_toast.spec | 59 | 0 |
diff --git a/src/test/modules/injection_points/expected/repack_toast.out b/src/test/modules/injection_points/expected/repack_toast.out
index b56dde1..0eefc88 100644
--- a/src/test/modules/injection_points/expected/repack_toast.out
+++ b/src/test/modules/injection_points/expected/repack_toast.out
@@ -63,3 +63,60 @@ injection_points_detach
(1 row)
+
+starting permutation: repack_compressed compressed_update wakeup_before_lock verify_compressed
+injection_points_attach
+-----------------------
+
+(1 row)
+
+step repack_compressed:
+ REPACK (CONCURRENTLY) repack_ctest;
+ <waiting ...>
+step compressed_update:
+ UPDATE repack_ctest SET j = gen_compressible(99) WHERE i = 2;
+
+step wakeup_before_lock:
+ SELECT injection_points_wakeup('repack-concurrently-before-lock');
+
+injection_points_wakeup
+-----------------------
+
+(1 row)
+
+step repack_compressed: <... completed>
+step verify_compressed:
+ INSERT INTO post_repack_data
+ SELECT i, j FROM repack_ctest ORDER BY i;
+
+ SELECT e.i,
+ length(e.j) AS expect_len,
+ length(p.j) AS actual_len,
+ (length(e.j) = length(p.j)) AS len_ok,
+ (md5(e.j) = md5(p.j)) AS hash_ok
+ FROM expected_data e
+ JOIN post_repack_data p USING (i)
+ ORDER BY e.i;
+
+ SELECT count(*) AS mismatches
+ FROM expected_data e
+ JOIN post_repack_data p USING (i)
+ WHERE length(e.j) != length(p.j) OR md5(e.j) != md5(p.j);
+
+i|expect_len|actual_len|len_ok|hash_ok
+-+----------+----------+------+-------
+1| 16000| 16000|t |t
+2| 16000| 16000|t |t
+3| 16000| 16000|t |t
+(3 rows)
+
+mismatches
+----------
+ 0
+(1 row)
+
+injection_points_detach
+-----------------------
+
+(1 row)
+
diff --git a/src/test/modules/injection_points/specs/repack_toast.spec b/src/test/modules/injection_points/specs/repack_toast.spec
index b878b19..fb8a557 100644
--- a/src/test/modules/injection_points/specs/repack_toast.spec
+++ b/src/test/modules/injection_points/specs/repack_toast.spec
@@ -13,6 +13,14 @@ setup
FROM generate_series(1, 2048) s(x);
$$;
+ -- 500 concatenated md5 hashes = 16000 hex chars; compresses but stays > 2KB.
+ CREATE FUNCTION gen_compressible(seed int)
+ RETURNS text
+ LANGUAGE sql IMMUTABLE as $$
+ SELECT string_agg(md5((seed * 1000 + x)::text), '')
+ FROM generate_series(1, 500) 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());
@@ -21,13 +29,30 @@ setup
CREATE TABLE data_s1(i int, j text);
CREATE TABLE data_s2(i int, j text);
+
+ CREATE TABLE repack_ctest(i int PRIMARY KEY, j text);
+ INSERT INTO repack_ctest(i, j)
+ VALUES (1, gen_compressible(1)),
+ (2, gen_compressible(2)),
+ (3, gen_compressible(3));
+
+ CREATE TABLE expected_data AS
+ SELECT 1 AS i, gen_compressible(1) AS j
+ UNION ALL SELECT 2, gen_compressible(99)
+ UNION ALL SELECT 3, gen_compressible(3);
+
+ CREATE TABLE post_repack_data(i int, j text);
}
teardown
{
DROP TABLE repack_test;
+ DROP TABLE repack_ctest;
+ DROP TABLE expected_data;
+ DROP TABLE post_repack_data;
DROP EXTENSION injection_points;
DROP FUNCTION get_long_string();
+ DROP FUNCTION gen_compressible(int);
DROP TABLE relfilenodes;
DROP TABLE data_s1;
@@ -67,6 +92,29 @@ step check1
FROM data_s1 d1 FULL JOIN data_s2 d2 USING (i, j)
WHERE d1.i ISNULL OR d2.i ISNULL;
}
+step repack_compressed
+{
+ REPACK (CONCURRENTLY) repack_ctest;
+}
+step verify_compressed
+{
+ INSERT INTO post_repack_data
+ SELECT i, j FROM repack_ctest ORDER BY i;
+
+ SELECT e.i,
+ length(e.j) AS expect_len,
+ length(p.j) AS actual_len,
+ (length(e.j) = length(p.j)) AS len_ok,
+ (md5(e.j) = md5(p.j)) AS hash_ok
+ FROM expected_data e
+ JOIN post_repack_data p USING (i)
+ ORDER BY e.i;
+
+ SELECT count(*) AS mismatches
+ FROM expected_data e
+ JOIN post_repack_data p USING (i)
+ WHERE length(e.j) != length(p.j) OR md5(e.j) != md5(p.j);
+}
teardown
{
SELECT injection_points_detach('repack-concurrently-before-lock');
@@ -101,6 +149,10 @@ step wakeup_before_lock
{
SELECT injection_points_wakeup('repack-concurrently-before-lock');
}
+step compressed_update
+{
+ UPDATE repack_ctest SET j = gen_compressible(99) WHERE i = 2;
+}
# Test if data changes introduced while one session is performing REPACK
# CONCURRENTLY find their way into the table.
@@ -110,3 +162,10 @@ permutation
check2
wakeup_before_lock
check1
+
+# Test that compressed TOAST values survive REPACK CONCURRENTLY.
+permutation
+ repack_compressed
+ compressed_update
+ wakeup_before_lock
+ verify_compressed