135 lines
5.0 KiB
Perl
135 lines
5.0 KiB
Perl
|
|
# Copyright (c) 2021-2023, PostgreSQL Global Development Group
|
|
|
|
# Tests that unlogged tables are properly reinitialized after a crash.
|
|
#
|
|
# The behavior should be the same when restoring from a backup, but
|
|
# that is not tested here.
|
|
|
|
use strict;
|
|
use warnings;
|
|
use PostgreSQL::Test::Cluster;
|
|
use PostgreSQL::Test::Utils;
|
|
use Test::More;
|
|
|
|
my $node = PostgreSQL::Test::Cluster->new('main');
|
|
|
|
$node->init;
|
|
$node->start;
|
|
my $pgdata = $node->data_dir;
|
|
|
|
# Create an unlogged table and an unlogged sequence to test that forks
|
|
# other than init are not copied.
|
|
$node->safe_psql('postgres', 'CREATE UNLOGGED TABLE base_unlogged (id int)');
|
|
$node->safe_psql('postgres', 'CREATE UNLOGGED SEQUENCE seq_unlogged');
|
|
|
|
my $baseUnloggedPath = $node->safe_psql('postgres',
|
|
q{select pg_relation_filepath('base_unlogged')});
|
|
my $seqUnloggedPath = $node->safe_psql('postgres',
|
|
q{select pg_relation_filepath('seq_unlogged')});
|
|
|
|
# Test that main and init forks exist.
|
|
ok(-f "$pgdata/${baseUnloggedPath}_init", 'table init fork exists');
|
|
ok(-f "$pgdata/$baseUnloggedPath", 'table main fork exists');
|
|
ok(-f "$pgdata/${seqUnloggedPath}_init", 'sequence init fork exists');
|
|
ok(-f "$pgdata/$seqUnloggedPath", 'sequence main fork exists');
|
|
|
|
# Test the sequence
|
|
is($node->safe_psql('postgres', "SELECT nextval('seq_unlogged')"),
|
|
1, 'sequence nextval');
|
|
is($node->safe_psql('postgres', "SELECT nextval('seq_unlogged')"),
|
|
2, 'sequence nextval again');
|
|
|
|
# Create an unlogged table in a tablespace.
|
|
|
|
my $tablespaceDir = PostgreSQL::Test::Utils::tempdir;
|
|
|
|
$node->safe_psql('postgres',
|
|
"CREATE TABLESPACE ts1 LOCATION '$tablespaceDir'");
|
|
$node->safe_psql('postgres',
|
|
'CREATE UNLOGGED TABLE ts1_unlogged (id int) TABLESPACE ts1');
|
|
|
|
my $ts1UnloggedPath = $node->safe_psql('postgres',
|
|
q{select pg_relation_filepath('ts1_unlogged')});
|
|
|
|
# Test that main and init forks exist.
|
|
ok(-f "$pgdata/${ts1UnloggedPath}_init", 'init fork in tablespace exists');
|
|
ok(-f "$pgdata/$ts1UnloggedPath", 'main fork in tablespace exists');
|
|
|
|
# Create more unlogged sequences for testing.
|
|
$node->safe_psql('postgres', 'CREATE UNLOGGED SEQUENCE seq_unlogged2');
|
|
# This rewrites the sequence relation in AlterSequence().
|
|
$node->safe_psql('postgres', 'ALTER SEQUENCE seq_unlogged2 INCREMENT 2');
|
|
$node->safe_psql('postgres', "SELECT nextval('seq_unlogged2')");
|
|
|
|
$node->safe_psql('postgres',
|
|
'CREATE UNLOGGED TABLE tab_seq_unlogged3 (a int GENERATED ALWAYS AS IDENTITY)'
|
|
);
|
|
# This rewrites the sequence relation in ResetSequence().
|
|
$node->safe_psql('postgres', 'TRUNCATE tab_seq_unlogged3 RESTART IDENTITY');
|
|
$node->safe_psql('postgres', 'INSERT INTO tab_seq_unlogged3 DEFAULT VALUES');
|
|
|
|
# Crash the postmaster.
|
|
$node->stop('immediate');
|
|
|
|
# Write fake forks to test that they are removed during recovery.
|
|
append_to_file("$pgdata/${baseUnloggedPath}_vm", 'TEST_VM');
|
|
append_to_file("$pgdata/${baseUnloggedPath}_fsm", 'TEST_FSM');
|
|
|
|
# Remove main fork to test that it is recopied from init.
|
|
unlink("$pgdata/${baseUnloggedPath}")
|
|
or BAIL_OUT("could not remove \"${baseUnloggedPath}\": $!");
|
|
unlink("$pgdata/${seqUnloggedPath}")
|
|
or BAIL_OUT("could not remove \"${seqUnloggedPath}\": $!");
|
|
|
|
# the same for the tablespace
|
|
append_to_file("$pgdata/${ts1UnloggedPath}_vm", 'TEST_VM');
|
|
append_to_file("$pgdata/${ts1UnloggedPath}_fsm", 'TEST_FSM');
|
|
unlink("$pgdata/${ts1UnloggedPath}")
|
|
or BAIL_OUT("could not remove \"${ts1UnloggedPath}\": $!");
|
|
|
|
$node->start;
|
|
|
|
# check unlogged table in base
|
|
ok( -f "$pgdata/${baseUnloggedPath}_init",
|
|
'table init fork in base still exists');
|
|
ok(-f "$pgdata/$baseUnloggedPath",
|
|
'table main fork in base recreated at startup');
|
|
ok(!-f "$pgdata/${baseUnloggedPath}_vm",
|
|
'vm fork in base removed at startup');
|
|
ok( !-f "$pgdata/${baseUnloggedPath}_fsm",
|
|
'fsm fork in base removed at startup');
|
|
|
|
# check unlogged sequence
|
|
ok(-f "$pgdata/${seqUnloggedPath}_init", 'sequence init fork still exists');
|
|
ok(-f "$pgdata/$seqUnloggedPath", 'sequence main fork recreated at startup');
|
|
|
|
# Test the sequence after restart
|
|
is($node->safe_psql('postgres', "SELECT nextval('seq_unlogged')"),
|
|
1, 'sequence nextval after restart');
|
|
is($node->safe_psql('postgres', "SELECT nextval('seq_unlogged')"),
|
|
2, 'sequence nextval after restart again');
|
|
|
|
# check unlogged table in tablespace
|
|
ok( -f "$pgdata/${ts1UnloggedPath}_init",
|
|
'init fork still exists in tablespace');
|
|
ok(-f "$pgdata/$ts1UnloggedPath",
|
|
'main fork in tablespace recreated at startup');
|
|
ok( !-f "$pgdata/${ts1UnloggedPath}_vm",
|
|
'vm fork in tablespace removed at startup');
|
|
ok( !-f "$pgdata/${ts1UnloggedPath}_fsm",
|
|
'fsm fork in tablespace removed at startup');
|
|
|
|
# Test other sequences
|
|
is($node->safe_psql('postgres', "SELECT nextval('seq_unlogged2')"),
|
|
1, 'altered sequence nextval after restart');
|
|
is($node->safe_psql('postgres', "SELECT nextval('seq_unlogged2')"),
|
|
3, 'altered sequence nextval after restart again');
|
|
|
|
$node->safe_psql('postgres',
|
|
"INSERT INTO tab_seq_unlogged3 VALUES (DEFAULT), (DEFAULT)");
|
|
is($node->safe_psql('postgres', "SELECT * FROM tab_seq_unlogged3"),
|
|
"1\n2", 'reset sequence nextval after restart');
|
|
|
|
done_testing();
|