diff --git a/include/myisamchk.h b/include/myisamchk.h index 5876d67ca5f..eaff2c9ffdd 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -117,6 +117,7 @@ typedef struct st_handler_check_param uint progress_counter; /* How often to call _report_progress() */ ulonglong progress, max_progress; + void (*init_fix_record)(void *); int (*fix_record)(struct st_myisam_info *info, uchar *record, int keynum); mysql_mutex_t print_msg_mutex; diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index cbee8b733ed..74d733948af 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -418,3 +418,40 @@ create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk insert into t2 (pk) select a from t1; ERROR 23000: Duplicate entry '1' for key 'PRIMARY' drop tables t1, t2; +# +# MDEV-23294 Segfault or assertion upon MyISAM repair +# +set @old_mode= @@sql_mode; +set @old_myisam_repair_threads= @@myisam_repair_threads; +set sql_mode='', myisam_repair_threads=2; +create table t (a binary,b blob,c blob as (concat (a,b)),h char,index (c)) engine=innodb; +Warnings: +Warning 1286 Unknown storage engine 'innodb' +Warning 1266 Using storage engine MyISAM for table 't' +Note 1071 Specified key was too long; max key length is 1000 bytes +insert into t values (0,0,default,0); +create table ti like t; +alter table ti engine=myisam; +insert into ti select * from t; +Warnings: +Warning 1906 The value specified for generated column 'c' in table 'ti' has been ignored +drop tables ti, t; +create table t (id int,a varchar(1),b varchar(1),c varchar(1) generated always as (concat (a,b)),key(c)) engine=myisam; +insert into t values (0,0,9687,0); +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +Warning 1906 The value specified for generated column 'c' in table 't' has been ignored +Warning 1265 Data truncated for column 'c' at row 1 +repair table t quick; +Table Op Msg_type Msg_text +test.t repair status OK +drop table t; +create table t1 (b varchar(1024), c char(3), unique(b,c)) engine=myisam; +insert into t1 values ('foo','baz'); +alter table t1 disable keys; +set session myisam_repair_threads= 2; +insert into t1 select 'qux'; +ERROR 21S01: Column count doesn't match value count at row 1 +drop table t1; +set sql_mode= @old_mode; +set myisam_repair_threads= @old_myisam_repair_threads; diff --git a/mysql-test/suite/vcol/t/vcol_keys_myisam.test b/mysql-test/suite/vcol/t/vcol_keys_myisam.test index 2a5aa3cd479..724cb8e510c 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_myisam.test +++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test @@ -313,3 +313,32 @@ create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk --error ER_DUP_ENTRY insert into t2 (pk) select a from t1; drop tables t1, t2; + +--echo # +--echo # MDEV-23294 Segfault or assertion upon MyISAM repair +--echo # +set @old_mode= @@sql_mode; +set @old_myisam_repair_threads= @@myisam_repair_threads; +set sql_mode='', myisam_repair_threads=2; +create table t (a binary,b blob,c blob as (concat (a,b)),h char,index (c)) engine=innodb; +insert into t values (0,0,default,0); +create table ti like t; +alter table ti engine=myisam; +insert into ti select * from t; +drop tables ti, t; + +create table t (id int,a varchar(1),b varchar(1),c varchar(1) generated always as (concat (a,b)),key(c)) engine=myisam; +insert into t values (0,0,9687,0); +repair table t quick; +drop table t; + +create table t1 (b varchar(1024), c char(3), unique(b,c)) engine=myisam; +insert into t1 values ('foo','baz'); +alter table t1 disable keys; +set session myisam_repair_threads= 2; +--error ER_WRONG_VALUE_COUNT_ON_ROW +insert into t1 select 'qux'; +# cleanup +drop table t1; +set sql_mode= @old_mode; +set myisam_repair_threads= @old_myisam_repair_threads; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index ddab8bcf741..0db7179e7e9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -709,6 +709,16 @@ my_bool mi_killed_in_mariadb(MI_INFO *info) return (((TABLE*) (info->external_ref))->in_use->killed != 0); } +static void init_compute_vcols(void *table) +{ + /* + To evaluate vcols we must have current_thd set. + This will set current_thd in all threads to the same THD, but it's + safe, because vcols are always evaluated under info->s->intern_lock. + */ + set_current_thd(static_cast