summaryrefslogtreecommitdiffstats
path: root/src/test/isolation/specs/horizons.spec
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/isolation/specs/horizons.spec')
-rw-r--r--src/test/isolation/specs/horizons.spec169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/test/isolation/specs/horizons.spec b/src/test/isolation/specs/horizons.spec
new file mode 100644
index 0000000..d5239ff
--- /dev/null
+++ b/src/test/isolation/specs/horizons.spec
@@ -0,0 +1,169 @@
+# Test that pruning and vacuuming pay attention to concurrent sessions
+# in the right way. For normal relations that means that rows cannot
+# be pruned away if there's an older snapshot, in contrast to that
+# temporary tables should nearly always be prunable.
+#
+# NB: Think hard before adding a test showing that rows in permanent
+# tables get pruned - it's quite likely that it'd be racy, e.g. due to
+# an autovacuum worker holding a snapshot.
+
+setup {
+ CREATE OR REPLACE FUNCTION explain_json(p_query text)
+ RETURNS json
+ LANGUAGE plpgsql AS $$
+ DECLARE
+ v_ret json;
+ BEGIN
+ EXECUTE p_query INTO STRICT v_ret;
+ RETURN v_ret;
+ END;$$;
+}
+
+teardown {
+ DROP FUNCTION explain_json(text);
+}
+
+session lifeline
+
+# Start a transaction, force a snapshot to be held
+step ll_start
+{
+ BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+ SELECT 1;
+}
+
+step ll_commit { COMMIT; }
+
+
+session pruner
+
+setup
+{
+ SET enable_seqscan = false;
+ SET enable_indexscan = false;
+ SET enable_bitmapscan = false;
+}
+
+step pruner_create_temp
+{
+ CREATE TEMPORARY TABLE horizons_tst (data int unique) WITH (autovacuum_enabled = off);
+ INSERT INTO horizons_tst(data) VALUES(1),(2);
+}
+
+step pruner_create_perm
+{
+ CREATE TABLE horizons_tst (data int unique) WITH (autovacuum_enabled = off);
+ INSERT INTO horizons_tst(data) VALUES(1),(2);
+}
+
+# Temp tables cannot be dropped in the teardown, so just always do so
+# as part of the permutation
+step pruner_drop
+{
+ DROP TABLE horizons_tst;
+}
+
+step pruner_delete
+{
+ DELETE FROM horizons_tst;
+}
+
+step pruner_begin { BEGIN; }
+step pruner_commit { COMMIT; }
+
+step pruner_vacuum
+{
+ VACUUM horizons_tst;
+}
+
+# Show the heap fetches of an ordered index-only-scan (other plans
+# have been forbidden above) - that tells us how many non-killed leaf
+# entries there are.
+step pruner_query
+{
+ SELECT explain_json($$
+ EXPLAIN (FORMAT json, BUFFERS, ANALYZE)
+ SELECT * FROM horizons_tst ORDER BY data;$$)->0->'Plan'->'Heap Fetches';
+}
+
+# Verify that the query plan still is an IOS
+step pruner_query_plan
+{
+ EXPLAIN (COSTS OFF) SELECT * FROM horizons_tst ORDER BY data;
+}
+
+
+# Show that with a permanent relation deleted rows cannot be pruned
+# away if there's a concurrent session still seeing the rows.
+permutation
+ pruner_create_perm
+ ll_start
+ pruner_query_plan
+ # Run query that could do pruning twice, first has chance to prune,
+ # second would not perform heap fetches if first query did.
+ pruner_query
+ pruner_query
+ pruner_delete
+ pruner_query
+ pruner_query
+ ll_commit
+ pruner_drop
+
+# Show that with a temporary relation deleted rows can be pruned away,
+# even if there's a concurrent session with a snapshot from before the
+# deletion. That's safe because the session with the older snapshot
+# cannot access the temporary table.
+permutation
+ pruner_create_temp
+ ll_start
+ pruner_query_plan
+ pruner_query
+ pruner_query
+ pruner_delete
+ pruner_query
+ pruner_query
+ ll_commit
+ pruner_drop
+
+# Verify that pruning in temporary relations doesn't remove rows still
+# visible in the current session
+permutation
+ pruner_create_temp
+ ll_start
+ pruner_query
+ pruner_query
+ pruner_begin
+ pruner_delete
+ pruner_query
+ pruner_query
+ ll_commit
+ pruner_commit
+ pruner_drop
+
+# Show that vacuum cannot remove deleted rows still visible to another
+# session's snapshot, when accessing a permanent table.
+permutation
+ pruner_create_perm
+ ll_start
+ pruner_query
+ pruner_query
+ pruner_delete
+ pruner_vacuum
+ pruner_query
+ pruner_query
+ ll_commit
+ pruner_drop
+
+# Show that vacuum can remove deleted rows still visible to another
+# session's snapshot, when accessing a temporary table.
+permutation
+ pruner_create_temp
+ ll_start
+ pruner_query
+ pruner_query
+ pruner_delete
+ pruner_vacuum
+ pruner_query
+ pruner_query
+ ll_commit
+ pruner_drop