summaryrefslogtreecommitdiffstats
path: root/src/test/recovery/t/014_unlogged_reinit.pl
blob: 72895104ed93ce025f71cc103d2493afc937e599 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Copyright (c) 2021-2022, 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();