From 950abd526837b8772044d521387fa6d410de5706 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 May 2012 08:48:10 +0300 Subject: [PATCH 1/7] Fix of LP bug#992380 + revise fix_fields about missing with_subselect collection The problem is that some fix_fields do not call Item_func::fix_fields and do not collect with subselect_information. --- mysql-test/r/func_in.result | 9 +++++++++ mysql-test/t/func_in.test | 11 +++++++++++ sql/item_cmpfunc.cc | 3 +++ sql/item_func.cc | 1 + sql/item_row.cc | 1 + sql/item_sum.cc | 3 +++ 6 files changed, 28 insertions(+) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 7f0e607e789..e45c775b377 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -787,3 +787,12 @@ DROP TABLE t1; # End of test BUG#13012483 # End of 5.1 tests +# +# LP bug#992380 Crash when creating PS for a query with +# subquery in WHERE (see also mysql bug#13012483) +# +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; +1 +DROP TABLE t1; diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index dd4194e2a4e..9e054da3fe2 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -576,3 +576,14 @@ DROP TABLE t1; --echo # --echo End of 5.1 tests + +--echo # +--echo # LP bug#992380 Crash when creating PS for a query with +--echo # subquery in WHERE (see also mysql bug#13012483) +--echo # +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; + +DROP TABLE t1; + diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ea216944dbb..dda9ab418a4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1791,6 +1791,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) } if (args[1]->maybe_null) maybe_null=1; + with_subselect= 1; with_sum_func= with_sum_func || args[1]->with_sum_func; used_tables_cache|= args[1]->used_tables(); not_null_tables_cache|= args[1]->not_null_tables(); @@ -4907,6 +4908,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1)) return TRUE; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; + with_subselect|= args[0]->with_subselect | args[1]->with_subselect; max_length= 1; decimals= 0; @@ -5597,6 +5599,7 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) used_tables_cache|= item->used_tables(); tmp_table_map= item->not_null_tables(); not_null_tables_cache|= tmp_table_map; + DBUG_ASSERT(!item->with_sum_func && !item->with_subselect); if (item->maybe_null) maybe_null=1; } diff --git a/sql/item_func.cc b/sql/item_func.cc index ed771b60769..8028ae53eaf 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2918,6 +2918,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, if (item->maybe_null) func->maybe_null=1; func->with_sum_func= func->with_sum_func || item->with_sum_func; + func->with_subselect|= item->with_subselect; used_tables_cache|=item->used_tables(); const_item_cache&=item->const_item(); f_args.arg_type[i]=item->result_type(); diff --git a/sql/item_row.cc b/sql/item_row.cc index 4040dbff7c6..5296f866248 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -88,6 +88,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref) } maybe_null|= item->maybe_null; with_sum_func= with_sum_func || item->with_sum_func; + with_subselect|= item->with_subselect; } fixed= 1; return FALSE; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index ac6ddc0fd54..61a780b6222 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -574,6 +574,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) return TRUE; set_if_bigger(decimals, args[i]->decimals); + with_subselect|= args[i]->with_subselect; } result_field=0; max_length=float_length(decimals); @@ -604,6 +605,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) (item= args[0])->check_cols(1)) return TRUE; decimals=item->decimals; + with_subselect= args[0]->with_subselect; switch (hybrid_type= item->result_type()) { case INT_RESULT: @@ -3216,6 +3218,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) args[i]->fix_fields(thd, args + i)) || args[i]->check_cols(1)) return TRUE; + with_subselect|= args[i]->with_subselect; } if (agg_item_charsets(collation, func_name(), From d56f5dae1ef60468dd7497453bcdca9b653922ca Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 May 2012 18:18:08 +0300 Subject: [PATCH 2/7] Fix bug lp:1001506 This is a backport of the (unchaged) fix for MySQL bug #11764372, 57197. Analysis: When the outer query finishes its main execution and computes GROUP BY, it needs to construct a new temporary table (and a corresponding JOIN) to execute the last DISTINCT operation. At this point JOIN::exec calls JOIN::join_free, which calls JOIN::cleanup -> TMP_TABLE_PARAM::cleanup for both the outer and the inner JOINs. The call to the inner TMP_TABLE_PARAM::cleanup sets copy_field = NULL, but not copy_field_end. The final execution phase that computes the DISTINCT invokes: evaluate_join_record -> end_write -> copy_funcs The last function copies the results of all functions into the temp table. copy_funcs walks over all functions in join->tmp_table_param.items_to_copy. In this case items_to_copy contains both assignments to user variables. The process of copying user variables invokes Item_func_set_user_var::check which in turn re-evaluates the arguments of the user variable assignment. This in turn triggers re-evaluation of the subquery, and ultimately copy_field. However, the previous call to TMP_TABLE_PARAM::cleanup for the subquery already set copy_field to NULL but not its copy_field_end. This results in a null pointer access, and a crash. Fix: Set copy_field_end and save_copy_field_end to null when deleting copy fields in TMP_TABLE_PARAM::cleanup(). --- mysql-test/r/user_var.result | 7 +++++++ mysql-test/t/user_var.test | 11 +++++++++++ sql/sql_class.h | 3 ++- sql/sql_select.cc | 2 ++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 374520ff610..19cb54ad2bc 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -456,4 +456,11 @@ SELECT (@v:=a) <> (@v:=1) FROM t1; (@v:=a) <> (@v:=1) 1 DROP TABLE t1; +CREATE TABLE t1(a int); +INSERT INTO t1 VALUES (1), (2); +SELECT DISTINCT @a:=MIN(t1.a) FROM t1, t1 AS t2 +GROUP BY @b:=(SELECT COUNT(*) > t2.a); +@a:=MIN(t1.a) +1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index efaf8afd91e..2782f61994d 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -365,4 +365,15 @@ SELECT (@v:=a) <> (@v:=1) FROM t1; DROP TABLE t1; +# +# LP BUG#1001506 Crash on a query with GROUP BY and user variables +# MySQL Bug #11764372 57197: EVEN MORE USER VARIABLE CRASHING FUN +# + +CREATE TABLE t1(a int); +INSERT INTO t1 VALUES (1), (2); +SELECT DISTINCT @a:=MIN(t1.a) FROM t1, t1 AS t2 +GROUP BY @b:=(SELECT COUNT(*) > t2.a); +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/sql_class.h b/sql/sql_class.h index 4bf1bc3964c..14f4f022de3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2880,7 +2880,8 @@ public: if (copy_field) /* Fix for Intel compiler */ { delete [] copy_field; - save_copy_field= copy_field= 0; + save_copy_field= copy_field= NULL; + save_copy_field_end= copy_field_end= NULL; } } }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 150f19f96a6..46b4511e24f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16072,6 +16072,8 @@ copy_fields(TMP_TABLE_PARAM *param) Copy_field *ptr=param->copy_field; Copy_field *end=param->copy_field_end; + DBUG_ASSERT((ptr != NULL && end >= ptr) || (ptr == NULL && end == NULL)); + for (; ptr != end; ptr++) (*ptr->do_copy)(ptr); From f45784c8503d0bbe77f3aec351fc87ff536b19be Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 May 2012 10:29:53 +0300 Subject: [PATCH 3/7] Fix of LP bug#992380 + revise fix_fields about missing with_subselect collection The problem is that some fix_fields do not call Item_func::fix_fields and do not collect with subselect_information. --- mysql-test/r/func_test.result | 41 +++++++++++++++ mysql-test/r/negation_elimination.result | 4 +- mysql-test/r/ps.result | 56 ++++++++++++++++++++ mysql-test/t/func_test.test | 20 ++++++++ mysql-test/t/ps.test | 65 ++++++++++++++++++++++++ sql/item_cmpfunc.cc | 38 ++++++++++++++ sql/item_cmpfunc.h | 3 ++ 7 files changed, 225 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index a97e6869d09..e3c77a40a77 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -279,3 +279,44 @@ NULL SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL; GREATEST(1.5E+2,1.3E+2,NULL) NULL +create table t1 (a int); +insert into t1 values (1), (100), (0), (NULL); +select not a from t1; +not a +0 +0 +1 +NULL +explain extended select not a from t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 +Warnings: +Note 1003 select (`test`.`t1`.`a` = 0) AS `not a` from `test`.`t1` +select * from t1 where not a; +a +0 +explain extended select * from t1 where not a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = 0) +select not (a+0) from t1; +not (a+0) +0 +0 +1 +NULL +explain extended select not (a+0) from t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 +Warnings: +Note 1003 select (not((`test`.`t1`.`a` + 0))) AS `not (a+0)` from `test`.`t1` +select * from t1 where not (a+0); +a +0 +explain extended select * from t1 where not (a+0); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (not((`test`.`t1`.`a` + 0))) +drop table t1; diff --git a/mysql-test/r/negation_elimination.result b/mysql-test/r/negation_elimination.result index af48002ed0f..35510242bcb 100644 --- a/mysql-test/r/negation_elimination.result +++ b/mysql-test/r/negation_elimination.result @@ -321,7 +321,7 @@ select * from t1 where not(NULL or a); a explain select * from t1 where not(NULL and a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL a 5 NULL 21 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index select * from t1 where not(NULL and a); a 0 @@ -387,5 +387,5 @@ explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like " id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 5 NULL 4 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or `test`.`t1`.`a`) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0) +Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or (`test`.`t1`.`a` <> 0)) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0) drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index b3f4ad017d3..72558324b50 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -3040,3 +3040,59 @@ id select_type table type possible_keys key key_len ref rows Extra DEALLOCATE PREPARE stmt; DROP TABLE t1; End of 5.1 tests. +# +# LP bug#1001500 Crash on the second execution of the PS for +# a query with degenerated conjunctive condition +# (see also mysql bug#12582849) +# +CREATE TABLE t1 ( +pk INTEGER AUTO_INCREMENT, +col_int_nokey INTEGER, +col_int_key INTEGER, +col_varchar_key VARCHAR(1), +col_varchar_nokey VARCHAR(1), +PRIMARY KEY (pk), +KEY (col_int_key), +KEY (col_varchar_key, col_int_key) +); +INSERT INTO t1 ( +col_int_key, col_int_nokey, +col_varchar_key, col_varchar_nokey +) VALUES +(4, 2, 'v', 'v'), +(62, 150, 'v', 'v'); +CREATE TABLE t2 ( +pk INTEGER AUTO_INCREMENT, +col_int_nokey INTEGER, +col_int_key INTEGER, +col_varchar_key VARCHAR(1), +col_varchar_nokey VARCHAR(1), +PRIMARY KEY (pk), +KEY (col_int_key), +KEY (col_varchar_key, col_int_key) +); +INSERT INTO t2 ( +col_int_key, col_int_nokey, +col_varchar_key, col_varchar_nokey +) VALUES +(8, NULL, 'x', 'x'), +(7, 8, 'd', 'd'); +PREPARE stmt FROM ' +SELECT + ( SELECT MAX( SQ1_alias2 .col_int_nokey ) AS SQ1_field1 + FROM ( t2 AS SQ1_alias1 RIGHT JOIN t1 AS SQ1_alias2 + ON ( SQ1_alias2.col_varchar_key = SQ1_alias1.col_varchar_nokey ) + ) + WHERE SQ1_alias2.pk < alias1.col_int_nokey OR alias1.pk + ) AS field1 +FROM ( t1 AS alias1 JOIN t2 AS alias2 ON alias2.pk ) +GROUP BY field1 +'; +EXECUTE stmt; +field1 +150 +EXECUTE stmt; +field1 +150 +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 77bf3be5e72..4cba29986a1 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -160,3 +160,23 @@ SELECT LEAST(1.1,1.2,NULL,1.0) FROM DUAL; SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL; # End of 4.1 tests + +# +# test of replacing NOT +# +create table t1 (a int); +insert into t1 values (1), (100), (0), (NULL); + +select not a from t1; +explain extended select not a from t1; + +select * from t1 where not a; +explain extended select * from t1 where not a; + +select not (a+0) from t1; +explain extended select not (a+0) from t1; + +select * from t1 where not (a+0); +explain extended select * from t1 where not (a+0); + +drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 9b3f3e750e1..e3f2a5c87d1 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3102,3 +3102,68 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1; --echo End of 5.1 tests. + +--echo # +--echo # LP bug#1001500 Crash on the second execution of the PS for +--echo # a query with degenerated conjunctive condition +--echo # (see also mysql bug#12582849) +--echo # + +CREATE TABLE t1 ( + pk INTEGER AUTO_INCREMENT, + col_int_nokey INTEGER, + col_int_key INTEGER, + + col_varchar_key VARCHAR(1), + col_varchar_nokey VARCHAR(1), + + PRIMARY KEY (pk), + KEY (col_int_key), + KEY (col_varchar_key, col_int_key) +); + +INSERT INTO t1 ( + col_int_key, col_int_nokey, + col_varchar_key, col_varchar_nokey +) VALUES +(4, 2, 'v', 'v'), +(62, 150, 'v', 'v'); + +CREATE TABLE t2 ( + pk INTEGER AUTO_INCREMENT, + col_int_nokey INTEGER, + col_int_key INTEGER, + + col_varchar_key VARCHAR(1), + col_varchar_nokey VARCHAR(1), + + PRIMARY KEY (pk), + KEY (col_int_key), + KEY (col_varchar_key, col_int_key) +); + +INSERT INTO t2 ( + col_int_key, col_int_nokey, + col_varchar_key, col_varchar_nokey +) VALUES +(8, NULL, 'x', 'x'), +(7, 8, 'd', 'd'); + +PREPARE stmt FROM ' +SELECT + ( SELECT MAX( SQ1_alias2 .col_int_nokey ) AS SQ1_field1 + FROM ( t2 AS SQ1_alias1 RIGHT JOIN t1 AS SQ1_alias2 + ON ( SQ1_alias2.col_varchar_key = SQ1_alias1.col_varchar_nokey ) + ) + WHERE SQ1_alias2.pk < alias1.col_int_nokey OR alias1.pk + ) AS field1 +FROM ( t1 AS alias1 JOIN t2 AS alias2 ON alias2.pk ) +GROUP BY field1 +'; + +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + +DROP TABLE t1, t2; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dda9ab418a4..61554bdf420 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4271,6 +4271,22 @@ Item_cond::fix_fields(THD *thd, Item **ref) if (abort_on_null) item->top_level_item(); + /* + replace degraded condition: + was: + become: = 1 + */ + if (item->type() == FIELD_ITEM) + { + Query_arena backup, *arena; + Item *new_item; + arena= thd->activate_stmt_arena_if_needed(&backup); + if ((new_item= new Item_func_ne(item, new Item_int(0, 1)))) + li.replace(item= new_item); + if (arena) + thd->restore_active_arena(arena, &backup); + } + // item can be substituted in fix_fields if ((!item->fixed && item->fix_fields(thd, li.ref())) || @@ -5283,6 +5299,28 @@ Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */ } +bool Item_func_not::fix_fields(THD *thd, Item **ref) +{ + if (args[0]->type() == FIELD_ITEM) + { + /* replace "NOT " with " == 0" */ + Query_arena backup, *arena; + Item *new_item; + bool rc= TRUE; + arena= thd->activate_stmt_arena_if_needed(&backup); + if ((new_item= new Item_func_eq(args[0], new Item_int(0, 1)))) + { + new_item->name= name; + rc= (*ref= new_item)->fix_fields(thd, ref); + } + if (arena) + thd->restore_active_arena(arena, &backup); + return rc; + } + return Item_func::fix_fields(thd, ref); +} + + Item *Item_bool_rowready_func2::neg_transformer(THD *thd) { Item *item= negated_item(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 25b636397a8..7239079c56f 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -413,6 +413,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); + bool fix_fields(THD *, Item **); virtual void print(String *str, enum_query_type query_type); }; @@ -479,6 +480,8 @@ public: longlong val_int(); enum Functype functype() const { return NOT_ALL_FUNC; } const char *func_name() const { return ""; } + bool fix_fields(THD *thd, Item **ref) + {return Item_func::fix_fields(thd, ref);} virtual void print(String *str, enum_query_type query_type); void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; }; void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; }; From 34f2f8ea41726d98e50752ff3453ebde70912c35 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 1 Jun 2012 17:53:59 +0200 Subject: [PATCH 4/7] MDEV-256 lp:995501 - mysqltest attempts to parse Perl code inside a block with false condition, gets confused and throws wrong errors --- client/mysqltest.cc | 11 +++++++---- mysql-test/r/mysqltest_256.result | 1 + mysql-test/t/mysqltest_256.test | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 mysql-test/r/mysqltest_256.result create mode 100644 mysql-test/t/mysqltest_256.test diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 68f076818dd..8f955ff586b 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -8259,8 +8259,12 @@ int main(int argc, char **argv) command->abort_on_error= (command->expected_errors.count == 0 && abort_on_error); - /* delimiter needs to be executed so we can continue to parse */ - ok_to_do= cur_block->ok || command->type == Q_DELIMITER; + /* + some commmands need to be executed or at least parsed unconditionally, + because they change the grammar. + */ + ok_to_do= cur_block->ok || command->type == Q_DELIMITER + || command->type == Q_PERL; /* Some commands need to be "done" the first time if they may get re-iterated over in a true context. This can only happen if there's @@ -8271,8 +8275,7 @@ int main(int argc, char **argv) if (command->type == Q_SOURCE || command->type == Q_ERROR || command->type == Q_WRITE_FILE || - command->type == Q_APPEND_FILE || - command->type == Q_PERL) + command->type == Q_APPEND_FILE) { for (struct st_block *stb= cur_block-1; stb >= block_stack; stb--) { diff --git a/mysql-test/r/mysqltest_256.result b/mysql-test/r/mysqltest_256.result new file mode 100644 index 00000000000..043c7208382 --- /dev/null +++ b/mysql-test/r/mysqltest_256.result @@ -0,0 +1 @@ +# Done diff --git a/mysql-test/t/mysqltest_256.test b/mysql-test/t/mysqltest_256.test new file mode 100644 index 00000000000..fd9447cd2d8 --- /dev/null +++ b/mysql-test/t/mysqltest_256.test @@ -0,0 +1,17 @@ +# +# MDEV-256 lp:995501 - mysqltest attempts to parse Perl code inside a block +# with false condition, gets confused and throws wrong errors +# + +let $run = 0; +if ($run) +{ + --perl + foreach (1) + { + print "In perl\n"; + } + EOF + SELECT 1; +} +--echo # Done From 7b32d88c05756a37b15e7f11f4cd83fec25f42e2 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 11 Jun 2012 22:12:47 -0700 Subject: [PATCH 5/7] Fixed LP bug #1008293. One of the reported problems manifested itself in the scenario when one thread tried to to get statistics on a key cache while the second thread had not finished initialization of the key cache structure yet. The problem was resolved by forcing serialization of such operations on key caches. To serialize function calls to perform certain operations over a key cache a new mutex associated with the key cache now is used. It is stored in the field op_lock of the KEY_CACHE structure. It is locked when the operation is performed. Some of the serialized key cache operations utilize calls for other key cache operations. To avoid recursive locking of op_lock the new functions that perform the operations of key cache initialization, destruction and re-partitioning with an additional parameter were introduced. The parameter says whether the operation over op_lock are to be performed or are to be omitted. The old functions for the operations of key cache initialization, destruction,and re-partitioning now just call the corresponding new functions with the additional parameter set to true requesting to use op_lock while all other calls of these new function have this parameter set to false. Another problem reported in the bug entry concerned the operation of assigning an index to a key cache. This operation can be called while the key cache structures are not initialized yet. In this case any call of flush_key_blocks() should return without any actions. No test case is provided with this patch. --- include/keycache.h | 3 +- mysys/mf_keycache.c | 330 +++++++++++++++++++++++++++++++------------- 2 files changed, 238 insertions(+), 95 deletions(-) diff --git a/include/keycache.h b/include/keycache.h index 12338037ea1..c19fa5988f8 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -150,9 +150,10 @@ typedef struct st_key_cache ulong param_partitions; /* number of the key cache partitions */ my_bool key_cache_inited; /* <=> key cache has been created */ my_bool can_be_used; /* usage of cache for read/write is allowed */ - my_bool in_init; /* Set to 1 in MySQL during init/resize */ + my_bool in_init; /* set to 1 in MySQL during init/resize */ uint partitions; /* actual number of partitions */ size_t key_cache_mem_size; /* specified size of the cache memory */ + pthread_mutex_t op_lock; /* to serialize operations like 'resize' */ } KEY_CACHE; diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index e0d495ce8e0..dc2d7fdd127 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -5863,6 +5863,111 @@ static KEY_CACHE_FUNCS partitioned_key_cache_funcs = ******************************************************************************/ +static +int repartition_key_cache_internal(KEY_CACHE *keycache, + uint key_cache_block_size, size_t use_mem, + uint division_limit, uint age_threshold, + uint partitions, my_bool use_op_lock); + +/* + Initialize a key cache : internal + + SYNOPSIS + init_key_cache_internal() + keycache pointer to the key cache to be initialized + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for cache buffers/structures + division_limit division limit (may be zero) + age_threshold age threshold (may be zero) + partitions number of partitions in the key cache + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it + + DESCRIPTION + The function performs the actions required from init_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE than the function initializes keycache->op_lock if needed, + then locks it, and unlocks it before the return. Otherwise the actions + with the lock are omitted. + + RETURN VALUE + total number of blocks in key cache partitions, if successful, + <= 0 - otherwise. + + NOTES + if keycache->key_cache_inited != 0 we assume that the memory + for the control block of the key cache has been already allocated. +*/ + +static +int init_key_cache_internal(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint partitions, + my_bool use_op_lock) +{ + void *keycache_cb; + int blocks; + if (keycache->key_cache_inited) + { + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); + keycache_cb= keycache->keycache_cb; + } + else + { + if (partitions == 0) + { + if (!(keycache_cb= (void *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB), + MYF(0)))) + return 0; + ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0; + keycache->key_cache_type= SIMPLE_KEY_CACHE; + keycache->interface_funcs= &simple_key_cache_funcs; + } + else + { + if (!(keycache_cb= (void *) my_malloc(sizeof(PARTITIONED_KEY_CACHE_CB), + MYF(0)))) + return 0; + ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0; + keycache->key_cache_type= PARTITIONED_KEY_CACHE; + keycache->interface_funcs= &partitioned_key_cache_funcs; + } + /* + Initialize op_lock if it's not initialized before. + The mutex may have been initialized before if we are being called + from repartition_key_cache_internal(). + */ + if (use_op_lock) + pthread_mutex_init(&keycache->op_lock, MY_MUTEX_INIT_FAST); + keycache->keycache_cb= keycache_cb; + keycache->key_cache_inited= 1; + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); + } + + if (partitions != 0) + { + ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions= partitions; + } + keycache->can_be_used= 0; + blocks= keycache->interface_funcs->init(keycache_cb, key_cache_block_size, + use_mem, division_limit, + age_threshold); + keycache->partitions= partitions ? + ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions : + 0; + DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS); + keycache->key_cache_mem_size= + keycache->partitions ? + ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_mem_size : + ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_mem_size; + if (blocks > 0) + keycache->can_be_used= 1; + if (use_op_lock) + pthread_mutex_unlock(&keycache->op_lock); + return blocks; +} + /* Initialize a key cache @@ -5887,16 +5992,15 @@ static KEY_CACHE_FUNCS partitioned_key_cache_funcs = age_threshold determine the initial values of those characteristics of the key cache that are used for midpoint insertion strategy. The parameter use_mem specifies the total amount of memory to be allocated for the - key cache buffers and for all auxiliary structures. + key cache buffers and for all auxiliary structures. + The function calls init_key_cache_internal() to perform all these actions + with the last parameter set to TRUE. RETURN VALUE total number of blocks in key cache partitions, if successful, <= 0 - otherwise. NOTES - if keycache->key_cache_inited != 0 we assume that the memory - for the control block of the key cache has been already allocated. - It's assumed that no two threads call this function simultaneously referring to the same key cache handle. */ @@ -5905,53 +6009,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, size_t use_mem, uint division_limit, uint age_threshold, uint partitions) { - void *keycache_cb; - int blocks; - if (keycache->key_cache_inited) - keycache_cb= keycache->keycache_cb; - else - { - if (partitions == 0) - { - if (!(keycache_cb= (void *) my_malloc(sizeof(SIMPLE_KEY_CACHE_CB), - MYF(0)))) - return 0; - ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0; - keycache->key_cache_type= SIMPLE_KEY_CACHE; - keycache->interface_funcs= &simple_key_cache_funcs; - } - else - { - if (!(keycache_cb= (void *) my_malloc(sizeof(PARTITIONED_KEY_CACHE_CB), - MYF(0)))) - return 0; - ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_inited= 0; - keycache->key_cache_type= PARTITIONED_KEY_CACHE; - keycache->interface_funcs= &partitioned_key_cache_funcs; - } - keycache->keycache_cb= keycache_cb; - keycache->key_cache_inited= 1; - } - - if (partitions != 0) - { - ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions= partitions; - } - keycache->can_be_used= 0; - blocks= keycache->interface_funcs->init(keycache_cb, key_cache_block_size, - use_mem, division_limit, - age_threshold); - keycache->partitions= partitions ? - ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->partitions : - 0; - DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS); - keycache->key_cache_mem_size= - keycache->partitions ? - ((PARTITIONED_KEY_CACHE_CB *) keycache_cb)->key_cache_mem_size : - ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_mem_size; - if (blocks > 0) - keycache->can_be_used= 1; - return blocks; + return init_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, partitions, 1); } @@ -5995,11 +6054,13 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, int blocks= -1; if (keycache->key_cache_inited) { + pthread_mutex_lock(&keycache->op_lock); if ((uint) keycache->param_partitions != keycache->partitions && use_mem) - blocks= repartition_key_cache(keycache, - key_cache_block_size, use_mem, - division_limit, age_threshold, - (uint) keycache->param_partitions); + blocks= repartition_key_cache_internal(keycache, + key_cache_block_size, use_mem, + division_limit, age_threshold, + (uint) keycache->param_partitions, + 0); else { blocks= keycache->interface_funcs->resize(keycache->keycache_cb, @@ -6018,6 +6079,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, ((SIMPLE_KEY_CACHE_CB *)(keycache->keycache_cb))->key_cache_mem_size; keycache->can_be_used= (blocks >= 0); + pthread_mutex_unlock(&keycache->op_lock); } return blocks; } @@ -6051,10 +6113,57 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, { if (keycache->key_cache_inited) { - + pthread_mutex_lock(&keycache->op_lock); keycache->interface_funcs->change_param(keycache->keycache_cb, division_limit, - age_threshold); + age_threshold); + pthread_mutex_unlock(&keycache->op_lock); + } +} + + +/* + Destroy a key cache : internal + + SYNOPSIS + end_key_cache_internal() + keycache pointer to the key cache to be destroyed + cleanup <=> complete free + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it + + DESCRIPTION + The function performs the actions required from end_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE than the function destroys keycache->op_lock if cleanup is true. + Otherwise the action with the lock is omitted. + + RETURN VALUE + none +*/ + +static +void end_key_cache_internal(KEY_CACHE *keycache, my_bool cleanup, + my_bool use_op_lock) +{ + if (keycache->key_cache_inited) + { + keycache->interface_funcs->end(keycache->keycache_cb, cleanup); + if (cleanup) + { + if (keycache->keycache_cb) + { + my_free((uchar *) keycache->keycache_cb, MYF(0)); + keycache->keycache_cb= 0; + } + /* + We do not destroy op_lock if we are going to reuse the same key cache. + This happens if we are called from repartition_key_cache_internal(). + */ + if (use_op_lock) + pthread_mutex_destroy(&keycache->op_lock); + keycache->key_cache_inited= 0; + } + keycache->can_be_used= 0; } } @@ -6072,6 +6181,8 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, auxiliary structures used by the key cache keycache. If the value of the parameter cleanup is TRUE then all resources used by the key cache are to be freed. + The function calls end_key_cache_internal() to perform all these actions + with the last parameter set to TRUE. RETURN VALUE none @@ -6079,20 +6190,7 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) { - if (keycache->key_cache_inited) - { - keycache->interface_funcs->end(keycache->keycache_cb, cleanup); - if (cleanup) - { - if (keycache->keycache_cb) - { - my_free((uchar *) keycache->keycache_cb, MYF(0)); - keycache->keycache_cb= 0; - } - keycache->key_cache_inited= 0; - } - keycache->can_be_used= 0; - } + end_key_cache_internal(keycache, cleanup, 1); } @@ -6140,7 +6238,7 @@ uchar *key_cache_read(KEY_CACHE *keycache, uchar *buff, uint length, uint block_length, int return_buffer) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->read(keycache->keycache_cb, file, filepos, level, buff, length, @@ -6192,7 +6290,7 @@ int key_cache_insert(KEY_CACHE *keycache, File file, my_off_t filepos, int level, uchar *buff, uint length) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->insert(keycache->keycache_cb, file, filepos, level, buff, length); @@ -6247,7 +6345,7 @@ int key_cache_write(KEY_CACHE *keycache, uchar *buff, uint length, uint block_length, int force_write) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->write(keycache->keycache_cb, file, file_extra, filepos, level, @@ -6299,7 +6397,7 @@ int flush_key_blocks(KEY_CACHE *keycache, int file, void *file_extra, enum flush_type type) { - if (keycache->key_cache_inited) + if (keycache->can_be_used) return keycache->interface_funcs->flush(keycache->keycache_cb, file, file_extra, type); return 0; @@ -6330,13 +6428,15 @@ int flush_key_blocks(KEY_CACHE *keycache, int reset_key_cache_counters(const char *name __attribute__((unused)), KEY_CACHE *keycache) { + int rc= 0; if (keycache->key_cache_inited) { - - return keycache->interface_funcs->reset_counters(name, - keycache->keycache_cb); + pthread_mutex_lock(&keycache->op_lock); + rc= keycache->interface_funcs->reset_counters(name, + keycache->keycache_cb); + pthread_mutex_unlock(&keycache->op_lock); } - return 0; + return rc; } @@ -6366,11 +6466,63 @@ void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no, { if (keycache->key_cache_inited) { + pthread_mutex_lock(&keycache->op_lock); keycache->interface_funcs->get_stats(keycache->keycache_cb, partition_no, key_cache_stats); + pthread_mutex_unlock(&keycache->op_lock); } } + +/* + Repartition a key cache : internal + + SYNOPSIS + repartition_key_cache_internal() + keycache pointer to the key cache to be repartitioned + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for the new key cache + division_limit new division limit (if not zero) + age_threshold new age threshold (if not zero) + partitions new number of partitions in the key cache + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it + + DESCRIPTION + The function performs the actions required from repartition_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE then the function locks keycache->op_lock at start and + unlocks it before the return. Otherwise the actions with the lock + are omitted. + + RETURN VALUE + number of blocks in the key cache, if successful, + 0 - otherwise. +*/ + +static +int repartition_key_cache_internal(KEY_CACHE *keycache, + uint key_cache_block_size, size_t use_mem, + uint division_limit, uint age_threshold, + uint partitions, my_bool use_op_lock) +{ + uint blocks= -1; + if (keycache->key_cache_inited) + { + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); + keycache->interface_funcs->resize(keycache->keycache_cb, + key_cache_block_size, 0, + division_limit, age_threshold); + end_key_cache_internal(keycache, 1, 0); + blocks= init_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, partitions, + 0); + if (use_op_lock) + pthread_mutex_unlock(&keycache->op_lock); + } + return blocks; +} + /* Repartition a key cache @@ -6394,16 +6546,14 @@ void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no, that are used for midpoint insertion strategy. The parameter use_mem specifies the total amount of memory to be allocated for the new key cache buffers and for all auxiliary structures. + The function calls repartition_key_cache_internal() to perform all these + actions with the last parameter set to TRUE. RETURN VALUE number of blocks in the key cache, if successful, 0 - otherwise. NOTES - The function does not block the calls and executions of other functions - from the key cache interface. However it assumes that the calls of - resize_key_cache itself are serialized. - Currently the function is called when the value of the variable key_cache_partitions is being reset for the key cache keycache. */ @@ -6412,16 +6562,8 @@ int repartition_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, size_t use_mem, uint division_limit, uint age_threshold, uint partitions) { - uint blocks= -1; - if (keycache->key_cache_inited) - { - keycache->interface_funcs->resize(keycache->keycache_cb, - key_cache_block_size, 0, - division_limit, age_threshold); - end_key_cache(keycache, 1); - blocks= init_key_cache(keycache, key_cache_block_size, use_mem, - division_limit, age_threshold, partitions); - } - return blocks; + return repartition_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, + partitions, 1); } From 64aa1fcb1354ffa24999a1512258c897116b0928 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 12 Jun 2012 10:06:26 -0700 Subject: [PATCH 6/7] Adjusted results in pbxt.negation_elimination after the fix for lp bug 992380. --- mysql-test/suite/pbxt/r/negation_elimination.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/pbxt/r/negation_elimination.result b/mysql-test/suite/pbxt/r/negation_elimination.result index 80225cd6044..3b968e396c5 100644 --- a/mysql-test/suite/pbxt/r/negation_elimination.result +++ b/mysql-test/suite/pbxt/r/negation_elimination.result @@ -321,7 +321,7 @@ select * from t1 where not(NULL or a); a explain select * from t1 where not(NULL and a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL a 5 NULL 21 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index select * from t1 where not(NULL and a); a 0 @@ -390,5 +390,5 @@ explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like " id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 index a a 5 NULL 5 40.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or `test`.`t1`.`a`) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0) +Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or (`test`.`t1`.`a` <> 0)) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0) drop table t1; From 584d923c3292395a2e8288adcf4795992789f27c Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Wed, 20 Jun 2012 13:41:31 +0400 Subject: [PATCH 7/7] Post-merge fixes: - put back the result encoding in func_in.result (messed up by kdiff3) - update .result for other tests (checked) --- mysql-test/r/derived_view.result | 4 ++-- mysql-test/r/func_in.result | 5 +++-- mysql-test/r/negation_elimination.result | 2 +- mysql-test/r/view.result | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 9e6d6db9314..a4f7a71dcb5 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -1672,7 +1672,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) Warnings: -Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on(multiple equal(NULL, `test`.`t2`.`a`)) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and `test`.`t2`.`b`) +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on(multiple equal(NULL, `test`.`t2`.`a`)) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t2`.`b` <> 0)) SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b AND t.c = t1.a; @@ -1703,7 +1703,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) 1 SIMPLE t3 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on((`test`.`t3`.`b` = `test`.`t2`.`a`)) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and `test`.`t2`.`b`) +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on((`test`.`t3`.`b` = `test`.`t2`.`a`)) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t2`.`b` <> 0)) SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b AND t.c = t1.a; diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index f6d50764cc9..d25dcd40117 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -150,8 +150,8 @@ Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` A drop table t1; set names utf8; create table t1 (a char(10) character set utf8 not null); -insert into t1 values ('bbbb'),(_koi8r'ÃÃÃÃ'),(_latin1'ÄÄÄÄ'); -select a from t1 where a in ('bbbb',_koi8r'ÃÃÃÃ',_latin1'ÄÄÄÄ') order by a; +insert into t1 values ('bbbb'),(_koi8r'ÃÃÃÃ'),(_latin1'ÄÄÄÄ'); +select a from t1 where a in ('bbbb',_koi8r'ÃÃÃÃ',_latin1'ÄÄÄÄ') order by a; a ÄÄÄÄ bbbb @@ -811,3 +811,4 @@ a b select * from t1 where IF(1,a,a)='2.1'; a b drop table t1; +# End of 5.3 tests diff --git a/mysql-test/r/negation_elimination.result b/mysql-test/r/negation_elimination.result index d32f8a0c3f9..aea6518b676 100644 --- a/mysql-test/r/negation_elimination.result +++ b/mysql-test/r/negation_elimination.result @@ -321,7 +321,7 @@ select * from t1 where not(NULL or a); a explain select * from t1 where not(NULL and a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using index select * from t1 where not(NULL and a); a 0 diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index a1b36c323c7..86ebc9a8ee7 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4207,13 +4207,13 @@ MM ZZ ZZ Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'VV' +Warning 1292 Truncated incorrect DOUBLE value: 'VV' EXPLAIN EXTENDED SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'VV' +Warning 1292 Truncated incorrect DOUBLE value: 'VV' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 'JJ') DROP VIEW v1; DROP TABLE t1;