1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-21 12:05:57 +03:00

Support amcheck of sequences

Sequences were left out of the list of relation kinds that
verify_heapam knew how to check, though it is fairly trivial to allow
them.  Doing that, and while at it, updating pg_amcheck to include
sequences in relations matched by table and relation patterns.

Author: Mark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/81ad4757-92c1-4aa3-7bee-f609544837e3%40enterprisedb.com
This commit is contained in:
Peter Eisentraut 2021-09-28 15:26:25 +02:00
parent 7d1aa6bf1c
commit c3b011d991
6 changed files with 95 additions and 18 deletions

View File

@ -180,8 +180,10 @@ CREATE SEQUENCE test_sequence;
SELECT * FROM verify_heapam('test_sequence', SELECT * FROM verify_heapam('test_sequence',
startblock := NULL, startblock := NULL,
endblock := NULL); endblock := NULL);
ERROR: cannot check relation "test_sequence" blkno | offnum | attnum | msg
DETAIL: This operation is not supported for sequences. -------+--------+--------+-----
(0 rows)
-- Check that foreign tables are rejected -- Check that foreign tables are rejected
CREATE FOREIGN DATA WRAPPER dummy; CREATE FOREIGN DATA WRAPPER dummy;
CREATE SERVER dummy_server FOREIGN DATA WRAPPER dummy; CREATE SERVER dummy_server FOREIGN DATA WRAPPER dummy;

View File

@ -8,7 +8,7 @@ use PostgresNode;
use TestLib; use TestLib;
use Fcntl qw(:seek); use Fcntl qw(:seek);
use Test::More tests => 80; use Test::More tests => 272;
my ($node, $result); my ($node, $result);
@ -60,6 +60,22 @@ detects_no_corruption(
"verify_heapam('test', skip := 'all-frozen')", "verify_heapam('test', skip := 'all-frozen')",
"all-frozen corrupted table skipping all-frozen"); "all-frozen corrupted table skipping all-frozen");
#
# Check a sequence with no corruption. The current implementation of sequences
# doesn't require its own test setup, since sequences are really just heap
# tables under-the-hood. To guard against future implementation changes made
# without remembering to update verify_heapam, we create and exercise a
# sequence, checking along the way that it passes corruption checks.
#
fresh_test_sequence('test_seq');
check_all_options_uncorrupted('test_seq', 'plain');
advance_test_sequence('test_seq');
check_all_options_uncorrupted('test_seq', 'plain');
set_test_sequence('test_seq');
check_all_options_uncorrupted('test_seq', 'plain');
reset_test_sequence('test_seq');
check_all_options_uncorrupted('test_seq', 'plain');
# Returns the filesystem path for the named relation. # Returns the filesystem path for the named relation.
sub relation_filepath sub relation_filepath
{ {
@ -110,6 +126,56 @@ sub fresh_test_table
)); ));
} }
# Create a test sequence of the given name.
sub fresh_test_sequence
{
my ($seqname) = @_;
return $node->safe_psql(
'postgres', qq(
DROP SEQUENCE IF EXISTS $seqname CASCADE;
CREATE SEQUENCE $seqname
INCREMENT BY 13
MINVALUE 17
START WITH 23;
SELECT nextval('$seqname');
SELECT setval('$seqname', currval('$seqname') + nextval('$seqname'));
));
}
# Call SQL functions to increment the sequence
sub advance_test_sequence
{
my ($seqname) = @_;
return $node->safe_psql(
'postgres', qq(
SELECT nextval('$seqname');
));
}
# Call SQL functions to set the sequence
sub set_test_sequence
{
my ($seqname) = @_;
return $node->safe_psql(
'postgres', qq(
SELECT setval('$seqname', 102);
));
}
# Call SQL functions to reset the sequence
sub reset_test_sequence
{
my ($seqname) = @_;
return $node->safe_psql(
'postgres', qq(
ALTER SEQUENCE $seqname RESTART WITH 51
));
}
# Stops the test node, corrupts the first page of the named relation, and # Stops the test node, corrupts the first page of the named relation, and
# restarts the node. # restarts the node.
sub corrupt_first_page sub corrupt_first_page

View File

