From 90e608c6acd150e727cb0002f36767d0866aa633 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 26 Jun 2018 11:42:02 +0400 Subject: [PATCH 1/8] A test cleanup for MDEV-15834: fixing failure in "mtr --embedded" --- mysql-test/suite/vcol/t/vcol_misc.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index a123d21d574..fab705eaaa6 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -327,8 +327,10 @@ SET sql_mode=DEFAULT; --copy_file std_data/frm/t1.frm $MYSQLD_DATADIR/test/t1.frm SHOW TABLES; +--replace_result $MYSQLD_DATADIR ./ --error ER_NOT_FORM_FILE SHOW CREATE TABLE t1; +--replace_result $MYSQLD_DATADIR ./ --error ER_NOT_FORM_FILE ALTER TABLE t1; --remove_file $MYSQLD_DATADIR/test/t1.frm From 1f6a89a8fdf88029518584f3e906d0e55bc1889a Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 27 Jun 2018 13:18:03 +0300 Subject: [PATCH 2/8] Added valgrind suppression for OpenSuse 42.2 --- mysql-test/valgrind.supp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 71e6836365e..c9c06c2634a 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -608,6 +608,19 @@ fun:dlopen* } +# +# Warning caused by small memory leak in _dl_init +# + +{ + dl_init memory leak + Memcheck:Leak + fun:malloc + obj:*/libstdc++.so* + fun:call_init.part* + fun:_dl_init +} + # # In glibc (checked version 2.7), inet_ntoa allocates an 18-byte # per-thread static buffer for the return value. That memory is freed From faef2e6a44de8e1c1301104671d08dfc1deef1e0 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 27 Jun 2018 13:18:30 +0300 Subject: [PATCH 3/8] Added more help text in case mysql_install_db fails. --- scripts/mysql_install_db.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 2c5f8d7082d..a8f32526a7e 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -211,6 +211,11 @@ cannot_find_file() echo "If you compiled from source, you need to run 'make install' to" echo "copy the software into the correct location ready for operation." echo + echo "If you compiled from source, you need to either run 'make install' to" + echo "copy the software into the correct location ready for operation." + echo "If you don't want to do a full install, you can use the --srcdir" + echo "option to only install the mysql database and privilege tables" + echo echo "If you are using a binary release, you must either be at the top" echo "level of the extracted archive, or pass the --basedir option" echo "pointing to that location." From 937c19318819f63d72a66dac5a60c638386512d6 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 27 Jun 2018 13:17:18 +0300 Subject: [PATCH 4/8] Fixed MDEV-16512, crashing on re-execution of failing SP MDEV-16512 Server crashes in find_field_in_table_ref on 2nd execution of SP referring to non-existing field Problem was in the natural join code that it changed TABLE_LIST and Item_fields but didn't restore changed things if things goes wrong and was not able to re-execute after failure. Some of the problems could have been avoided if we would have run fix_fields before doing natural join transformations. Fixed by marking functions complete AFTER they had executed, instead at start. I had also to change some tests that checked if Item_fields are usable. This doesn't fix all known problems, but at least avoids some crashes. What should be done in the near future is to mark the statement in the SP as 'not re-executable' and force a reparse of it on next execution. Reviewer: Sergei Petrunia --- mysql-test/r/join.result | 40 +++++++++++++++++++++++++++++++ mysql-test/t/join.test | 52 ++++++++++++++++++++++++++++++++++++++++ sql/sql_base.cc | 12 ++++++---- sql/table.cc | 6 ++--- 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 1e51d55f012..7b0e7807e39 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -1497,3 +1497,43 @@ Note 1003 select NULL AS `i1`,`v2`.`i2` AS `i2`,`v2`.`a` AS `a`,`v2`.`b` AS `b` DROP VIEW v2; DROP TABLE t1,t2; SET optimizer_switch=@save_optimizer_switch; +# +# MDEV-16512 +# Server crashes in find_field_in_table_ref on 2nd execution of SP referring to +# non-existing field +# +CREATE TABLE t (i INT); +CREATE PROCEDURE p() SELECT t1.f FROM t AS t1 JOIN t AS t2 USING (f); +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +FLUSH TABLES; +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +DROP TABLE t; +CREATE TABLE t (f INT); +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +DROP TABLE t; +CREATE TABLE t (i INT); +CALL p; +ERROR 42S22: Unknown column 'f' in 'from clause' +DROP PROCEDURE p; +DROP TABLE t; +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT, c INT); +CREATE TABLE t4 (a INT, c INT); +CREATE TABLE t5 (a INT, c INT); +CREATE PROCEDURE p1() SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a) +LEFT JOIN t5 USING (a)) USING (a); +CALL p1; +ERROR 23000: Column 'c' in field list is ambiguous +CALL p1; +ERROR 23000: Column 'c' in field list is ambiguous +DROP PROCEDURE p1; +DROP TABLE t1,t2,t3,t4,t5; +# +# End of MariaDB 5.5 tests +# diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 203a7d377a5..feafac57a7e 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -1159,3 +1159,55 @@ DROP VIEW v2; DROP TABLE t1,t2; SET optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # MDEV-16512 +--echo # Server crashes in find_field_in_table_ref on 2nd execution of SP referring to +--echo # non-existing field +--echo # + +CREATE TABLE t (i INT); +CREATE PROCEDURE p() SELECT t1.f FROM t AS t1 JOIN t AS t2 USING (f); +--error ER_BAD_FIELD_ERROR +CALL p; +--error ER_BAD_FIELD_ERROR +CALL p; +FLUSH TABLES; +--error ER_BAD_FIELD_ERROR +CALL p; +DROP TABLE t; + +# +# Fix the table definition to match the using +# + +CREATE TABLE t (f INT); +# +# The following shouldn't fail as the table is now matching the using +# +--error ER_BAD_FIELD_ERROR +CALL p; +DROP TABLE t; +CREATE TABLE t (i INT); +--error ER_BAD_FIELD_ERROR +CALL p; +DROP PROCEDURE p; +DROP TABLE t; + +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT, c INT); +CREATE TABLE t4 (a INT, c INT); +CREATE TABLE t5 (a INT, c INT); +CREATE PROCEDURE p1() SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a) +LEFT JOIN t5 USING (a)) USING (a); +--error ER_NON_UNIQ_ERROR +CALL p1; +--error ER_NON_UNIQ_ERROR +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1,t2,t3,t4,t5; + +--echo # +--echo # End of MariaDB 5.5 tests +--echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 71bbb538b5c..8ffb7bc118b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7687,6 +7687,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, Query_arena *arena, backup; bool result= TRUE; List *non_join_columns; + List *join_columns; DBUG_ENTER("store_natural_using_join_columns"); DBUG_ASSERT(!natural_using_join->join_columns); @@ -7694,7 +7695,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, arena= thd->activate_stmt_arena_if_needed(&backup); if (!(non_join_columns= new List) || - !(natural_using_join->join_columns= new List)) + !(join_columns= new List)) goto err; /* Append the columns of the first join operand. */ @@ -7703,7 +7704,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, nj_col_1= it_1.get_natural_column_ref(); if (nj_col_1->is_common) { - natural_using_join->join_columns->push_back(nj_col_1); + join_columns->push_back(nj_col_1); /* Reset the common columns for the next call to mark_common_columns. */ nj_col_1->is_common= FALSE; } @@ -7724,7 +7725,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, { const char *using_field_name_ptr= using_field_name->c_ptr(); List_iterator_fast - it(*(natural_using_join->join_columns)); + it(*join_columns); Natural_join_column *common_field; for (;;) @@ -7757,7 +7758,8 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, } if (non_join_columns->elements > 0) - natural_using_join->join_columns->concat(non_join_columns); + join_columns->concat(non_join_columns); + natural_using_join->join_columns= join_columns; natural_using_join->is_join_columns_complete= TRUE; result= FALSE; @@ -7989,7 +7991,6 @@ static bool setup_natural_join_row_types(THD *thd, DBUG_PRINT("info", ("using cached setup_natural_join_row_types")); DBUG_RETURN(false); } - context->select_lex->first_natural_join_processing= false; List_iterator_fast table_ref_it(*from_clause); TABLE_LIST *table_ref; /* Current table reference. */ @@ -8034,6 +8035,7 @@ static bool setup_natural_join_row_types(THD *thd, change on re-execution */ context->natural_join_first_table= context->first_name_resolution_table; + context->select_lex->first_natural_join_processing= false; DBUG_RETURN (false); } diff --git a/sql/table.cc b/sql/table.cc index 87a249defa0..48aa445e1aa 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5487,7 +5487,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col); } - DBUG_ASSERT(!nj_col->table_field || + DBUG_ASSERT(!nj_col->table_field || !nj_col->table_field->field || nj_col->table_ref->table == nj_col->table_field->field->table); /* @@ -5536,7 +5536,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ RETURN # Pointer to a column of a natural join (or its operand) - NULL No memory to allocate the column + NULL We didn't originally have memory to allocate the column */ Natural_join_column * @@ -5552,7 +5552,7 @@ Field_iterator_table_ref::get_natural_column_ref() */ nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col && - (!nj_col->table_field || + (!nj_col->table_field || !nj_col->table_field->field || nj_col->table_ref->table == nj_col->table_field->field->table)); return nj_col; } From 9d41dd2f39f5a0c840d77e5fb7fc8d1396bf1a33 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 27 Jun 2018 15:34:11 +0400 Subject: [PATCH 5/8] MDEV-8540 - Crash on server shutdown since 10.0.16 For the purpose of reporting an error to error log, shutdown thread was attempting to access current_thd->variables.lc_messages->errmsgs->errmsgs. Whereas current_thd was NULL. We should log errors according to global lc_messages setting instead of session setting. --- sql/log.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 5b4ba87ef52..2504b5e2d06 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2499,14 +2499,14 @@ void MYSQL_LOG::close(uint exiting) if (log_type == LOG_BIN && mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; - sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno); } if (!(exiting & LOG_CLOSE_DELAYED_CLOSE) && mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; - sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno); } } @@ -2690,7 +2690,7 @@ err: if (!write_error) { write_error= 1; - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno); } mysql_mutex_unlock(&LOCK_log); return TRUE; @@ -2866,7 +2866,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, if (! write_error) { write_error= 1; - sql_print_error(ER(ER_ERROR_ON_WRITE), name, tmp_errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, tmp_errno); } } } @@ -6385,7 +6385,7 @@ void MYSQL_BIN_LOG::close(uint exiting) if (mysql_file_close(index_file.file, MYF(0)) < 0 && ! write_error) { write_error= 1; - sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno); + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), index_file_name, errno); } } log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED; From 90cb7212742e9ae3a63bd183e171c95bd12d559f Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 29 Jun 2018 22:46:38 -0700 Subject: [PATCH 6/8] MDEV-16603 Crash with set join_cache_level=4 When the definition of the index used for hash join was created in create_hj_key_for_table() it could cause memory overwrite due to a bug that led to an underestimation of the number of the index component. --- mysql-test/r/join_cache.result | 33 +++++++++++++++++++++++++++++++++ mysql-test/t/join_cache.test | 31 +++++++++++++++++++++++++++++++ sql/sql_select.cc | 4 ++-- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index 386f7119bc8..f1e6fb577c8 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5871,4 +5871,37 @@ SET join_buffer_size = default; SET join_buffer_space_limit= default; set optimizer_switch=@save_optimizer_switch; DROP TABLE t1,t4,t5,t2; +# +# MDEV-16603: BNLH for query with materialized semi-join +# +set join_cache_level=4; +CREATE TABLE t1 ( i1 int, v1 varchar(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (7,'x'); +CREATE TABLE t2 (i1 int, v1 varchar(1), KEY v1 (v1,i1)) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(NULL,'x'),(1,'x'),(3,'x'),(5,'x'),(8,'x'),(48,'x'), +(228,'x'),(3,'y'),(1,'z'),(9,'z'); +CREATE TABLE temp +SELECT t1.i1 AS f1, t1.v1 AS f2 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1)); +SELECT * FROM temp +WHERE (f1,f2) IN (SELECT t1.i1, t1.v1 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1))); +f1 f2 +7 x +7 x +7 x +7 x +7 x +7 x +7 x +EXPLAIN EXTENDED SELECT * FROM temp +WHERE (f1,f2) IN (SELECT t1.i1, t1.v1 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1))); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 1 100.00 +1 PRIMARY temp hash_ALL NULL #hash#$hj 9 test.t1.i1,test.t1.v1 7 100.00 Using where; Using join buffer (flat, BNLH join) +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 1 100.00 Using where +2 MATERIALIZED t2 hash_index v1 #hash#v1:v1 4:9 test.t1.v1 10 10.00 Using join buffer (flat, BNLH join) +Warnings: +Note 1003 select `test`.`temp`.`f1` AS `f1`,`test`.`temp`.`f2` AS `f2` from `test`.`temp` semi join (`test`.`t2` join `test`.`t1`) where ((`test`.`temp`.`f1` = `test`.`t1`.`i1`) and (`test`.`t2`.`v1` = `test`.`t1`.`v1`) and (`test`.`temp`.`f2` = `test`.`t1`.`v1`)) +DROP TABLE t1,t2,temp; +SET join_cache_level = default; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 58a7b885356..d82b4fa6030 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -3836,5 +3836,36 @@ set optimizer_switch=@save_optimizer_switch; DROP TABLE t1,t4,t5,t2; +--echo # +--echo # MDEV-16603: BNLH for query with materialized semi-join +--echo # + +--source include/have_innodb.inc + +set join_cache_level=4; + +CREATE TABLE t1 ( i1 int, v1 varchar(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (7,'x'); + +CREATE TABLE t2 (i1 int, v1 varchar(1), KEY v1 (v1,i1)) ENGINE=InnoDB; + +INSERT INTO t2 VALUES + (NULL,'x'),(1,'x'),(3,'x'),(5,'x'),(8,'x'),(48,'x'), + (228,'x'),(3,'y'),(1,'z'),(9,'z'); + +CREATE TABLE temp +SELECT t1.i1 AS f1, t1.v1 AS f2 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1)); + +let $q = +SELECT * FROM temp +WHERE (f1,f2) IN (SELECT t1.i1, t1.v1 FROM (t2 JOIN t1 ON (t1.v1 = t2.v1))); + +eval $q; +eval EXPLAIN EXTENDED $q; + +DROP TABLE t1,t2,temp; + +SET join_cache_level = default; + # this must be the last command in the file set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b79431ae2f6..700b7b37928 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7994,7 +7994,6 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, if (first_keyuse) { key_parts++; - first_keyuse= FALSE; } else { @@ -8004,7 +8003,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, if (curr->keypart == keyuse->keypart && !(~used_tables & curr->used_tables) && join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, - keyuse) && + curr) && are_tables_local(join_tab, curr->used_tables)) break; } @@ -8012,6 +8011,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab, key_parts++; } } + first_keyuse= FALSE; keyuse++; } while (keyuse->table == table && keyuse->is_for_hash_join()); if (!key_parts) From 24a0a74f5d92a861989fcea17a0c62c1ee7b1299 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 10 Jul 2018 13:54:04 +0530 Subject: [PATCH 7/8] MDEV-16307: Incorrect results when using BNLH join instead of BNL join with views In this issue we are using derived_with_keys optimization and we are using these keys to do a hash join which is incorrect. We cannot create keys for dervied tables whose keyparts have types are of BLOB or TEXT type. TEXT or BLOB columns can only be indexed over a specified length. --- mysql-test/r/derived.result | 33 +++++++++++++++++++++++++++++++++ mysql-test/t/derived.test | 21 +++++++++++++++++++++ sql/table.cc | 13 +++++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 54c78dc9f6f..5debfaed5e3 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1023,6 +1023,7 @@ INSERT INTO t2 VALUES (NULL),(NULL); CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; INSERT INTO t3 VALUES ('abc',NULL),('def',4); +set @save_join_cache_level= @@join_cache_level; SET join_cache_level= 8; explain SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; @@ -1052,4 +1053,36 @@ i drop procedure pr; drop view v1; drop table t1; +set @@join_cache_level= @save_join_cache_level; +# +# MDEV-16307: Incorrect results when using BNLH join instead of BNL join with views +# +CREATE TABLE t1 (c1 text, c2 int); +INSERT INTO t1 VALUES ('a',1), ('c',3), ('g',7), ('d',4), ('c',3); +CREATE TABLE t2 (c1 text, c2 int); +INSERT INTO t2 VALUES ('b',2), ('c',3); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 PRIMARY ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +2 DERIVED t1 ALL NULL NULL NULL NULL 5 +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +c1 c2 c1 c2 +c 3 c 3 +c 3 c 3 +set @save_join_cache_level= @@join_cache_level; +set @@join_cache_level=4; +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where +1 PRIMARY hash_ALL NULL #hash#$hj 3 test.t2.c1 5 Using where; Using join buffer (flat, BNLH join) +2 DERIVED t1 ALL NULL NULL NULL NULL 5 +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +c1 c2 c1 c2 +c 3 c 3 +c 3 c 3 +drop table t1,t2; +drop view v1; +set @@join_cache_level= @save_join_cache_level; # end of 5.5 diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index c5b792c8d4d..217203422e0 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -880,6 +880,7 @@ CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; INSERT INTO t3 VALUES ('abc',NULL),('def',4); +set @save_join_cache_level= @@join_cache_level; SET join_cache_level= 8; explain SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; @@ -902,5 +903,25 @@ call pr(2); drop procedure pr; drop view v1; drop table t1; +set @@join_cache_level= @save_join_cache_level; +--echo # +--echo # MDEV-16307: Incorrect results when using BNLH join instead of BNL join with views +--echo # + +CREATE TABLE t1 (c1 text, c2 int); +INSERT INTO t1 VALUES ('a',1), ('c',3), ('g',7), ('d',4), ('c',3); +CREATE TABLE t2 (c1 text, c2 int); +INSERT INTO t2 VALUES ('b',2), ('c',3); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; + +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +set @save_join_cache_level= @@join_cache_level; +set @@join_cache_level=4; +explain SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1; +drop table t1,t2; +drop view v1; +set @@join_cache_level= @save_join_cache_level; --echo # end of 5.5 diff --git a/sql/table.cc b/sql/table.cc index 48aa445e1aa..f6152a36eef 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6060,6 +6060,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info, The function checks whether a possible key satisfies the constraints imposed on the keys of any temporary table. + We need to filter out BLOB columns here, because ref access optimizer creates + KEYUSE objects for equalities for non-key columns for two puproses: + 1. To discover possible keys for derived_with_keys optimization + 2. To do hash joins + For the purpose of #1, KEYUSE objects are not created for "blob_column=..." . + However, they might be created for #2. In order to catch that case, we filter + them out here. + @return TRUE if the key is valid @return FALSE otherwise */ @@ -6075,11 +6083,12 @@ bool TABLE::check_tmp_key(uint key, uint key_parts, { uint fld_idx= next_field_no(arg); reg_field= field + fld_idx; + if ((*reg_field)->type() == MYSQL_TYPE_BLOB) + return FALSE; uint fld_store_len= (uint16) (*reg_field)->key_length(); if ((*reg_field)->real_maybe_null()) fld_store_len+= HA_KEY_NULL_LENGTH; - if ((*reg_field)->type() == MYSQL_TYPE_BLOB || - (*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || + if ((*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || (*reg_field)->type() == MYSQL_TYPE_GEOMETRY) fld_store_len+= HA_KEY_BLOB_LENGTH; key_len+= fld_store_len; From 2fbf2277ffec86d69f793534da7043b6dd540780 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 11 Jul 2018 10:43:38 +0300 Subject: [PATCH 8/8] MDEV-15982: Incorrect results when subquery is materialized fix_semijoin_strategies_for_picked_join_order() should set join->sjm_lookup_tables to be a bitmap of tables inside SJ-Materialization-Lookup nests. --- mysql-test/r/subselect_sj2_mat.result | 51 +++++++++++++++++++++++++++ mysql-test/t/subselect_sj2_mat.test | 49 +++++++++++++++++++++++++ sql/opt_subselect.cc | 3 +- 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index 19aa3bd3f02..7f97e1aabee 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -1658,3 +1658,54 @@ id 12 13 drop table t1; +# +# MDEV-15982: Incorrect results when subquery is materialized +# +CREATE TABLE `t1` (`id` int(32) NOT NULL primary key); +INSERT INTO `t1` VALUES +(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), (135), (136), (137), (138), (139), (140), (141), (142), (143), (144), (145), (146), +(147), (148), (149), (150), (151), (152), (153), (154), (155), (156), (157), (158), (159), (160), (161), +(162), (163), (164), (165), (166), (167), (168), (169), (170), (171), (172), (173), +(174), (175), (176), (177), (178), (179), (180), (181), (182), (183), (2), (3), (4), (5), (6), (19), (35), +(7), (20), (8), (36), (219), (22), (10), (23), (37), (11), (24); +CREATE TABLE `t2` (`type` int , `id` int(32) NOT NULL primary key); +INSERT INTO `t2` VALUES +(2,2),(2,3),(1,4),(2,5),(1,6),(1,19),(5,7),(1,20),(1,8),(1,21),(1,9), +(1,22),(2,10),(1,23),(2,11),(1,24),(1,12),(1,25),(2,13),(2,26),(2,14), +(2,27),(1,15),(1,28),(3,16),(1,29),(2,17),(1,30),(5,18),(2,1); +CREATE TABLE `t3` (`ref_id` int(32) unsigned ,`type` varchar(80),`id` int(32) NOT NULL ); +INSERT INTO `t3` VALUES +(1,'incident',31),(2,'faux pas',32), +(5,'oopsies',33),(3,'deniable',34), +(11,'wasntme',35),(10,'wasntme',36), +(17,'faux pas',37),(13,'unlikely',38), +(13,'improbable',39),(14,'incident',40), +(26,'problem',41),(14,'problem',42), +(26,'incident',43),(27,'incident',44); +explain +SELECT t2.id FROM t2,t1 +WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 30 Using index +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 Using where +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.id 1 Using index +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 14 +2 MATERIALIZED t1 eq_ref PRIMARY PRIMARY 4 test.t3.id 1 Using index +SELECT t2.id FROM t2,t1 +WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +id +10 +11 +set optimizer_switch='materialization=off'; +SELECT t2.id FROM t2,t1 +WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +id +11 +10 +set optimizer_switch='materialization=on'; +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/subselect_sj2_mat.test b/mysql-test/t/subselect_sj2_mat.test index 0665cdf68fe..43b63459928 100644 --- a/mysql-test/t/subselect_sj2_mat.test +++ b/mysql-test/t/subselect_sj2_mat.test @@ -345,3 +345,52 @@ WHERE ( (t.id IN (0,4,12,13,1,10,3,11)) ); drop table t1; +--echo # +--echo # MDEV-15982: Incorrect results when subquery is materialized +--echo # + +CREATE TABLE `t1` (`id` int(32) NOT NULL primary key); +INSERT INTO `t1` VALUES +(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), (135), (136), (137), (138), (139), (140), (141), (142), (143), (144), (145), (146), +(147), (148), (149), (150), (151), (152), (153), (154), (155), (156), (157), (158), (159), (160), (161), +(162), (163), (164), (165), (166), (167), (168), (169), (170), (171), (172), (173), +(174), (175), (176), (177), (178), (179), (180), (181), (182), (183), (2), (3), (4), (5), (6), (19), (35), +(7), (20), (8), (36), (219), (22), (10), (23), (37), (11), (24); + +CREATE TABLE `t2` (`type` int , `id` int(32) NOT NULL primary key); +INSERT INTO `t2` VALUES +(2,2),(2,3),(1,4),(2,5),(1,6),(1,19),(5,7),(1,20),(1,8),(1,21),(1,9), +(1,22),(2,10),(1,23),(2,11),(1,24),(1,12),(1,25),(2,13),(2,26),(2,14), +(2,27),(1,15),(1,28),(3,16),(1,29),(2,17),(1,30),(5,18),(2,1); + +CREATE TABLE `t3` (`ref_id` int(32) unsigned ,`type` varchar(80),`id` int(32) NOT NULL ); +INSERT INTO `t3` VALUES +(1,'incident',31),(2,'faux pas',32), +(5,'oopsies',33),(3,'deniable',34), +(11,'wasntme',35),(10,'wasntme',36), +(17,'faux pas',37),(13,'unlikely',38), +(13,'improbable',39),(14,'incident',40), +(26,'problem',41),(14,'problem',42), +(26,'incident',43),(27,'incident',44); + +explain +SELECT t2.id FROM t2,t1 + WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; + +SELECT t2.id FROM t2,t1 + WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; + +set optimizer_switch='materialization=off'; + +SELECT t2.id FROM t2,t1 + WHERE t2.id IN (SELECT t3.ref_id FROM t3,t1 where t3.id = t1.id) and t2.id = t1.id; +set optimizer_switch='materialization=on'; + +DROP TABLE t1,t2,t3; + + diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index ec7b10f20c8..14b2aaee591 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3532,7 +3532,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) first= tablenr - sjm->tables + 1; join->best_positions[first].n_sj_tables= sjm->tables; join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE; - join->sjm_lookup_tables|= s->table->map; + for (uint i= first; i < first+ sjm->tables; i++) + join->sjm_lookup_tables |= join->best_positions[i].table->table->map; } else if (pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN) {