From 495d96709fb0b116dbac253bdf0a3c0b12bf775a Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 15 Apr 2025 11:17:57 +1000 Subject: [PATCH] MDEV-35866 CHECK TABLE get number of rows without HA_STATS_RECORDS_IS_EXACT Call ha_rnd_init followed by two ha_rnd_next's to find whether there is more than one row. --- mysql-test/suite/sql_sequence/check.result | 26 +++++++++++++++++ mysql-test/suite/sql_sequence/check.test | 33 ++++++++++++++++++++++ sql/ha_sequence.cc | 26 +++++++++++++++-- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/sql_sequence/check.result b/mysql-test/suite/sql_sequence/check.result index 2bf644f022c..9439bd5ff22 100644 --- a/mysql-test/suite/sql_sequence/check.result +++ b/mysql-test/suite/sql_sequence/check.result @@ -115,3 +115,29 @@ create sequence s; update s set minimum_value=500, maximum_value=200; ERROR HY000: Storage engine SEQUENCE of the table `test`.`s` doesn't have this option drop sequence s; +# +# MDEV-35866 mariadb-check does not return warning for incorrect sequence with engine InnoDB +# +CREATE SEQUENCE s engine=innodb; +ALTER TABLE s sequence=0; +delete from s; +FLUSH TABLES; +CHECK TABLE s; +Table Op Msg_type Msg_text +test.s check Error Fewer than one row in the table +test.s check error Corrupt +DROP SEQUENCE s; +CREATE SEQUENCE s engine=innodb; +CHECK TABLE s; +Table Op Msg_type Msg_text +test.s check status OK +DROP SEQUENCE s; +CREATE SEQUENCE s engine=innodb; +ALTER TABLE s sequence=0; +insert into s values (2,1,9223372036854775806,1,1,1000,0,0); +FLUSH TABLES; +CHECK TABLE s; +Table Op Msg_type Msg_text +test.s check Warning More than one row in the table +test.s check status OK +DROP SEQUENCE s; diff --git a/mysql-test/suite/sql_sequence/check.test b/mysql-test/suite/sql_sequence/check.test index 2d88478d663..04e48a44ddf 100644 --- a/mysql-test/suite/sql_sequence/check.test +++ b/mysql-test/suite/sql_sequence/check.test @@ -137,3 +137,36 @@ create sequence s; --error ER_ILLEGAL_HA update s set minimum_value=500, maximum_value=200; drop sequence s; + +--echo # +--echo # MDEV-35866 mariadb-check does not return warning for incorrect sequence with engine InnoDB +--echo # +--source include/have_innodb.inc +# Fewer than one row +let $datadir=`select @@datadir`; +CREATE SEQUENCE s engine=innodb; +copy_file $datadir/test/s.frm $datadir/test/s1.frm; +ALTER TABLE s sequence=0; +delete from s; +FLUSH TABLES; +remove_file $datadir/test/s.frm; +move_file $datadir/test/s1.frm $datadir/test/s.frm; +CHECK TABLE s; +DROP SEQUENCE s; + +# Just one row, check ok +CREATE SEQUENCE s engine=innodb; +CHECK TABLE s; +DROP SEQUENCE s; + +# More than one row +let $datadir=`select @@datadir`; +CREATE SEQUENCE s engine=innodb; +copy_file $datadir/test/s.frm $datadir/test/s1.frm; +ALTER TABLE s sequence=0; +insert into s values (2,1,9223372036854775806,1,1,1000,0,0); +FLUSH TABLES; +remove_file $datadir/test/s.frm; +move_file $datadir/test/s1.frm $datadir/test/s.frm; +CHECK TABLE s; +DROP SEQUENCE s; diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index e2cf7a8c3b1..038d7de80c1 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -422,10 +422,11 @@ void ha_sequence::print_error(int error, myf errflag) int ha_sequence::check(THD* thd, HA_CHECK_OPT* check_opt) { + int error= 0; DBUG_ENTER("ha_sequence::check"); /* Check the underlying engine */ - if (int ret= file->check(thd, check_opt)) - DBUG_RETURN(ret); + if ((error= file->check(thd, check_opt))) + DBUG_RETURN(error); /* Check number of rows */ if ((file->table_flags() & HA_STATS_RECORDS_IS_EXACT)) { @@ -439,6 +440,27 @@ int ha_sequence::check(THD* thd, HA_CHECK_OPT* check_opt) DBUG_RETURN(HA_ADMIN_CORRUPT); } } + else + { + if (file->ha_rnd_init_with_error(1)) + DBUG_RETURN(HA_ADMIN_FAILED); + if ((error= file->ha_rnd_next(table->record[0]))) + { + file->ha_rnd_end(); + if (error == HA_ERR_END_OF_FILE) + { + my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0)); + DBUG_RETURN(HA_ADMIN_CORRUPT); + } + file->print_error(error, MYF(0)); + DBUG_RETURN(HA_ADMIN_FAILED); + } + if (!file->ha_rnd_next(table->record[0])) + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, + ER_THD(thd, ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS)); + file->ha_rnd_end(); + } /* Initialise the sequence from the table if needed. */