@ -305,14 +305,20 @@ verify_heapam(PG_FUNCTION_ARGS)
*/ */
if (ctx.rel->rd_rel->relkind != RELKIND_RELATION && if (ctx.rel->rd_rel->relkind != RELKIND_RELATION &&
ctx.rel->rd_rel->relkind != RELKIND_MATVIEW && ctx.rel->rd_rel->relkind != RELKIND_MATVIEW &&
ctx.rel->rd_rel->relkind != RELKIND_TOASTVALUE) ctx.rel->rd_rel->relkind != RELKIND_TOASTVALUE &&
ctx.rel->rd_rel->relkind != RELKIND_SEQUENCE)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot check relation \"%s\"", errmsg("cannot check relation \"%s\"",
RelationGetRelationName(ctx.rel)), RelationGetRelationName(ctx.rel)),
errdetail_relkind_not_supported(ctx.rel->rd_rel->relkind))); errdetail_relkind_not_supported(ctx.rel->rd_rel->relkind)));
if (ctx.rel->rd_rel->relam != HEAP_TABLE_AM_OID) /*
* Sequences always use heap AM, but they don't show that in the catalogs.
* Other relkinds might be using a different AM, so check.
*/
if (ctx.rel->rd_rel->relkind != RELKIND_SEQUENCE &&
ctx.rel->rd_rel->relam != HEAP_TABLE_AM_OID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("only heap AM is supported"))); errmsg("only heap AM is supported")));

View File

@ -220,10 +220,10 @@ SET client_min_messages = DEBUG1;
</term> </term>
<listitem> <listitem>
<para> <para>
Checks a table for structural corruption, where pages in the relation Checks a table, sequence, or materialized view for structural corruption,
contain data that is invalidly formatted, and for logical corruption, where pages in the relation contain data that is invalidly formatted, and
where pages are structurally valid but inconsistent with the rest of the for logical corruption, where pages are structurally valid but
database cluster. inconsistent with the rest of the database cluster.
</para> </para>
<para> <para>
The following optional arguments are recognized: The following optional arguments are recognized:

View File

@ -41,8 +41,9 @@ PostgreSQL documentation
</para> </para>
<para> <para>
Only table relations and btree indexes are currently supported. Other Only ordinary and toast table relations, materialized views, sequences, and
relation types are silently skipped. btree indexes are currently supported. Other relation types are silently
skipped.
</para> </para>
<para> <para>
@ -124,7 +125,7 @@ PostgreSQL documentation
</para> </para>
<para> <para>
This is similar to the <option>--relation</option> option, except that This is similar to the <option>--relation</option> option, except that
it applies only to indexes, not tables. it applies only to indexes, not to other relation types.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -140,7 +141,7 @@ PostgreSQL documentation
</para> </para>
<para> <para>
This is similar to the <option>--exclude-relation</option> option, This is similar to the <option>--exclude-relation</option> option,
except that it applies only to indexes, not tables. except that it applies only to indexes, not other relation types.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -236,7 +237,8 @@ PostgreSQL documentation
</para> </para>
<para> <para>
This is similar to the <option>--relation</option> option, except that This is similar to the <option>--relation</option> option, except that
it applies only to tables, not indexes. it applies only to tables, materialized views, and sequences, not to
indexes.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -252,7 +254,8 @@ PostgreSQL documentation
</para> </para>
<para> <para>
This is similar to the <option>--exclude-relation</option> option, This is similar to the <option>--exclude-relation</option> option,
except that it applies only to tables, not indexes. except that it applies only to tables, materialized views, and
sequences, not to indexes.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -1910,14 +1910,14 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations,
if (opts.allrel) if (opts.allrel)
appendPQExpBuffer(&sql, appendPQExpBuffer(&sql,
" AND c.relam = %u " " AND c.relam = %u "
"AND c.relkind IN ('r', 'm', 't') " "AND c.relkind IN ('r', 'S', 'm', 't') "
"AND c.relnamespace != %u", "AND c.relnamespace != %u",
HEAP_TABLE_AM_OID, PG_TOAST_NAMESPACE); HEAP_TABLE_AM_OID, PG_TOAST_NAMESPACE);
else else
appendPQExpBuffer(&sql, appendPQExpBuffer(&sql,
" AND c.relam IN (%u, %u)" " AND c.relam IN (%u, %u)"
"AND c.relkind IN ('r', 'm', 't', 'i') " "AND c.relkind IN ('r', 'S', 'm', 't', 'i') "
"AND ((c.relam = %u AND c.relkind IN ('r', 'm', 't')) OR " "AND ((c.relam = %u AND c.relkind IN ('r', 'S', 'm', 't')) OR "
"(c.relam = %u AND c.relkind = 'i'))", "(c.relam = %u AND c.relkind = 'i'))",
HEAP_TABLE_AM_OID, BTREE_AM_OID, HEAP_TABLE_AM_OID, BTREE_AM_OID,
HEAP_TABLE_AM_OID, BTREE_AM_OID); HEAP_TABLE_AM_OID, BTREE_AM_OID);