# Copyright (c) 2025, PostgreSQL Global Development Group
# Test recursive catalog cache invalidation, i.e. invalidation while a # catalog cache entry is being built.
use strict;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
if ($ENV{enable_injection_points} ne 'yes')
{
plan skip_all => 'Injection points not supported by this build';
}
# Node initialization
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init();
$node->start;
# Check if the extension injection_points is available, as it may be # possible that this script is run with installcheck, where the module # would not be installed by default. if (!$node->check_extension('injection_points'))
{
plan skip_all => 'Extension injection_points not installed';
}
sub randStr
{
my $len = shift;
my @chars = ("A" .. "Z", "a" .. "z", "0" .. "9");
return join '', map { @chars[ rand @chars ] } 1 .. $len;
}
# Create a function with a large body, so that it is toasted.
my $longtext = randStr(10000);
$node->safe_psql( 'postgres', qq[
CREATE FUNCTION foofunc(dummy integer) RETURNS integer AS \$\$ SELECT 1; /* $longtext */ \$\$ LANGUAGE SQL
]);
my $psql_session = $node->background_psql('postgres');
my $psql_session2 = $node->background_psql('postgres');
# Set injection point in the session, to pause while populating the # catcache list
$psql_session->query_safe(
qq[
SELECT injection_points_set_local();
SELECT injection_points_attach('catcache-list-miss-systable-scan-started', 'wait');
]);
# This pauses on the injection point while populating catcache list # for functions with name "foofunc"
$psql_session->query_until(
qr/starting_bg_psql/, q(
\echo starting_bg_psql
SELECT foofunc(1);
));
# While the first session is building the catcache list, create a new # function that overloads the same name. This sends a catcache # invalidation.
$node->safe_psql( 'postgres', qq[
CREATE FUNCTION foofunc() RETURNS integer AS \$\$ SELECT 123 \$\$ LANGUAGE SQL
]);
# Continue the paused session. It will continue to construct the # catcache list, and will accept invalidations while doing that. # # (The fact that the first function has a large body is crucial, # because the cache invalidation is accepted during detoasting. If # the body is not toasted, the invalidation is processed after # building the catcache list, which avoids the recursion that we are # trying to exercise here.) # # The "SELECT foofunc(1)" query will now finish.
$psql_session2->query_safe(
qq[
SELECT injection_points_wakeup('catcache-list-miss-systable-scan-started');
SELECT injection_points_detach('catcache-list-miss-systable-scan-started');
]);
# Test that the new function is visible to the session.
$psql_session->query_safe("SELECT foofunc();");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.