From c9a73aa20476527fc8f610f80f972dc7ae737a7a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 May 2012 14:49:52 +0300 Subject: [PATCH 01/17] Fix bug lp:993745 This is a backport of the fix for MySQL bug #13723054 in 5.6. Original comment: The crash is caused by arbitrary memory area owerwriting in case of BLOB fields during attempt to copy BLOB field key image into record buffer(record buffer is too small to get BLOB key part image). note: QUICK_GROUP_MIN_MAX_SELECT can not work with BLOB fields because it uses record buffer as temporary buffer for key values however this case is filtered out by covering_keys() check in get_best_group_min_max() as BLOBs always require key length modificator in the key declaration and if the key has a BLOB then it can not be covered key. The fix is to use 'max_used_key_length' key length instead of 0. Analysis: Spcifically the crash in this bug was a result of the call to key_copy() that copied the whole key, inlcuding the BLOB field which is not used for index access. Copying the blob field overwrote memory as far as the function parameter 'key_info'. As a result the contents of key_info was all 0, which resulted in a crash when this key_info was accessed few lines below in key_cmp(). --- mysql-test/r/func_group_innodb.result | 13 +++++++++++++ mysql-test/t/func_group_innodb.test | 14 ++++++++++++++ sql/opt_range.cc | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_group_innodb.result b/mysql-test/r/func_group_innodb.result index 908e85c1652..8c016787e03 100644 --- a/mysql-test/r/func_group_innodb.result +++ b/mysql-test/r/func_group_innodb.result @@ -145,3 +145,16 @@ select count(*), min(7), max(7) from t2m, t1i; count(*) min(7) max(7) 0 NULL NULL drop table t1m, t1i, t2m, t2i; +# +# Bug#13723054 CRASH WITH MIN/MAX AFTER QUICK_GROUP_MIN_MAX_SELECT::NEXT_MIN +# +CREATE TABLE t1(a BLOB, b VARCHAR(255) CHARSET LATIN1, c INT, +KEY(b, c, a(765))) ENGINE=INNODB; +INSERT INTO t1(a, b, c) VALUES ('', 'a', 0), ('', 'a', null), ('', 'a', 0); +SELECT MIN(c) FROM t1 GROUP BY b; +MIN(c) +0 +EXPLAIN SELECT MIN(c) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL b 263 NULL 4 Using index for group-by +DROP TABLE t1; diff --git a/mysql-test/t/func_group_innodb.test b/mysql-test/t/func_group_innodb.test index 1bdfd8f54bb..9e88894de58 100644 --- a/mysql-test/t/func_group_innodb.test +++ b/mysql-test/t/func_group_innodb.test @@ -83,3 +83,17 @@ explain select count(*), min(7), max(7) from t2m, t1i; select count(*), min(7), max(7) from t2m, t1i; drop table t1m, t1i, t2m, t2i; + + +--echo # +--echo # Bug#13723054 CRASH WITH MIN/MAX AFTER QUICK_GROUP_MIN_MAX_SELECT::NEXT_MIN +--echo # + +CREATE TABLE t1(a BLOB, b VARCHAR(255) CHARSET LATIN1, c INT, + KEY(b, c, a(765))) ENGINE=INNODB; +INSERT INTO t1(a, b, c) VALUES ('', 'a', 0), ('', 'a', null), ('', 'a', 0); + +SELECT MIN(c) FROM t1 GROUP BY b; +EXPLAIN SELECT MIN(c) FROM t1 GROUP BY b; + +DROP TABLE t1; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 185f3eecd3c..2d0656333bd 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -10827,7 +10827,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min() if (min_max_arg_part && min_max_arg_part->field->is_null()) { /* Find the first subsequent record without NULL in the MIN/MAX field. */ - key_copy(tmp_record, record, index_info, 0); + key_copy(tmp_record, record, index_info, max_used_key_length); result= file->ha_index_read_map(record, tmp_record, make_keypart_map(real_key_parts), HA_READ_AFTER_KEY); From 213476ef3e2649c928c65705c08176282afbb55b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2012 11:02:58 +0300 Subject: [PATCH 02/17] Fix for bug lp:992405 The patch backports two patches from mysql 5.6: - BUG#12640437: USING SQL_BUFFER_RESULT RESULTS IN A DIFFERENT QUERY OUTPUT - Bug#12578908: SELECT SQL_BUFFER_RESULT OUTPUTS TOO MANY ROWS WHEN GROUP IS OPTIMIZED AWAY Original comment: ----------------- 3714 Jorgen Loland 2012-03-01 BUG#12640437 - USING SQL_BUFFER_RESULT RESULTS IN A DIFFERENT QUERY OUTPUT For all but simple grouped queries, temporary tables are used to resolve grouping. In these cases, the list of grouping fields is stored in the temporary table and grouping is resolved there (e.g. by adding a unique constraint on the involved fields). Because of this, grouping is already done when the rows are read from the temporary table. In the case where a group clause may be optimized away, grouping does not have to be resolved using a temporary table. However, if a temporary table is explicitly requested (e.g. because the SQL_BUFFER_RESULT hint is used, or the statement is INSERT...SELECT), a temporary table is used anyway. In this case, the temporary table is created with an empty group list (because the group clause was optimized away) and it will therefore not create groups. Since the temporary table does not take care of grouping, JOIN::group shall not be set to false in make_simple_join(). This was fixed in bug 12578908. However, there is an exception where make_simple_join() should set JOIN::group to false even if the query uses a temporary table that was explicitly requested but is not strictly needed. That exception is if the loose index scan access method (explain says "Using index for group-by") is used to read into the temporary table. With loose index scan, grouping is resolved by the access method. This is exactly what happens in this bug. --- mysql-test/r/group_by.result | 54 ++++++++++++++++++++++++++++++++++++ mysql-test/t/group_by.test | 54 +++++++++++++++++++++++++++++++++++- sql/sql_select.cc | 27 ++++++++++++++++-- 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 5a3fc7a337c..609604c2d66 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -2005,4 +2005,58 @@ zzz 8 #TODO: in merge with 5.3 add original test suite drop table t1, t2; +# +# Bug#12578908: SELECT SQL_BUFFER_RESULT OUTPUTS TOO MANY +# ROWS WHEN GROUP IS OPTIMIZED AWAY +# +CREATE TABLE t1 (col1 int, col2 int) ; +INSERT INTO t1 VALUES (10,1),(11,7); +CREATE TABLE t2 (col1 int, col2 int) ; +INSERT INTO t2 VALUES (10,8); + +EXPLAIN SELECT SQL_BUFFER_RESULT t2.col2 FROM t2 JOIN t1 ON t1.col1 GROUP BY t2.col2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 system NULL NULL NULL NULL 1 Using temporary +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +SELECT SQL_BUFFER_RESULT t2.col2 FROM t2 JOIN t1 ON t1.col1 GROUP BY t2.col2; +col2 +8 + +EXPLAIN SELECT t2.col2 FROM t2 JOIN t1 ON t1.col1 GROUP BY t2.col2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 system NULL NULL NULL NULL 1 +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +SELECT t2.col2 FROM t2 JOIN t1 ON t1.col1 GROUP BY t2.col2; +col2 +8 + +DROP TABLE t1,t2; +# +# BUG#12640437: USING SQL_BUFFER_RESULT RESULTS IN A +# DIFFERENT QUERY OUTPUT +# +CREATE TABLE t1 ( +a int, +b varchar(1), +KEY (b,a) +); +INSERT INTO t1 VALUES (1,NULL),(0,'a'); + +EXPLAIN SELECT SQL_BUFFER_RESULT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range b b 9 NULL 2 Using where; Using index for group-by; Using temporary + +SELECT SQL_BUFFER_RESULT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +MIN(a) b +0 a + +EXPLAIN SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range b b 9 NULL 2 Using where; Using index for group-by + +SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +MIN(a) b +0 a + +DROP TABLE t1; # End of 5.2 tests diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 3206893fa6d..7fd7aaccfdf 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1372,5 +1372,57 @@ GROUP BY zzz; drop table t1, t2; ---echo # End of 5.2 tests +--echo # +--echo # Bug#12578908: SELECT SQL_BUFFER_RESULT OUTPUTS TOO MANY +--echo # ROWS WHEN GROUP IS OPTIMIZED AWAY +--echo # +CREATE TABLE t1 (col1 int, col2 int) ; +INSERT INTO t1 VALUES (10,1),(11,7); + +CREATE TABLE t2 (col1 int, col2 int) ; +INSERT INTO t2 VALUES (10,8); + +let $q_body=t2.col2 FROM t2 JOIN t1 ON t1.col1 GROUP BY t2.col2; + +--echo +--eval EXPLAIN SELECT SQL_BUFFER_RESULT $q_body +--eval SELECT SQL_BUFFER_RESULT $q_body +--echo +--eval EXPLAIN SELECT $q_body +--eval SELECT $q_body + +--echo +DROP TABLE t1,t2; + +--echo # +--echo # BUG#12640437: USING SQL_BUFFER_RESULT RESULTS IN A +--echo # DIFFERENT QUERY OUTPUT +--echo # + +CREATE TABLE t1 ( + a int, + b varchar(1), + KEY (b,a) +); + +INSERT INTO t1 VALUES (1,NULL),(0,'a'); + +let $query= + SELECT SQL_BUFFER_RESULT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; + +--echo +--eval EXPLAIN $query +--echo +--eval $query + +let $query= SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; +--echo +--eval EXPLAIN $query +--echo +--eval $query + +--echo +DROP TABLE t1; + +--echo # End of 5.2 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7a2940ce6ff..d093a9ada3b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1306,7 +1306,6 @@ JOIN::optimize() simple_order=1; select_distinct= 0; // No need in distinct for 1 row group_optimized_away= 1; - implicit_grouping= TRUE; } calc_group_buffer(this, group_list); @@ -6072,7 +6071,31 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table) tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; first_record= sort_and_group=0; send_records= (ha_rows) 0; - group= 0; + + if (group_optimized_away && !tmp_table_param.precomputed_group_by) + { + /* + If grouping has been optimized away, a temporary table is + normally not needed unless we're explicitly requested to create + one (e.g. due to a SQL_BUFFER_RESULT hint or INSERT ... SELECT). + + In this case (grouping was optimized away), temp_table was + created without a grouping expression and JOIN::exec() will not + perform the necessary grouping (by the use of end_send_group() + or end_write_group()) if JOIN::group is set to false. + + There is one exception: if the loose index scan access method is + used to read into the temporary table, grouping and aggregate + functions are handled. + */ + // the temporary table was explicitly requested + DBUG_ASSERT(test(select_options & OPTION_BUFFER_RESULT)); + // the temporary table does not have a grouping expression + DBUG_ASSERT(!temp_table->group); + } + else + group= false; + row_limit= unit->select_limit_cnt; do_send_rows= row_limit ? 1 : 0; From 8065143637dd622b094e548ae373a28bbe78e028 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2012 13:26:34 +0300 Subject: [PATCH 03/17] Fix for LP bug#993726 Optimization of aggregate functions detected constant under max() and evalueted it, but condition in the WHWRE clause (which is always FALSE) was not taken into account --- mysql-test/r/group_by.result | 12 ++++++++++++ mysql-test/t/group_by.test | 9 +++++++++ sql/opt_sum.cc | 4 +++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 609604c2d66..ad4fc2b98bb 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -2059,4 +2059,16 @@ MIN(a) b 0 a DROP TABLE t1; +# +# LP bug#993726 Wrong result from a query with ALL subquery predicate in WHERE +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (0); +SELECT 1 FROM t1 WHERE 1 > ALL(SELECT 1 FROM t1 WHERE a!=0); +1 +1 +SELECT max(1) FROM t1 WHERE a!=0; +max(1) +NULL +drop table t1; # End of 5.2 tests diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 7fd7aaccfdf..34bab173985 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1425,4 +1425,13 @@ let $query= SELECT MIN(a), b FROM t1 WHERE t1.b = 'a' GROUP BY b; --echo DROP TABLE t1; +--echo # +--echo # LP bug#993726 Wrong result from a query with ALL subquery predicate in WHERE +--echo # +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (0); +SELECT 1 FROM t1 WHERE 1 > ALL(SELECT 1 FROM t1 WHERE a!=0); +SELECT max(1) FROM t1 WHERE a!=0; +drop table t1; + --echo # End of 5.2 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 92a286a3b1c..35986cf7fc0 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -403,7 +403,7 @@ int opt_sum_query(THD *thd, } removed_tables|= table->map; } - else if (!expr->const_item() || !is_exact_count) + else if (!expr->const_item() || !is_exact_count || conds) { /* The optimization is not applicable in both cases: @@ -413,6 +413,8 @@ int opt_sum_query(THD *thd, NULL if the query does not return any rows. Thus, if we are not able to determine if the query returns any rows, we can't apply the optimization and replace MIN/MAX with a constant. + (c) there is a WHERE clause. The WHERE conditions may result in + an empty result, but the clause cannot be taken into account here. */ const_result= 0; break; From ea8314fdd537d14061bb261e6494f38a8fc9291b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2012 21:14:37 +0300 Subject: [PATCH 04/17] LP bug#994275 fix. In 5.3 we substitute constants in ref access values it can't be null so we do not need add NOT NULL for early NULL filtering. --- mysql-test/r/select.result | 12 ++++++++++++ mysql-test/r/select_jcl6.result | 12 ++++++++++++ mysql-test/r/select_pkeycache.result | 12 ++++++++++++ mysql-test/t/select.test | 15 +++++++++++++++ sql/sql_select.cc | 10 ++++++++++ 5 files changed, 61 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e25df1c7634..51e347ab728 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -5101,3 +5101,15 @@ Warning 1292 Incorrect datetime value: 'aa' DROP TABLE t1; DROP VIEW v1; SET optimizer_switch=@save_optimizer_switch; +# +# LP bug#994275 Assertion `real->type() == Item::FIELD_ITEM' failed +# in add_not_null_conds(JOIN*) with JOIN, ZEROFILL column, PK +# +CREATE TABLE t1 ( a INT(6) ZEROFILL ); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( b INT PRIMARY KEY ); +INSERT INTO t2 VALUES (3),(4); +SELECT * FROM t1, t2 WHERE a=3 AND a=b; +a b +drop table t1,t2; +End of 5.3 tests diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result index f2cadea01e1..6eaa85a9efe 100644 --- a/mysql-test/r/select_jcl6.result +++ b/mysql-test/r/select_jcl6.result @@ -5112,6 +5112,18 @@ Warning 1292 Incorrect datetime value: 'aa' DROP TABLE t1; DROP VIEW v1; SET optimizer_switch=@save_optimizer_switch; +# +# LP bug#994275 Assertion `real->type() == Item::FIELD_ITEM' failed +# in add_not_null_conds(JOIN*) with JOIN, ZEROFILL column, PK +# +CREATE TABLE t1 ( a INT(6) ZEROFILL ); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( b INT PRIMARY KEY ); +INSERT INTO t2 VALUES (3),(4); +SELECT * FROM t1, t2 WHERE a=3 AND a=b; +a b +drop table t1,t2; +End of 5.3 tests set join_cache_level=default; show variables like 'join_cache_level'; Variable_name Value diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result index e25df1c7634..51e347ab728 100644 --- a/mysql-test/r/select_pkeycache.result +++ b/mysql-test/r/select_pkeycache.result @@ -5101,3 +5101,15 @@ Warning 1292 Incorrect datetime value: 'aa' DROP TABLE t1; DROP VIEW v1; SET optimizer_switch=@save_optimizer_switch; +# +# LP bug#994275 Assertion `real->type() == Item::FIELD_ITEM' failed +# in add_not_null_conds(JOIN*) with JOIN, ZEROFILL column, PK +# +CREATE TABLE t1 ( a INT(6) ZEROFILL ); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( b INT PRIMARY KEY ); +INSERT INTO t2 VALUES (3),(4); +SELECT * FROM t1, t2 WHERE a=3 AND a=b; +a b +drop table t1,t2; +End of 5.3 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 75ea88b6bde..b937462e3e9 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4272,3 +4272,18 @@ DROP TABLE t1; DROP VIEW v1; SET optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # LP bug#994275 Assertion `real->type() == Item::FIELD_ITEM' failed +--echo # in add_not_null_conds(JOIN*) with JOIN, ZEROFILL column, PK +--echo # + +CREATE TABLE t1 ( a INT(6) ZEROFILL ); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 ( b INT PRIMARY KEY ); +INSERT INTO t2 VALUES (3),(4); +SELECT * FROM t1, t2 WHERE a=3 AND a=b; +drop table t1,t2; + +--echo End of 5.3 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 20de4c9ffea..86cab59fd2a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7998,6 +7998,16 @@ static void add_not_null_conds(JOIN *join) Item *item= tab->ref.items[keypart]; Item *notnull; Item *real= item->real_item(); + if (real->basic_const_item()) + { + /* + It could be constant instead of field after constant + propagation. + */ + DBUG_ASSERT(real->is_expensive() || // prevent early expensive eval + !real->is_null()); // NULLs are not propagated + continue; + } DBUG_ASSERT(real->type() == Item::FIELD_ITEM); Item_field *not_null_item= (Item_field*)real; JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab; From 597e98bc8355e838ad258abdf79e4a41609b6694 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 8 May 2012 00:26:41 +0200 Subject: [PATCH 05/17] MDEV-261 : mysqtest crashes when assigning variable to result of select , like let x = `SELECT ` The fix is to detect the condition "no active connection", to report error and die. Note, that the check for no active connection was already in place for ordinary commands, and was missing only for assign-variable command. --- client/mysqltest.cc | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 45de35ab84b..7d23bc75af7 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -739,6 +739,9 @@ void handle_error(struct st_command*, const char *err_sqlstate, DYNAMIC_STRING *ds); void handle_no_error(struct st_command*); +static void handle_no_active_connection(struct st_command* command, + struct st_connection *cn, DYNAMIC_STRING *ds); + #ifdef EMBEDDED_LIBRARY /* workaround for MySQL BUG#57491 */ @@ -2287,6 +2290,19 @@ void var_query_set(VAR *var, const char *query, const char** query_end) DBUG_ENTER("var_query_set"); LINT_INIT(res); + if (!mysql) + { + struct st_command command; + memset(&command, 0, sizeof(command)); + command.query= (char*)query; + command.first_word_len= (*query_end - query); + command.first_argument= command.query + command.first_word_len; + command.end= (char*)*query; + command.abort_on_error= 1; /* avoid uninitialized variables */ + handle_no_active_connection(&command, cur_con, &ds_res); + DBUG_VOID_RETURN; + } + /* Only white space or ) allowed past ending ` */ while (end > query && *end != '`') { @@ -2392,6 +2408,12 @@ void var_set_query_get_value(struct st_command *command, VAR *var) DBUG_ENTER("var_set_query_get_value"); LINT_INIT(res); + if (!mysql) + { + handle_no_active_connection(command, cur_con, &ds_res); + DBUG_VOID_RETURN; + } + strip_parentheses(command); DBUG_PRINT("info", ("query: %s", command->query)); check_command_args(command, command->first_argument, query_get_value_args, @@ -2550,6 +2572,7 @@ void eval_expr(VAR *v, const char *p, const char **p_end, bool do_eval) command.first_word_len= len; command.first_argument= command.query + len; command.end= (char*)*p_end; + command.abort_on_error= 1; /* avoid uninitialized variables */ var_set_query_get_value(&command, v); DBUG_VOID_RETURN; } @@ -6924,6 +6947,22 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) } +/* + Handle situation where query is sent but there is no active connection + (e.g directly after disconnect). + + We emulate MySQL-compatible behaviour of sending something on a closed + connection. +*/ +static void handle_no_active_connection(struct st_command *command, + struct st_connection *cn, DYNAMIC_STRING *ds) +{ + handle_error(command, 2006, "MySQL server has gone away", "000000", ds); + cn->pending= FALSE; + var_set_errno(2006); +} + + /* Run query using MySQL C API @@ -6950,11 +6989,7 @@ void run_query_normal(struct st_connection *cn, struct st_command *command, if (!mysql) { - /* Emulate old behaviour of sending something on a closed connection */ - handle_error(command, 2006, "MySQL server has gone away", - "000000", ds); - cn->pending= FALSE; - var_set_errno(2006); + handle_no_active_connection(command, cn, ds); DBUG_VOID_RETURN; } From 54534a69847c62364ca0a76cec35cf26c34330c6 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 8 May 2012 12:38:22 +0200 Subject: [PATCH 06/17] MDEV-262 : log_state occationally fails in buildbot. The failures are missing entries in the slow query log. The reason for the failure are sleep() calls with short duration 10ms, which is less than the default system timer resolution for various WaitForXXXObject functions (15.6 ms) and thus can't work reliably. The fix is to make sleeps tiny bit longer (20ms from 10ms) in the test. --- mysql-test/r/log_state.result | 28 ++++++++++++++-------------- mysql-test/t/log_state.test | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 654f9d127d3..d296a64b675 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -320,22 +320,22 @@ TRUNCATE TABLE mysql.slow_log; CREATE TABLE t1 (a INT); CREATE TABLE t2 (b INT, PRIMARY KEY (b)); INSERT INTO t2 VALUES (3),(4); -INSERT INTO t1 VALUES (1+sleep(.01)),(2); -INSERT INTO t1 SELECT b+sleep(.01) from t2; -UPDATE t1 SET a=a+sleep(.01) WHERE a>2; -UPDATE t1 SET a=a+sleep(.01) ORDER BY a DESC; -UPDATE t2 set b=b+sleep(.01) limit 1; -UPDATE t1 SET a=a+sleep(.01) WHERE a in (SELECT b from t2); -DELETE FROM t1 WHERE a=a+sleep(.01) ORDER BY a LIMIT 2; +INSERT INTO t1 VALUES (1+sleep(.02)),(2); +INSERT INTO t1 SELECT b+sleep(.02) from t2; +UPDATE t1 SET a=a+sleep(.02) WHERE a>2; +UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC; +UPDATE t2 set b=b+sleep(.02) limit 1; +UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2); +DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2; SELECT rows_examined,sql_text FROM mysql.slow_log; rows_examined sql_text -0 INSERT INTO t1 VALUES (1+sleep(.01)),(2) -2 INSERT INTO t1 SELECT b+sleep(.01) from t2 -4 UPDATE t1 SET a=a+sleep(.01) WHERE a>2 -8 UPDATE t1 SET a=a+sleep(.01) ORDER BY a DESC -2 UPDATE t2 set b=b+sleep(.01) limit 1 -4 UPDATE t1 SET a=a+sleep(.01) WHERE a in (SELECT b from t2) -6 DELETE FROM t1 WHERE a=a+sleep(.01) ORDER BY a LIMIT 2 +0 INSERT INTO t1 VALUES (1+sleep(.02)),(2) +2 INSERT INTO t1 SELECT b+sleep(.02) from t2 +4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2 +8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC +2 UPDATE t2 set b=b+sleep(.02) limit 1 +4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2) +6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2 DROP TABLE t1,t2; TRUNCATE TABLE mysql.slow_log; # end of bug#49756 diff --git a/mysql-test/t/log_state.test b/mysql-test/t/log_state.test index 05e17dc9fa7..032c46e83b6 100644 --- a/mysql-test/t/log_state.test +++ b/mysql-test/t/log_state.test @@ -381,13 +381,13 @@ CREATE TABLE t2 (b INT, PRIMARY KEY (b)); INSERT INTO t2 VALUES (3),(4); connect (con2,localhost,root,,); -INSERT INTO t1 VALUES (1+sleep(.01)),(2); -INSERT INTO t1 SELECT b+sleep(.01) from t2; -UPDATE t1 SET a=a+sleep(.01) WHERE a>2; -UPDATE t1 SET a=a+sleep(.01) ORDER BY a DESC; -UPDATE t2 set b=b+sleep(.01) limit 1; -UPDATE t1 SET a=a+sleep(.01) WHERE a in (SELECT b from t2); -DELETE FROM t1 WHERE a=a+sleep(.01) ORDER BY a LIMIT 2; +INSERT INTO t1 VALUES (1+sleep(.02)),(2); +INSERT INTO t1 SELECT b+sleep(.02) from t2; +UPDATE t1 SET a=a+sleep(.02) WHERE a>2; +UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC; +UPDATE t2 set b=b+sleep(.02) limit 1; +UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2); +DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2; SELECT rows_examined,sql_text FROM mysql.slow_log; disconnect con2; From 4e2926d927e51f47f51ccbb0ec77ffd9999f68c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 May 2012 19:13:26 +0300 Subject: [PATCH 07/17] Addition to the fix to LP bug#994275. It is problem of constant propagated to ref* access method (the problem was hiden by using debug binaries for testing). --- sql/sql_select.cc | 15 +++++++++++++-- sql/sql_select.h | 14 +++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 86cab59fd2a..fccd94ec3cd 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1289,8 +1289,19 @@ JOIN::optimize() store_key *key_copy= tab->ref.key_copy[key_copy_index]; if (key_copy->type() == store_key::FIELD_STORE_KEY) { - store_key_field *field_copy= ((store_key_field *)key_copy); - field_copy->change_source_field((Item_field *) item); + if (item->basic_const_item()) + { + /* It is constant propagated here */ + tab->ref.key_copy[key_copy_index]= + new store_key_const_item(*tab->ref.key_copy[key_copy_index], + item); + } + else + { + store_key_field *field_copy= ((store_key_field *)key_copy); + DBUG_ASSERT(item->type() == Item::FIELD_ITEM); + field_copy->change_source_field((Item_field *) item); + } } } key_copy_index++; diff --git a/sql/sql_select.h b/sql/sql_select.h index 2724c4a5a63..22bdd93a38c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1468,6 +1468,11 @@ public: to_field=field_arg->new_key_field(thd->mem_root, field_arg->table, ptr, null, 1); } + store_key(store_key &arg) + :null_key(arg.null_key), to_field(arg.to_field), + null_ptr(arg.null_ptr), err(arg.err) + + {} virtual ~store_key() {} /** Not actually needed */ virtual enum Type type() const=0; virtual const char *name() const=0; @@ -1572,6 +1577,10 @@ public: null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : (uchar*) 0, length), item(item_arg), use_value(val) {} + store_key_item(store_key &arg, Item *new_item, bool val) + :store_key(arg), item(new_item), use_value(val) + {} + enum Type type() const { return ITEM_STORE_KEY; } const char *name() const { return "func"; } @@ -1617,11 +1626,14 @@ public: store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr, uchar *null_ptr_arg, uint length, Item *item_arg) - :store_key_item(thd, to_field_arg,ptr, + :store_key_item(thd, to_field_arg, ptr, null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : (uchar*) 0, length, item_arg, FALSE), inited(0) { } + store_key_const_item(store_key &arg, Item *new_item) + :store_key_item(arg, new_item, FALSE), inited(0) + {} enum Type type() const { return CONST_ITEM_STORE_KEY; } const char *name() const { return "const"; } From fe0a0bdb143696c54206cd5f908dac94996aab42 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 May 2012 20:58:41 +0300 Subject: [PATCH 08/17] Fix compiler warnings. --- sql/sql_select.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.h b/sql/sql_select.h index 22bdd93a38c..ab531f66649 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1469,7 +1469,7 @@ public: ptr, null, 1); } store_key(store_key &arg) - :null_key(arg.null_key), to_field(arg.to_field), + :Sql_alloc(), null_key(arg.null_key), to_field(arg.to_field), null_ptr(arg.null_ptr), err(arg.err) {} From 6fc863c7495d7715684918842b062bd6209b7d53 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 May 2012 09:00:21 +0300 Subject: [PATCH 09/17] Fixed typo --- client/mysqltest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 7d23bc75af7..6cf9918e829 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -2297,7 +2297,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end) command.query= (char*)query; command.first_word_len= (*query_end - query); command.first_argument= command.query + command.first_word_len; - command.end= (char*)*query; + command.end= (char*)*query_end; command.abort_on_error= 1; /* avoid uninitialized variables */ handle_no_active_connection(&command, cur_con, &ds_res); DBUG_VOID_RETURN; From f2cbc014d98a927ed7038f55a25c3d288de10f51 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 May 2012 09:35:46 +0300 Subject: [PATCH 10/17] fix for LP bug#994392 The not_null_tables() of Item_func_not_all and Item_in_optimizer was inherited from Item_func by mistake. It made the optimizer think that subquery predicates with ALL/ANY/IN were null-rejecting. This could trigger invalid conversions of outer joins into inner joins. --- mysql-test/r/join_outer.result | 24 ++++++++++++++++++++++++ mysql-test/t/join_outer.test | 19 +++++++++++++++++++ sql/item_cmpfunc.h | 2 ++ 3 files changed, 45 insertions(+) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index e7636573201..12989fdb036 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1596,3 +1596,27 @@ f 1 DROP TABLE t1; End of 5.1 tests +# +# LP BUG#994392: Wrong result with RIGHT/LEFT JOIN and ALL subquery +# predicate in WHERE condition. +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(9); +CREATE TABLE t2(b INT); +INSERT INTO t2 VALUES(8); +CREATE TABLE t3(c INT); +INSERT INTO t3 VALUES(3); +SELECT * FROM t2 RIGHT JOIN t3 ON(c = b) WHERE b < ALL(SELECT a FROM t1 WHERE a <= 7); +b c +NULL 3 +SELECT * FROM t3 LEFT JOIN t2 ON(c = b) WHERE b < ALL(SELECT a FROM t1 WHERE a <= 7); +c b +3 NULL +SELECT * FROM t2 RIGHT JOIN t3 ON(c = b) WHERE b not in (SELECT a FROM t1 WHERE a <= 7); +b c +NULL 3 +SELECT * FROM t3 LEFT JOIN t2 ON(c = b) WHERE b not in (SELECT a FROM t1 WHERE a <= 7); +c b +3 NULL +drop table t1,t2,t3; +End of 5.2 tests diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 5e18f77c422..01f1980b4c1 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1162,3 +1162,22 @@ DROP TABLE t1; --echo End of 5.1 tests + +--echo # +--echo # LP BUG#994392: Wrong result with RIGHT/LEFT JOIN and ALL subquery +--echo # predicate in WHERE condition. +--echo # + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(9); +CREATE TABLE t2(b INT); +INSERT INTO t2 VALUES(8); +CREATE TABLE t3(c INT); +INSERT INTO t3 VALUES(3); +SELECT * FROM t2 RIGHT JOIN t3 ON(c = b) WHERE b < ALL(SELECT a FROM t1 WHERE a <= 7); +SELECT * FROM t3 LEFT JOIN t2 ON(c = b) WHERE b < ALL(SELECT a FROM t1 WHERE a <= 7); +SELECT * FROM t2 RIGHT JOIN t3 ON(c = b) WHERE b not in (SELECT a FROM t1 WHERE a <= 7); +SELECT * FROM t3 LEFT JOIN t2 ON(c = b) WHERE b not in (SELECT a FROM t1 WHERE a <= 7); +drop table t1,t2,t3; + +--echo End of 5.2 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index ca3989d8b2c..5f8a7c6bd22 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -257,6 +257,7 @@ public: {} bool fix_fields(THD *, Item **); bool fix_left(THD *thd, Item **ref); + table_map not_null_tables() const { return 0; } bool is_null(); longlong val_int(); void cleanup(); @@ -473,6 +474,7 @@ public: show(0) {} virtual void top_level_item() { abort_on_null= 1; } + table_map not_null_tables() const { return 0; } bool top_level() { return abort_on_null; } longlong val_int(); enum Functype functype() const { return NOT_ALL_FUNC; } From 97ae1682f185be05276b172919e47fd86e9fd953 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Sat, 12 May 2012 11:53:14 +0400 Subject: [PATCH 11/17] BUG#997747: Assertion `join->best_read < ((double)1.79..5e+308L)' failed in greedy_search with LEFT JOINs and unique keys - Backport the fix for BUG#806524 from MariaDB 5.3 --- mysql-test/r/table_elim.result | 21 +++++++++++++++++++++ mysql-test/t/table_elim.test | 22 ++++++++++++++++++++++ sql/sql_select.cc | 8 +++++--- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/table_elim.result b/mysql-test/r/table_elim.result index 6c713946b27..cd7d3cb6973 100644 --- a/mysql-test/r/table_elim.result +++ b/mysql-test/r/table_elim.result @@ -566,3 +566,24 @@ id select_type table type possible_keys key key_len ref rows Extra # ^^ The above must not produce a QEP of t3,t5,t2,t4 # as that violates the "no interleaving of outer join nests" rule. DROP TABLE t1,t2,t3,t4,t5; +# +# BUG#997747: Assertion `join->best_read < ((double)1.79..5e+308L)' +# failed in greedy_search with LEFT JOINs and unique keys +# +CREATE TABLE t1 (a1 INT); +CREATE TABLE t2 (b1 INT); +CREATE TABLE t3 (c1 INT, UNIQUE KEY(c1)); +CREATE TABLE t4 (d1 INT, UNIQUE KEY(d1)); +CREATE TABLE t5 (e1 INT); +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (2),(3); +INSERT INTO t3 VALUES (3),(4); +INSERT INTO t4 VALUES (4),(5); +INSERT INTO t5 VALUES (5),(6); +SELECT a1 FROM t1 LEFT JOIN t2 LEFT JOIN t3 LEFT JOIN t4 +ON c1 = d1 ON d1 = b1 ON a1 = b1 +LEFT JOIN t5 ON a1 = e1 ; +a1 +1 +2 +DROP TABLE t1,t2,t3,t4,t5; diff --git a/mysql-test/t/table_elim.test b/mysql-test/t/table_elim.test index 5576362b396..f5a90efe9a3 100644 --- a/mysql-test/t/table_elim.test +++ b/mysql-test/t/table_elim.test @@ -499,3 +499,25 @@ WHERE t3.f2 ; DROP TABLE t1,t2,t3,t4,t5; +--echo # +--echo # BUG#997747: Assertion `join->best_read < ((double)1.79..5e+308L)' +--echo # failed in greedy_search with LEFT JOINs and unique keys +--echo # +CREATE TABLE t1 (a1 INT); +CREATE TABLE t2 (b1 INT); +CREATE TABLE t3 (c1 INT, UNIQUE KEY(c1)); +CREATE TABLE t4 (d1 INT, UNIQUE KEY(d1)); +CREATE TABLE t5 (e1 INT); + +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (2),(3); +INSERT INTO t3 VALUES (3),(4); +INSERT INTO t4 VALUES (4),(5); +INSERT INTO t5 VALUES (5),(6); + +SELECT a1 FROM t1 LEFT JOIN t2 LEFT JOIN t3 LEFT JOIN t4 +ON c1 = d1 ON d1 = b1 ON a1 = b1 +LEFT JOIN t5 ON a1 = e1 ; + +DROP TABLE t1,t2,t3,t4,t5; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5fc6a8e9f8d..932fdf1b2cf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9130,14 +9130,16 @@ static uint reset_nj_counters(JOIN *join, List *join_list) while ((table= li++)) { NESTED_JOIN *nested_join; + bool is_eliminated_nest= FALSE; if ((nested_join= table->nested_join)) { nested_join->counter= 0; - //nested_join->n_tables= my_count_bits(nested_join->used_tables & - // ~join->eliminated_tables); nested_join->n_tables= reset_nj_counters(join, &nested_join->join_list); + if (!nested_join->n_tables) + is_eliminated_nest= TRUE; } - if (!table->table || (table->table->map & ~join->eliminated_tables)) + if ((table->nested_join && !is_eliminated_nest) || + (!table->nested_join && (table->table->map & ~join->eliminated_tables))) n++; } DBUG_RETURN(n); From 6d41fa0d54b7173cd5d700819e022f9c2690f5ec Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Sun, 13 May 2012 13:15:17 +0400 Subject: [PATCH 12/17] BUG#998236: Assertion failure or valgrind errors at best_access_path ... - Let fix_semijoin_strategies_for_picked_join_order() set POSITION::prefix_record_count for POSITION records that it copies from SJ_MATERIALIZATION_INFO::tables. (These records do not have prefix_record_count set, because they are optimized as joins-inside-semijoin-nests, without full advance_sj_state() processing). --- mysql-test/r/subselect_sj.result | 42 ++++++++++++++++++++++++ mysql-test/r/subselect_sj_jcl6.result | 42 ++++++++++++++++++++++++ mysql-test/t/subselect_sj.test | 46 +++++++++++++++++++++++++++ sql/opt_subselect.cc | 22 +++++++++++++ 4 files changed, 152 insertions(+) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index db0a278bc8a..3933100a7aa 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -2701,4 +2701,46 @@ DROP VIEW v1; DROP TABLE t1; set @@join_cache_level= @tmp_jcl_978479; set @@optimizer_switch= @tmp_os_978479; +# +# BUG#998236: Assertion failure or valgrind errors at best_access_path ... +# +CREATE TABLE t1 (a1 VARCHAR(3), a2 VARCHAR(35), KEY(a1,a2)) ENGINE=MyISAM; +INSERT INTO t1 VALUES +('USA','Arvada'),('USA','Athens'),('USA','Atlanta'),('USA','Augusta'), +('USA','Aurora'),('USA','Aurora'),('USA','Austin'),('USA','Bakersfield'), +('USA','Baltimore'),('USA','Baton'),('USA','Beaumont'),('USA','Bellevue'), +('USA','Berkeley'),('USA','Billings'),('USA','Birmingham'),('USA','Boise'), +('USA','Boston'),('USA','Boulder'),('USA','Bridgeport'),('USA','Brockton'), +('USA','Brownsville'),('USA','Buffalo'),('USA','Burbank'),('USA','Cambridge'), +('USA','Cape'),('USA','Carrollton'),('USA','Carson'),('USA','Cary'), +('USA','Cedar'),('USA','Chandler'),('USA','Charleston'),('USA','Charlotte'), +('USA','Chattanooga'),('USA','Chesapeake'),('USA','Chicago'),('USA','Chula'), +('USA','Cincinnati'),('USA','Citrus'),('USA','Clarksville'),('USA','Clearwater'), +('USA','Cleveland'),('USA','Colorado'),('USA','Columbia'),('USA','Columbus'), +('USA','Columbus'),('USA','Compton'),('USA','Concord'),('USA','Coral'), +('USA','Corona'),('USA','Corpus'),('USA','Costa'),('USA','Dallas'),('USA','Daly'), +('USA','Davenport'),('USA','Dayton'),('USA','Denver'),('USA','DesMoines'), +('USA','Detroit'),('USA','Downey'),('USA','Durham'),('USA','East'),('USA','ElCajon'), +('USA','ElMonte'),('USA','ElPaso'),('USA','Elgin'),('USA','Elizabeth'), +('USA','Erie'),('USA','Escondido'),('USA','Eugene'),('USA','Evansville'), +('USA','Fairfield'),('USA','Fall'),('USA','Fayetteville'),('USA','Flint'), +('USA','Fontana'),('USA','FortCollins'),('USA','FortLauderdale'),('USA','FortWayne'), +('USA','FortWorth'),('USA','Fremont'),('USA','Fresno'),('USA','Fullerton'), +('USA','Gainesville'),('USA','GardenGrove'),('USA','Garland'),('USA','Gary'), +('USA','Gilbert'),('USA','Glendale'),('USA','Glendale'),('USA','GrandPrairie'), +('USA','GrandRapids'),('USA','Green Bay'),('USA','Greensboro'),('USA','Hampton'), +('USA','Hartford'),('USA','Hayward'),('USA','Henderson'),('USA','Hialeah'), +('USA','Inglewood'),('USA','Livonia'); +CREATE TABLE t3 (c1 VARCHAR(3), c2 VARCHAR(16), PRIMARY KEY (c1,c2)) ENGINE=MyISAM; +INSERT INTO t3 VALUES ('USA','Chinese'), ('USA','English'); +CREATE TABLE t2 (b1 INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +SELECT alias1.a1 AS field1 +FROM t1 AS alias1, t1 AS alias2 +WHERE alias1.a2 IN ( SELECT a1 FROM t1, t2 ) +AND alias1.a1 IS NULL +AND ( alias1.a1, alias2.a1 ) IN ( SELECT c1, c1 FROM t3 ) +GROUP BY field1; +field1 +DROP TABLE t1,t3,t2; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 8e9aba81935..8cc9352bfa3 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -2715,6 +2715,48 @@ DROP VIEW v1; DROP TABLE t1; set @@join_cache_level= @tmp_jcl_978479; set @@optimizer_switch= @tmp_os_978479; +# +# BUG#998236: Assertion failure or valgrind errors at best_access_path ... +# +CREATE TABLE t1 (a1 VARCHAR(3), a2 VARCHAR(35), KEY(a1,a2)) ENGINE=MyISAM; +INSERT INTO t1 VALUES +('USA','Arvada'),('USA','Athens'),('USA','Atlanta'),('USA','Augusta'), +('USA','Aurora'),('USA','Aurora'),('USA','Austin'),('USA','Bakersfield'), +('USA','Baltimore'),('USA','Baton'),('USA','Beaumont'),('USA','Bellevue'), +('USA','Berkeley'),('USA','Billings'),('USA','Birmingham'),('USA','Boise'), +('USA','Boston'),('USA','Boulder'),('USA','Bridgeport'),('USA','Brockton'), +('USA','Brownsville'),('USA','Buffalo'),('USA','Burbank'),('USA','Cambridge'), +('USA','Cape'),('USA','Carrollton'),('USA','Carson'),('USA','Cary'), +('USA','Cedar'),('USA','Chandler'),('USA','Charleston'),('USA','Charlotte'), +('USA','Chattanooga'),('USA','Chesapeake'),('USA','Chicago'),('USA','Chula'), +('USA','Cincinnati'),('USA','Citrus'),('USA','Clarksville'),('USA','Clearwater'), +('USA','Cleveland'),('USA','Colorado'),('USA','Columbia'),('USA','Columbus'), +('USA','Columbus'),('USA','Compton'),('USA','Concord'),('USA','Coral'), +('USA','Corona'),('USA','Corpus'),('USA','Costa'),('USA','Dallas'),('USA','Daly'), +('USA','Davenport'),('USA','Dayton'),('USA','Denver'),('USA','DesMoines'), +('USA','Detroit'),('USA','Downey'),('USA','Durham'),('USA','East'),('USA','ElCajon'), +('USA','ElMonte'),('USA','ElPaso'),('USA','Elgin'),('USA','Elizabeth'), +('USA','Erie'),('USA','Escondido'),('USA','Eugene'),('USA','Evansville'), +('USA','Fairfield'),('USA','Fall'),('USA','Fayetteville'),('USA','Flint'), +('USA','Fontana'),('USA','FortCollins'),('USA','FortLauderdale'),('USA','FortWayne'), +('USA','FortWorth'),('USA','Fremont'),('USA','Fresno'),('USA','Fullerton'), +('USA','Gainesville'),('USA','GardenGrove'),('USA','Garland'),('USA','Gary'), +('USA','Gilbert'),('USA','Glendale'),('USA','Glendale'),('USA','GrandPrairie'), +('USA','GrandRapids'),('USA','Green Bay'),('USA','Greensboro'),('USA','Hampton'), +('USA','Hartford'),('USA','Hayward'),('USA','Henderson'),('USA','Hialeah'), +('USA','Inglewood'),('USA','Livonia'); +CREATE TABLE t3 (c1 VARCHAR(3), c2 VARCHAR(16), PRIMARY KEY (c1,c2)) ENGINE=MyISAM; +INSERT INTO t3 VALUES ('USA','Chinese'), ('USA','English'); +CREATE TABLE t2 (b1 INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +SELECT alias1.a1 AS field1 +FROM t1 AS alias1, t1 AS alias2 +WHERE alias1.a2 IN ( SELECT a1 FROM t1, t2 ) +AND alias1.a1 IS NULL +AND ( alias1.a1, alias2.a1 ) IN ( SELECT c1, c1 FROM t3 ) +GROUP BY field1; +field1 +DROP TABLE t1,t3,t2; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 7f1181bb562..63bb29a2e13 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2398,6 +2398,52 @@ DROP TABLE t1; set @@join_cache_level= @tmp_jcl_978479; set @@optimizer_switch= @tmp_os_978479; +--echo # +--echo # BUG#998236: Assertion failure or valgrind errors at best_access_path ... +--echo # +CREATE TABLE t1 (a1 VARCHAR(3), a2 VARCHAR(35), KEY(a1,a2)) ENGINE=MyISAM; +INSERT INTO t1 VALUES +('USA','Arvada'),('USA','Athens'),('USA','Atlanta'),('USA','Augusta'), +('USA','Aurora'),('USA','Aurora'),('USA','Austin'),('USA','Bakersfield'), +('USA','Baltimore'),('USA','Baton'),('USA','Beaumont'),('USA','Bellevue'), +('USA','Berkeley'),('USA','Billings'),('USA','Birmingham'),('USA','Boise'), +('USA','Boston'),('USA','Boulder'),('USA','Bridgeport'),('USA','Brockton'), +('USA','Brownsville'),('USA','Buffalo'),('USA','Burbank'),('USA','Cambridge'), +('USA','Cape'),('USA','Carrollton'),('USA','Carson'),('USA','Cary'), +('USA','Cedar'),('USA','Chandler'),('USA','Charleston'),('USA','Charlotte'), +('USA','Chattanooga'),('USA','Chesapeake'),('USA','Chicago'),('USA','Chula'), +('USA','Cincinnati'),('USA','Citrus'),('USA','Clarksville'),('USA','Clearwater'), +('USA','Cleveland'),('USA','Colorado'),('USA','Columbia'),('USA','Columbus'), +('USA','Columbus'),('USA','Compton'),('USA','Concord'),('USA','Coral'), +('USA','Corona'),('USA','Corpus'),('USA','Costa'),('USA','Dallas'),('USA','Daly'), +('USA','Davenport'),('USA','Dayton'),('USA','Denver'),('USA','DesMoines'), +('USA','Detroit'),('USA','Downey'),('USA','Durham'),('USA','East'),('USA','ElCajon'), +('USA','ElMonte'),('USA','ElPaso'),('USA','Elgin'),('USA','Elizabeth'), +('USA','Erie'),('USA','Escondido'),('USA','Eugene'),('USA','Evansville'), +('USA','Fairfield'),('USA','Fall'),('USA','Fayetteville'),('USA','Flint'), +('USA','Fontana'),('USA','FortCollins'),('USA','FortLauderdale'),('USA','FortWayne'), +('USA','FortWorth'),('USA','Fremont'),('USA','Fresno'),('USA','Fullerton'), +('USA','Gainesville'),('USA','GardenGrove'),('USA','Garland'),('USA','Gary'), +('USA','Gilbert'),('USA','Glendale'),('USA','Glendale'),('USA','GrandPrairie'), +('USA','GrandRapids'),('USA','Green Bay'),('USA','Greensboro'),('USA','Hampton'), +('USA','Hartford'),('USA','Hayward'),('USA','Henderson'),('USA','Hialeah'), +('USA','Inglewood'),('USA','Livonia'); + +CREATE TABLE t3 (c1 VARCHAR(3), c2 VARCHAR(16), PRIMARY KEY (c1,c2)) ENGINE=MyISAM; +INSERT INTO t3 VALUES ('USA','Chinese'), ('USA','English'); + +# Not reproducible with 2 rows +CREATE TABLE t2 (b1 INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); + +SELECT alias1.a1 AS field1 +FROM t1 AS alias1, t1 AS alias2 +WHERE alias1.a2 IN ( SELECT a1 FROM t1, t2 ) +AND alias1.a1 IS NULL +AND ( alias1.a1, alias2.a1 ) IN ( SELECT c1, c1 FROM t3 ) +GROUP BY field1; + +DROP TABLE t1,t3,t2; # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index ee8e723091a..967981bcc9d 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3159,6 +3159,25 @@ at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab, } +/* + Re-calculate values of join->best_positions[start..end].prefix_record_count +*/ + +static void recalculate_prefix_record_count(JOIN *join, uint start, uint end) +{ + for (uint j= start; j < end ;j++) + { + double prefix_count; + if (j == join->const_tables) + prefix_count= 1.0; + else + prefix_count= join->best_positions[j-1].prefix_record_count * + join->best_positions[j-1].records_read; + + join->best_positions[j].prefix_record_count= prefix_count; + } +} + /* Fix semi-join strategies for the picked join order @@ -3228,6 +3247,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) sjm->is_sj_scan= FALSE; memcpy(pos - sjm->tables + 1, sjm->positions, sizeof(POSITION) * sjm->tables); + recalculate_prefix_record_count(join, tablenr - sjm->tables + 1, + tablenr); first= tablenr - sjm->tables + 1; join->best_positions[first].n_sj_tables= sjm->tables; join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE; @@ -3241,6 +3262,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1; memcpy(join->best_positions + first, sjm->positions, sizeof(POSITION) * sjm->tables); + recalculate_prefix_record_count(join, first, first + sjm->tables); join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN; join->best_positions[first].n_sj_tables= sjm->tables; /* From 3d37b67b2bf978c6755508aef0e0a1e64257f41c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 May 2012 08:31:07 +0300 Subject: [PATCH 13/17] Fix for LP bug#998516 If we did nothing in resolving unique table conflict we should not retry (it leed to infinite loop). Now we retry (recheck) unique table check only in case if we materialized a table. --- mysql-test/r/derived_view.result | 18 ++++++++++++++++++ mysql-test/t/derived_view.test | 13 +++++++++++++ sql/sql_base.cc | 2 +- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index ef8e0a2a9cb..9e6d6db9314 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2087,6 +2087,24 @@ a b drop table t1; set optimizer_switch=@save978847_optimizer_switch; # +# LP bug998516 Server hangs on INSERT .. SELECT with derived_merge, +# FROM subquery, UNION +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +INSERT INTO t1 SELECT * FROM ( SELECT * FROM t1 ) AS alias UNION SELECT * FROM t2; +select * from t1; +a +1 +2 +1 +2 +3 +4 +drop table t1,t2; +# # end of 5.3 tests # set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 3320ca25136..30811be2934 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1437,6 +1437,19 @@ drop table t1; set optimizer_switch=@save978847_optimizer_switch; + +--echo # +--echo # LP bug998516 Server hangs on INSERT .. SELECT with derived_merge, +--echo # FROM subquery, UNION +--echo # +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +INSERT INTO t1 SELECT * FROM ( SELECT * FROM t1 ) AS alias UNION SELECT * FROM t2; +select * from t1; +drop table t1,t2; + --echo # --echo # end of 5.3 tests --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 38e56a49767..628a4bfd919 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1739,8 +1739,8 @@ retry: ("convert merged to materialization to resolve the conflict")); derived->change_refs_to_fields(); derived->set_materialized_derived(); + goto retry; } - goto retry; } DBUG_RETURN(res); } From 5a47413934a0ba0aeb91224f1010bb70bd9b1e8a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 May 2012 10:13:25 +0300 Subject: [PATCH 14/17] fix of LP bug#998321 The problem is that we can't check null_value field of non-basic constant without the item execution.: --- mysql-test/r/func_if.result | 17 +++++++++++++++++ mysql-test/t/func_if.test | 13 +++++++++++++ sql/item_cmpfunc.cc | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 955a784f04c..8d3507f6bed 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -186,3 +186,20 @@ MAX(IFNULL(CAST(c AS UNSIGNED), 0)) 12345678901234567890 DROP TABLE t1; End of 5.0 tests +# +# LP bug#998321 Simple query with IF expression causes an +# assertion abort (see also mysql Bug#12620084) +# +SELECT if(0, (SELECT min('hello')), NULL); +if(0, (SELECT min('hello')), NULL) +NULL +SELECT if(1, (SELECT min('hello')), NULL); +if(1, (SELECT min('hello')), NULL) +hello +SELECT if(0, NULL, (SELECT min('hello'))); +if(0, NULL, (SELECT min('hello'))) +hello +SELECT if(1, NULL, (SELECT min('hello'))); +if(1, NULL, (SELECT min('hello'))) +NULL +End of 5.2 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 8142f57c0de..0d51b95ebe4 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -170,6 +170,19 @@ DROP TABLE t1; --echo End of 5.0 tests + +--echo # +--echo # LP bug#998321 Simple query with IF expression causes an +--echo # assertion abort (see also mysql Bug#12620084) +--echo # + +SELECT if(0, (SELECT min('hello')), NULL); +SELECT if(1, (SELECT min('hello')), NULL); +SELECT if(0, NULL, (SELECT min('hello'))); +SELECT if(1, NULL, (SELECT min('hello'))); + +--echo End of 5.2 tests + --disable_query_log # Restore timezone to default set time_zone= @@global.time_zone; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c4d56a93af6..ea216944dbb 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2659,8 +2659,8 @@ Item_func_if::fix_length_and_dec() enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); - bool null1=args[1]->const_item() && args[1]->null_value; - bool null2=args[2]->const_item() && args[2]->null_value; + bool null1=args[1]->basic_const_item() && args[1]->null_value; + bool null2=args[2]->basic_const_item() && args[2]->null_value; if (null1) { From 0520825803c76be46e5d8a3d62d9d1149fe523c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 May 2012 10:45:20 +0300 Subject: [PATCH 15/17] Test suite of fixed bug (LP bug#993459). --- mysql-test/r/ps.result | 104 +++++++++++++++++++++++++++++++++++++++++ mysql-test/r/sp.result | 39 ++++++++++++++++ mysql-test/t/ps.test | 92 +++++++++++++++++++++++++++++++++++- mysql-test/t/sp.test | 36 ++++++++++++++ 4 files changed, 269 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 09b3c1a3c67..4825b4db403 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -3125,3 +3125,107 @@ Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 deallocate prepare st; drop table t1; +# +# LP bug#993459 Execution of PS for a query with GROUP BY +# returns wrong result (see also mysql bug#13805127) +# +PREPARE s1 FROM +" +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2 +"; + +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE @x = 1 +UNION +SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:99345900:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +c1 c2 count(c3) +2012-03-01 01:00:00 3 1 +2012-03-01 01:99345900:00 2 1 +2012-03-01 02:00:00 3 1 + +EXECUTE s1; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 + +SET @x = 2; +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE @x = 1 +UNION +SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 + +EXECUTE s1; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 + +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE @x = 1 +UNION +SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 + +EXECUTE s1; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 +DEALLOCATE PREPARE s1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index d9c34701bd1..3e7e0b5cd0c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -7108,3 +7108,42 @@ DROP FUNCTION f1; # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ +# +# LP bug#993459 Execution of PS for a query with GROUP BY +# returns wrong result (see also mysql bug#13805127) +# +CREATE PROCEDURE p1(x INT UNSIGNED) +BEGIN +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE x = 1 +UNION +SELECT 2 FROM dual WHERE x = 1 OR x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2 +; +END| + +CALL p1(1); +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 +CALL p1(2); +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +CALL p1(1); +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 +DROP PROCEDURE p1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index a3b064acb04..2f101b4e42f 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3152,6 +3152,94 @@ execute st; show status like '%Handler_read%'; deallocate prepare st; - drop table t1; - + +--echo # +--echo # LP bug#993459 Execution of PS for a query with GROUP BY +--echo # returns wrong result (see also mysql bug#13805127) +--echo # + +PREPARE s1 FROM +" +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2 +"; + +--echo +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:99345900:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +--echo +EXECUTE s1; + +--echo +SET @x = 2; +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +--echo +EXECUTE s1; + +--echo +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +--echo +EXECUTE s1; + +DEALLOCATE PREPARE s1; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index bbbb9784d35..d403e94ebbb 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -8441,3 +8441,39 @@ DROP FUNCTION f1; --echo # ------------------------------------------------------------------ --echo # -- End of 5.1 tests --echo # ------------------------------------------------------------------ + +--echo # +--echo # LP bug#993459 Execution of PS for a query with GROUP BY +--echo # returns wrong result (see also mysql bug#13805127) +--echo # +delimiter |; + +CREATE PROCEDURE p1(x INT UNSIGNED) +BEGIN + SELECT c1, t2.c2, count(c3) + FROM + ( + SELECT 3 as c2 FROM dual WHERE x = 1 + UNION + SELECT 2 FROM dual WHERE x = 1 OR x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 + WHERE t2.c2 = t1.c2 + GROUP BY c1, c2 + ; +END| + +delimiter ;| + +--echo +CALL p1(1); +CALL p1(2); +CALL p1(1); + +DROP PROCEDURE p1; From 57f824b0990b0a8708665a4a9ede245ce6064539 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 18 May 2012 12:42:06 +0200 Subject: [PATCH 16/17] post-merge fixes sql/slave.cc: add mutex protection, like in sql_parse.cc --- mysql-test/suite/innodb/t/disabled.def | 3 ++- mysql-test/suite/innodb_plugin/t/disabled.def | 3 +++ mysql-test/suite/innodb_plugin/t/innodb-blob.test | 1 - sql/slave.cc | 6 +++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def index 6536c0221f8..46309c92bbe 100644 --- a/mysql-test/suite/innodb/t/disabled.def +++ b/mysql-test/suite/innodb/t/disabled.def @@ -10,6 +10,7 @@ # ############################################################################## -#innodb_bug53756 : Waiting for merge with Percona Server; bug fixed in innodb_plugin in MySQL 5.1.50 +innodb_bug13635833: Disabled until merging with XtraDB 5.1.63 + innodb-lock: Disabled until merging with XtraDB 5.1.60 innodb_replace: Disabled until merging with XtraDB 5.1.60 diff --git a/mysql-test/suite/innodb_plugin/t/disabled.def b/mysql-test/suite/innodb_plugin/t/disabled.def index 72fec47a09a..a8f74a04a53 100644 --- a/mysql-test/suite/innodb_plugin/t/disabled.def +++ b/mysql-test/suite/innodb_plugin/t/disabled.def @@ -10,7 +10,10 @@ # ############################################################################## +innodb_bug13635833: Disabled until merging with XtraDB 5.1.63 + innodb_bug52745: Disabled as this has valgrind failures (also in MySQL 5.1.50) innodb-index: Disabled until merging with XtraDB 5.1.60 innodb-lock: Disabled until merging with XtraDB 5.1.60 innodb_replace: Disabled until merging with XtraDB 5.1.60 +innodb-blob: Disabled until merging with XtraDB 5.1.63 diff --git a/mysql-test/suite/innodb_plugin/t/innodb-blob.test b/mysql-test/suite/innodb_plugin/t/innodb-blob.test index eb2bc13d609..7d2968c720d 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb-blob.test +++ b/mysql-test/suite/innodb_plugin/t/innodb-blob.test @@ -3,7 +3,6 @@ # columns are stored off-page. --source include/have_innodb_plugin.inc -skip Not fixed in XtraDB yet; # DEBUG_SYNC must be compiled in. --source include/have_debug_sync.inc diff --git a/sql/slave.cc b/sql/slave.cc index e793061b844..41068ffa211 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1451,7 +1451,9 @@ Waiting for the slave SQL thread to free enough relay log space"); #endif if (rli->sql_force_rotate_relay) { + pthread_mutex_lock(&active_mi->data_lock); rotate_relay_log(rli->mi); + pthread_mutex_unlock(&active_mi->data_lock); rli->sql_force_rotate_relay= false; } @@ -4531,7 +4533,6 @@ int rotate_relay_log(Master_info* mi) DBUG_ENTER("rotate_relay_log"); Relay_log_info* rli= &mi->rli; int error= 0; - safe_mutex_assert_owner(&mi->data_lock); /* We need to test inited because otherwise, new_file() will attempt to lock @@ -4559,7 +4560,10 @@ int rotate_relay_log(Master_info* mi) output in SHOW SLAVE STATUS meanwhile. So we harvest now. If the log is closed, then this will just harvest the last writes, probably 0 as they probably have been harvested. + + Note that it needs to be protected by mi->data_lock. */ + safe_mutex_assert_owner(&mi->data_lock); rli->relay_log.harvest_bytes_written(&rli->log_space_total); end: DBUG_RETURN(error); From 02c4c5f735e65338f30f8fd08090a66a256b8220 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 18 May 2012 16:24:12 +0400 Subject: [PATCH 17/17] BUG#1000269: Wrong result (extra rows) with semijoin+materialization, IN subqueries, join_cache_level>0 - make make_cond_after_sjm() correctly handle OR clauses where one branch refers to the semi-join table while the other branch refers to the non-semijoin table. --- mysql-test/r/subselect_sj_mat.result | 13 +++++++++++++ mysql-test/t/subselect_sj_mat.test | 13 +++++++++++++ sql/sql_select.cc | 17 +++++++++++------ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index 1f96932309d..45a3e951523 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -2026,6 +2026,19 @@ y z DROP VIEW v2; DROP TABLE t1, t2; +# +# BUG#1000269: Wrong result (extra rows) with semijoin+materialization, IN subqueries, join_cache_level>0 +# +CREATE TABLE t1 (a1 VARCHAR(1), a2 VARCHAR(1)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('b','b'),('e','e'); +CREATE TABLE t2 (b1 VARCHAR(1), b2 VARCHAR(1), KEY(b1)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('v','v'),('s','s'),('l','l'), ('y','y'),('c','c'),('i','i'); +SELECT * FROM t1, t2 WHERE b1 IN ( SELECT b2 FROM t2 WHERE b1 > 'o' ) AND ( b1 < 'l' OR a1 IN ('b','c') ); +a1 a2 b1 b2 +b b v v +b b s s +b b y y +DROP TABLE t1,t2; # This must be at the end: set optimizer_switch=@subselect_sj_mat_tmp; set join_cache_level=@save_join_cache_level; diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index a077e9b5af5..4c40b2b5487 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -1664,6 +1664,19 @@ EXECUTE ps; DROP VIEW v2; DROP TABLE t1, t2; +--echo # +--echo # BUG#1000269: Wrong result (extra rows) with semijoin+materialization, IN subqueries, join_cache_level>0 +--echo # +CREATE TABLE t1 (a1 VARCHAR(1), a2 VARCHAR(1)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('b','b'),('e','e'); + +CREATE TABLE t2 (b1 VARCHAR(1), b2 VARCHAR(1), KEY(b1)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('v','v'),('s','s'),('l','l'), ('y','y'),('c','c'),('i','i'); + +SELECT * FROM t1, t2 WHERE b1 IN ( SELECT b2 FROM t2 WHERE b1 > 'o' ) AND ( b1 < 'l' OR a1 IN ('b','c') ); + +DROP TABLE t1,t2; + --echo # This must be at the end: set optimizer_switch=@subselect_sj_mat_tmp; set join_cache_level=@save_join_cache_level; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 50d1ffbb19c..38c4726a0f8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -93,7 +93,8 @@ static store_key *get_store_key(THD *thd, uint maybe_null); static bool make_outerjoin_info(JOIN *join); static Item* -make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, table_map sjm_tables); +make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, + table_map sjm_tables, bool inside_or_clause); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); static void revise_cache_usage(JOIN_TAB *join_tab); static bool make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after); @@ -8423,7 +8424,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (tab->bush_children) { // Reached the materialization tab - tmp= make_cond_after_sjm(cond, cond, save_used_tables, used_tables); + tmp= make_cond_after_sjm(cond, cond, save_used_tables, used_tables, + /*inside_or_clause=*/FALSE); used_tables= save_used_tables | used_tables; save_used_tables= 0; } @@ -17458,13 +17460,14 @@ make_cond_for_table_from_pred(THD *thd, Item *root_cond, Item *cond, */ static COND * make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, - table_map sjm_tables) + table_map sjm_tables, bool inside_or_clause) { /* We assume that conditions that refer to only join prefix tables or sjm_tables have already been checked. */ - if ((!(cond->used_tables() & ~tables) || + if (!inside_or_clause && + (!(cond->used_tables() & ~tables) || !(cond->used_tables() & ~sjm_tables))) return (COND*) 0; // Already checked @@ -17481,7 +17484,8 @@ make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, Item *item; while ((item=li++)) { - Item *fix=make_cond_after_sjm(root_cond, item, tables, sjm_tables); + Item *fix=make_cond_after_sjm(root_cond, item, tables, sjm_tables, + inside_or_clause); if (fix) new_cond->argument_list()->push_back(fix); } @@ -17511,7 +17515,8 @@ make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, Item *item; while ((item=li++)) { - Item *fix= make_cond_after_sjm(root_cond, item, tables, 0L); + Item *fix= make_cond_after_sjm(root_cond, item, tables, sjm_tables, + /*inside_or_clause= */TRUE); if (!fix) return (COND*) 0; // Always true new_cond->argument_list()->push_back(fix);