From 12fb1c1e24d59eba470e1a38a2c124044025b0a9 Mon Sep 17 00:00:00 2001 From: Hayato Kuroda Date: Wed, 7 Oct 2026 15:46:50 +0900 Subject: [PATCH v2 3/4] Reproduce the mixture of the error context by REPACK CONCURRENTLY --- src/backend/commands/repack_worker.c | 3 + src/test/modules/injection_points/Makefile | 2 + src/test/modules/injection_points/meson.build | 8 ++ .../t/001_repack_error_context.pl | 76 +++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 src/test/modules/injection_points/t/001_repack_error_context.pl diff --git a/src/backend/commands/repack_worker.c b/src/backend/commands/repack_worker.c index d355b9954fc..7dd6c288504 100644 --- a/src/backend/commands/repack_worker.c +++ b/src/backend/commands/repack_worker.c @@ -28,6 +28,7 @@ #include "storage/proc.h" #include "tcop/tcopprot.h" #include "utils/guc.h" +#include "utils/injection_point.h" #include "utils/memutils.h" #define PGREPACK_PLUGIN "pgrepack" @@ -396,6 +397,8 @@ decode_concurrent_changes(LogicalDecodingContext *ctx, char *errm = NULL; XLogRecPtr end_lsn; + INJECTION_POINT("repack-worker-error-context", NULL); + CHECK_FOR_INTERRUPTS(); record = XLogReadRecord(ctx->reader, &errm); diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile index 2463d6e0fb9..1ca1dc98d02 100644 --- a/src/test/modules/injection_points/Makefile +++ b/src/test/modules/injection_points/Makefile @@ -45,6 +45,8 @@ NO_INSTALLCHECK = 1 export enable_injection_points +TAP_TESTS = 1 + ifdef USE_PGXS PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build index b4a0079484b..8695d45b1b0 100644 --- a/src/test/modules/injection_points/meson.build +++ b/src/test/modules/injection_points/meson.build @@ -77,4 +77,12 @@ tests += { '--temp-config', files('extra.conf'), ], }, + 'tap': { + 'env': { + 'enable_injection_points': 'yes', + }, + 'tests': [ + 't/001_repack_error_context.pl', + ], + }, } diff --git a/src/test/modules/injection_points/t/001_repack_error_context.pl b/src/test/modules/injection_points/t/001_repack_error_context.pl new file mode 100644 index 00000000000..9c348e1bfb6 --- /dev/null +++ b/src/test/modules/injection_points/t/001_repack_error_context.pl @@ -0,0 +1,76 @@ +# Copyright (c) 2026, PostgreSQL Global Development Group + +# Test that an error propagated by the REPACK decoding worker does not use +# a current context on the backend. +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('repack_error_context'); +# wal_level must be higher than 'replica' +$node->init(allows_streaming => 1); +$node->start; + +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + +# Setup a node +$node->safe_psql('postgres', + "CREATE EXTENSION injection_points WITH SCHEMA public;"); +$node->safe_psql('postgres', + "CREATE TABLE repack_error_context_test (i integer PRIMARY KEY);"); +$node->safe_psql('postgres', + "INSERT INTO repack_error_context_test SELECT generate_series(1, 100);"); + +# Define a function that triggers an injection point. The backend would wait at +# this point by the upcoming test. +$node->safe_psql('postgres', qq[ + CREATE FUNCTION repack_error_context(integer) RETURNS integer + LANGUAGE plpgsql IMMUTABLE AS \$\$ + BEGIN + PERFORM public.injection_points_run('repack-leader-error-context'); + RETURN \$1; + END; + \$\$; +]); + +# Define an index which uses the repack_error_context function +$node->safe_psql('postgres', + "CREATE INDEX repack_error_context_idx ON repack_error_context_test (repack_error_context(i));"); + +$node->safe_psql('postgres', + "SELECT injection_points_attach('repack-leader-error-context', 'wait');"); + +my $log_offset = -s $node->logfile; + +# Run REPACK CONCURRENTLY. The command would wait at the injection point. +my $session = $node->background_psql('postgres', on_error_stop => 0); +$session->query_until( + qr/repack_started/, + q[ +\echo repack_started +REPACK (CONCURRENTLY) repack_error_context_test; +]); +$node->wait_for_event('client backend', 'repack-leader-error-context'); + +# Attach another injection point for the repack worker to raise an error +$node->safe_psql('postgres', + "SELECT injection_points_attach('repack-worker-error-context', 'error')"); + +$node->wait_for_log( + qr/client backend.*ERROR: error triggered for injection point repack-worker-error-context/, + $log_offset); + +$session->quit; + +my $log_contents = slurp_file($node->logfile, $log_offset); +unlike( + $log_contents, + qr/PL\/pgSQL function public\.repack_error_context/, + 'worker error does not use the backend PL/pgSQL context'); + +done_testing(); -- 2.52.0