From a941e58fb8a1911b1dabcd85c8f906e88466318d Mon Sep 17 00:00:00 2001 From: Robert Bindar Date: Mon, 13 May 2019 12:30:35 +0300 Subject: [PATCH 1/4] MDEV-788 mysqlimport should support the ability to disable foreign keys --- client/mysqlimport.c | 11 +++++++++-- mysql-test/r/mysqldump.result | 18 ++++++++++++++++++ mysql-test/t/mysqldump.test | 29 +++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 38cec6da668..4cd51477e32 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -48,8 +48,8 @@ static char *add_load_option(char *ptr,const char *object, const char *statement); static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0, - replace=0,silent=0,ignore=0,opt_compress=0, - opt_low_priority= 0, tty_password= 0; + replace, silent, ignore, ignore_foreign_keys, + opt_compress, opt_low_priority, tty_password; static my_bool debug_info_flag= 0, debug_check_flag= 0; static uint opt_use_threads=0, opt_local_file=0, my_end_arg= 0; static char *opt_password=0, *current_user=0, @@ -123,6 +123,10 @@ static struct my_option my_long_options[] = ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ignore", 'i', "If duplicate unique key was found, keep old row.", &ignore, &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"ignore-foreign-keys", 'k', + "Disable foreign key checks while importing the data.", + &ignore_foreign_keys, &ignore_foreign_keys, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.", &opt_ignore_lines, &opt_ignore_lines, 0, GET_LL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -487,6 +491,9 @@ static MYSQL *db_connect(char *host, char *database, ignore_errors=0; db_error(mysql); } + if (ignore_foreign_keys) + mysql_query(mysql, "set foreign_key_checks= 0;"); + return mysql; } diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 25c1931d0e0..8d8e3b7eda4 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -5610,3 +5610,21 @@ DROP FUNCTION f; # DROP VIEW v1; DROP FUNCTION f; +# +# MDEV-788 New option to ignore foreign key contraints in mysqlimport +# +create table t1 ( +id int primary key +) engine=InnoDB; +create table t2 ( +t1_id int, +CONSTRAINT fk +FOREIGN KEY (t1_id) REFERENCES t1 (id) +) ENGINE = InnoDB; +select count(*) from t2; +count(*) +1 +select count(*) from t2; +count(*) +2 +drop tables t2, t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index e8a0cc3f81f..7382bd455c8 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2484,6 +2484,7 @@ DROP TABLE t1; DROP TABLE t2; DROP DATABASE db_20772273; USE test; +--remove_file $MYSQLTEST_VARDIR/tmp/t2.txt --echo # --echo # Bug #25717383: MYSQLDUMP MAY EXECUTE ANY ARBITRARY QUERY @@ -2649,3 +2650,31 @@ DROP FUNCTION f; --echo # DROP VIEW v1; DROP FUNCTION f; + +--echo # +--echo # MDEV-788 New option to ignore foreign key contraints in mysqlimport +--echo # +create table t1 ( + id int primary key +) engine=InnoDB; + +create table t2 ( + t1_id int, + CONSTRAINT fk + FOREIGN KEY (t1_id) REFERENCES t1 (id) +) ENGINE = InnoDB; + +--write_file $MYSQLTEST_VARDIR/tmp/t2.txt +0 +EOF + +--error 1 +--exec $MYSQL_IMPORT --silent test $MYSQLTEST_VARDIR/tmp/t2.txt +--exec $MYSQL_IMPORT --silent -k test $MYSQLTEST_VARDIR/tmp/t2.txt +select count(*) from t2; + +--exec $MYSQL_IMPORT --silent --ignore-foreign-keys test $MYSQLTEST_VARDIR/tmp/t2.txt +select count(*) from t2; + +--remove_file $MYSQLTEST_VARDIR/tmp/t2.txt +drop tables t2, t1; From 6ab9d1627a16b79429036f0ef10e05639bbcf46b Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Wed, 15 May 2019 01:38:28 +0530 Subject: [PATCH 2/4] MDEV-19407: Assertion `field->table->stats_is_read' failed in is_eits_usable Statistics were not read for a table when we had a CREATE TABLE query. Enforce reading statistics for commands CREATE TABLE, SET and DO. --- mysql-test/r/stat_tables.result | 19 +++++++++++++++++++ mysql-test/r/stat_tables_innodb.result | 19 +++++++++++++++++++ mysql-test/t/stat_tables.test | 20 ++++++++++++++++++++ sql/sql_statistics.cc | 3 +++ 4 files changed, 61 insertions(+) diff --git a/mysql-test/r/stat_tables.result b/mysql-test/r/stat_tables.result index 0a53a5ae99d..afb3e12a474 100644 --- a/mysql-test/r/stat_tables.result +++ b/mysql-test/r/stat_tables.result @@ -707,8 +707,27 @@ ERROR 42S02: Table 'test.x' doesn't exist select * from information_schema.tables where table_name='v'; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT def test v VIEW NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL VIEW +set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; drop view v; +# +# MDEV-19407: Assertion `field->table->stats_is_read' failed in is_eits_usable +# +set @save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +set @@optimizer_use_condition_selectivity= 1; +set @@use_stat_tables='never'; +create table t1(pk int); +insert into t1 values (4),(3); +set @@optimizer_use_condition_selectivity= 4; +set use_stat_tables='preferably'; +INSERT INTO t1 SELECT * FROM x; +ERROR 42S02: Table 'test.x' doesn't exist +CREATE TABLE t2 SELECT pk FROM t1 WHERE pk>2; +select * from t2; +pk +4 +3 +drop table t1,t2; set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set @save_optimizer_switch=@@optimizer_switch; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index 9a93b479664..643a7aa55ea 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -734,8 +734,27 @@ ERROR 42S02: Table 'test.x' doesn't exist select * from information_schema.tables where table_name='v'; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT def test v VIEW NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL VIEW +set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; drop view v; +# +# MDEV-19407: Assertion `field->table->stats_is_read' failed in is_eits_usable +# +set @save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +set @@optimizer_use_condition_selectivity= 1; +set @@use_stat_tables='never'; +create table t1(pk int); +insert into t1 values (4),(3); +set @@optimizer_use_condition_selectivity= 4; +set use_stat_tables='preferably'; +INSERT INTO t1 SELECT * FROM x; +ERROR 42S02: Table 'test.x' doesn't exist +CREATE TABLE t2 SELECT pk FROM t1 WHERE pk>2; +select * from t2; +pk +4 +3 +drop table t1,t2; set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set @save_optimizer_switch=@@optimizer_switch; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/t/stat_tables.test b/mysql-test/t/stat_tables.test index 2727f8d8bb1..1e4d261c3f3 100644 --- a/mysql-test/t/stat_tables.test +++ b/mysql-test/t/stat_tables.test @@ -469,9 +469,29 @@ CREATE VIEW v AS SELECT * FROM t1 JOIN t2; INSERT INTO t2 SELECT * FROM x; select * from information_schema.tables where table_name='v'; +set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; drop view v; + +--echo # +--echo # MDEV-19407: Assertion `field->table->stats_is_read' failed in is_eits_usable +--echo # + +set @save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +set @@optimizer_use_condition_selectivity= 1; +set @@use_stat_tables='never'; +create table t1(pk int); +insert into t1 values (4),(3); +set @@optimizer_use_condition_selectivity= 4; +set use_stat_tables='preferably'; + +--error ER_NO_SUCH_TABLE +INSERT INTO t1 SELECT * FROM x; +CREATE TABLE t2 SELECT pk FROM t1 WHERE pk>2; +select * from t2; +drop table t1,t2; + set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set @save_optimizer_switch=@@optimizer_switch; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 81ab599ed64..37f73adccb3 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2191,6 +2191,9 @@ inline bool statistics_for_command_is_needed(THD *thd) case SQLCOM_DELETE_MULTI: case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: + case SQLCOM_CREATE_TABLE: + case SQLCOM_SET_OPTION: + case SQLCOM_DO: break; default: return FALSE; From 70a5fb49a74e2dfd57fa79ebbc0fc780ce898841 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Thu, 16 May 2019 13:49:47 +0530 Subject: [PATCH 3/4] Fixed the case when statistics were not getting read because we had the statistics tables in the FROM list of the select. The statistics for tables are not read in such cases, so we need to check this case separately. --- mysql-test/r/stat_tables.result | 11 +++++++++++ mysql-test/r/stat_tables_innodb.result | 11 +++++++++++ mysql-test/t/stat_tables.test | 6 ++++++ sql/opt_range.cc | 2 +- 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/stat_tables.result b/mysql-test/r/stat_tables.result index afb3e12a474..d26221b5f8d 100644 --- a/mysql-test/r/stat_tables.result +++ b/mysql-test/r/stat_tables.result @@ -728,6 +728,17 @@ pk 4 3 drop table t1,t2; +create table t1(a int,b int, key k1(a) ); +insert into t1 values(1,1),(2,2),(3,3); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from mysql.index_stats, t1 where index_name='k1' and t1.a > 1 and t1.b > 1; +db_name table_name index_name prefix_arity avg_frequency a b +test t1 k1 1 1.0000 2 2 +test t1 k1 1 1.0000 3 3 +drop table t1; set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set @save_optimizer_switch=@@optimizer_switch; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index 643a7aa55ea..b8bed681465 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -755,6 +755,17 @@ pk 4 3 drop table t1,t2; +create table t1(a int,b int, key k1(a) ); +insert into t1 values(1,1),(2,2),(3,3); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from mysql.index_stats, t1 where index_name='k1' and t1.a > 1 and t1.b > 1; +db_name table_name index_name prefix_arity avg_frequency a b +test t1 k1 1 1.0000 2 2 +test t1 k1 1 1.0000 3 3 +drop table t1; set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set @save_optimizer_switch=@@optimizer_switch; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/t/stat_tables.test b/mysql-test/t/stat_tables.test index 1e4d261c3f3..e9f37698a73 100644 --- a/mysql-test/t/stat_tables.test +++ b/mysql-test/t/stat_tables.test @@ -492,6 +492,12 @@ CREATE TABLE t2 SELECT pk FROM t1 WHERE pk>2; select * from t2; drop table t1,t2; +create table t1(a int,b int, key k1(a) ); +insert into t1 values(1,1),(2,2),(3,3); +analyze table t1; +select * from mysql.index_stats, t1 where index_name='k1' and t1.a > 1 and t1.b > 1; +drop table t1; + set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set @save_optimizer_switch=@@optimizer_switch; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 71e8055394c..e8421ad052a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3050,7 +3050,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) if (thd->variables.optimizer_use_condition_selectivity > 2 && !bitmap_is_clear_all(used_fields) && - thd->variables.use_stat_tables > 0) + thd->variables.use_stat_tables > 0 && table->stats_is_read) { PARAM param; MEM_ROOT alloc; From 796486d19b7eede58566620dfd110d24ac723218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 May 2019 14:17:22 +0300 Subject: [PATCH 4/4] MDEV-19485: Add a test case The bug was introduced in MariaDB 10.4.0 by commit 0e5a4ac2532c64a545796c787354dc41d61d0e62 but it is good to have a regression test for this scenario in all applicable MariaDB versions. Cover the purge of an undo log record that was written before the completion of ADD SPATIAL INDEX. --- .../suite/innodb_gis/r/rtree_add_index.result | 13 ++++++++++++ .../suite/innodb_gis/t/rtree_add_index.test | 20 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 mysql-test/suite/innodb_gis/r/rtree_add_index.result create mode 100644 mysql-test/suite/innodb_gis/t/rtree_add_index.test diff --git a/mysql-test/suite/innodb_gis/r/rtree_add_index.result b/mysql-test/suite/innodb_gis/r/rtree_add_index.result new file mode 100644 index 00000000000..dbd804b18bd --- /dev/null +++ b/mysql-test/suite/innodb_gis/r/rtree_add_index.result @@ -0,0 +1,13 @@ +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (''); +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1; +ALTER TABLE t1 ADD SPATIAL INDEX (g); +disconnect purge_control; +InnoDB 0 transactions not purged +DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_gis/t/rtree_add_index.test b/mysql-test/suite/innodb_gis/t/rtree_add_index.test new file mode 100644 index 00000000000..cbc82f62a70 --- /dev/null +++ b/mysql-test/suite/innodb_gis/t/rtree_add_index.test @@ -0,0 +1,20 @@ +--source include/have_innodb.inc + +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; + +CREATE TABLE t1 (g MULTIPOINT NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (''); + +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; + +DELETE FROM t1; + +ALTER TABLE t1 ADD SPATIAL INDEX (g); + +disconnect purge_control; +--source ../../innodb/include/wait_all_purged.inc +DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;