diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 43d479a1043..772f1d15b92 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] -post_commit_to = "commits@lists.mysql.com" -post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.5" +post_commit_to = "MYSQL_COMMITS_SECURITY_WW@ORACLE.COM" +post_push_to = "MYSQL_COMMITS_SECURITY_WW@ORACLE.COM" +tree_name = "mysql-5.5-security" diff --git a/VERSION b/VERSION index d05c93f6e73..508f021f35d 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=21 +MYSQL_VERSION_PATCH=20 MYSQL_VERSION_EXTRA= diff --git a/dbug/dbug.c b/dbug/dbug.c index 8b3927d2427..cac544b6cd3 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -1863,6 +1863,8 @@ static void DBUGOpenFile(CODE_STATE *cs, name=cs->stack->name; if (strcmp(name, "-") == 0) { + if (!is_shared(cs->stack, out_file)) + DBUGCloseFile(cs, cs->stack->out_file); cs->stack->out_file= stdout; cs->stack->flags |= FLUSH_ON_WRITE; cs->stack->name[0]=0; @@ -1885,6 +1887,8 @@ static void DBUGOpenFile(CODE_STATE *cs, } else { + if (!is_shared(cs->stack, out_file)) + DBUGCloseFile(cs, cs->stack->out_file); cs->stack->out_file= fp; } } diff --git a/libmysql/get_password.c b/libmysql/get_password.c index c3428dd2838..a10d112ccd0 100644 --- a/libmysql/get_password.c +++ b/libmysql/get_password.c @@ -71,9 +71,9 @@ void get_tty_password_buff(const char *opt_message, char *to, size_t length) _cputs(opt_message ? opt_message : "Enter password: "); for (;;) { - char tmp; + int tmp; tmp=_getch(); - if (tmp == '\b' || (int) tmp == 127) + if (tmp == '\b' || tmp == 127) { if (pos != to) { @@ -82,15 +82,13 @@ void get_tty_password_buff(const char *opt_message, char *to, size_t length) continue; } } - if (tmp == '\n' || tmp == '\r' || tmp == 3) + if (tmp == -1 || tmp == '\n' || tmp == '\r' || tmp == 3) break; if (iscntrl(tmp) || pos == end) continue; _cputs("*"); - *(pos++) = tmp; + *(pos++) = (char)tmp; } - while (pos != to && isspace(pos[-1]) == ' ') - pos--; /* Allow dummy space at end */ *pos=0; _cputs("\n"); } @@ -137,8 +135,6 @@ static void get_password(char *to,uint length,int fd, my_bool echo) } *(pos++) = tmp; } - while (pos != to && isspace(pos[-1]) == ' ') - pos--; /* Allow dummy space at end */ *pos=0; return; } diff --git a/mysql-test/include/wait_until_disconnected.inc b/mysql-test/include/wait_until_disconnected.inc index c274fbbe089..71361682442 100644 --- a/mysql-test/include/wait_until_disconnected.inc +++ b/mysql-test/include/wait_until_disconnected.inc @@ -12,7 +12,7 @@ while (!$mysql_errno) # Strangely enough, the server might return "Too many connections" # while being shutdown, thus 1040 is an "allowed" error. # See BUG#36228. - --error 0,1040,1053,2002,2003,2006,2013 + --error 0,1040,1053,2002,2003,2005,2006,2013 show status; dec $counter; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index aa7da22d20c..76ea349cd83 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -584,6 +584,7 @@ sub main { } mtr_report_test($tinfo); push @$completed, $tinfo; + ++$num_tests } mtr_print_line(); @@ -599,7 +600,8 @@ sub main { if ( @$completed != $num_tests) { - mtr_error("Not all tests completed"); + mtr_error("Not all tests completed (only ". scalar(@$completed) . + " of $num_tests)"); } remove_vardir_subs() if $opt_clean_vardir; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index b63131fcca6..fbc8e3d28e2 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1562,6 +1562,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 7 drop table t1,t2; CREATE TABLE t1(c1 VARCHAR(33), KEY USING BTREE (c1)); diff --git a/mysql-test/r/derived_opt.result b/mysql-test/r/derived_opt.result index 721d4277775..c5376bee756 100644 --- a/mysql-test/r/derived_opt.result +++ b/mysql-test/r/derived_opt.result @@ -273,4 +273,13 @@ ON alias3.f4 != 0 ) ON alias3.f4 != 0; f4 f4 f2 f4 drop table t1,t2,t3,t4; +# +# LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal +# Fix: force materialization in case of conflict +# +SET optimizer_switch='derived_merge=on'; +CREATE TABLE t1 ( i INT ); +INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) ); +drop table t1; +set optimizer_switch=@save_optimizer_switch; set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 587a1dd9e31..4756daaf687 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -80,6 +80,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; select * from (select * from t1 where f1 in (2,3)) tt where f11=2; @@ -93,6 +94,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 12 for merged views create view v1 as select * from t1; @@ -165,6 +167,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; select * from v4 where f2 in (1,3); @@ -178,6 +181,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 12 for materialized derived tables explain for simple derived @@ -229,6 +233,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; select * from t1 join (select * from t2 group by f2) tt on f1=f2; @@ -244,6 +249,7 @@ Handler_read_last 0 Handler_read_next 3 Handler_read_prev 0 Handler_read_rnd 11 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 36 for materialized views drop view v1,v2,v3; @@ -318,6 +324,7 @@ Handler_read_last 0 Handler_read_next 22 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 60 explain showing late materialization flush status; @@ -334,6 +341,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; select * from t1 join v2 on f1=f2; @@ -349,6 +357,7 @@ Handler_read_last 0 Handler_read_next 3 Handler_read_prev 0 Handler_read_rnd 11 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 36 explain extended select * from v1 join v4 on f1=f2; id select_type table type possible_keys key key_len ref rows filtered Extra @@ -443,6 +452,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 39 flush status; merged in merged derived join merged in merged derived @@ -1089,7 +1099,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t system NULL NULL NULL NULL 1 100.00 1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00 -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select 6 AS `a`,5 AS `b` from `test`.`t3` where (not(<6,5>(((6,5),(select 7,5 having (trigcond((((6) = 7) or isnull(7))) and trigcond((((5) = 5) or isnull(5))) and trigcond((7)) and trigcond((5)))))))) SELECT t.a,t.b FROM t3 RIGHT JOIN ((SELECT * FROM t1) AS t, t2) ON t2.b != 0 @@ -1103,7 +1113,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00 -3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select 6 AS `a`,5 AS `b` from `test`.`t3` where (not(<6,5>(((6,5),(select 7,5 having (trigcond((((6) = 7) or isnull(7))) and trigcond((((5) = 5) or isnull(5))) and trigcond((7)) and trigcond((5)))))))) SELECT t.a,t.b FROM t3 RIGHT JOIN (v1 AS t, t2) ON t2.b != 0 @@ -1117,7 +1127,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00 -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select 6 AS `a`,5 AS `b` from `test`.`t3` where (not(<6,5>(((6,5),(select 7,5 having (trigcond((((6) = 7) or isnull(7))) and trigcond((((5) = 5) or isnull(5))) and trigcond((7)) and trigcond((5)))))))) DROP VIEW v1; @@ -1800,6 +1810,7 @@ INSERT INTO t2 VALUES (7), (4); CREATE TABLE t1 (b int NOT NULL); INSERT INTO t1 VALUES (5), (7); CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; +SET @save_optimizer_switch=@@optimizer_switch; SET SESSION optimizer_switch='derived_merge=off'; PREPARE st1 FROM 'SELECT * FROM (SELECT * FROM t2 LEFT JOIN v1 ON t2.a = v1.b) AS t'; @@ -1812,9 +1823,9 @@ a b 7 7 4 NULL DEALLOCATE PREPARE st1; +set SESSION optimizer_switch= @save_optimizer_switch; DROP VIEW v1; DROP TABLE t1,t2; -SET SESSION optimizer_switch='derived_merge=on'; # # LP bug #879939: assertion in ha_maria::enable_indexes # with derived_with_keys=on @@ -1832,6 +1843,7 @@ INSERT INTO t1 VALUES ('USA','Mesquite'), ('USA','Metairie'), ('USA','Miami'); CREATE TABLE t3 (a varchar(35)); INSERT INTO t3 VALUES ('Miami'); +SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch = 'derived_with_keys=on'; SET @@tmp_table_size=1024*4; explain SELECT * FROM (SELECT t1.* FROM t1, t2) AS t JOIN t3 ON t3.a = t.b; @@ -1855,6 +1867,7 @@ USA Miami Miami USA Miami Miami USA Miami Miami SET @@tmp_table_size=default; +set SESSION optimizer_switch= @save_optimizer_switch; drop table t1,t2,t3; # # BUG#882994: Crash in QUICK_RANGE_SELECT::reset with derived_with_keys @@ -1889,5 +1902,42 @@ ORDER BY CONCAT(alias2.col_varchar_nokey); col_varchar_key pk col_varchar_key col_varchar_nokey set max_heap_table_size= @tmp_882994; drop table t1,t2,t3; +# +# LP bug #917990: Bad estimate of #rows for derived table with LIMIT +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES +(8), (3), (4), (7), (9), (5), (1), (2); +SELECT * FROM (SELECT * FROM t1 LIMIT 3) t; +a +8 +3 +4 +EXPLAIN +SELECT * FROM (SELECT * FROM t1 LIMIT 3) t; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 +DROP TABLE t1; +# +# LP BUG#921878 incorrect check of items during columns union types +# aggregation for merged derived tables +# +SET @save_optimizer_switch=@@optimizer_switch; +SET SESSION optimizer_switch='derived_merge=on'; +CREATE TABLE t1 ( a ENUM( 'x', 'y' ) ); +insert into t1 values ('x'); +CREATE TABLE t2 LIKE t1; +insert into t1 values ('y'); +CREATE TABLE t3 LIKE t1; +INSERT INTO t3 +SELECT * FROM ( SELECT * FROM t1 ) AS A +UNION SELECT * FROM t2; +select * from t3; +a +x +y +drop table t1,t2,t3; +set SESSION optimizer_switch= @save_optimizer_switch; set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index c39a226303b..aa93424f2ae 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -1825,6 +1825,70 @@ drop table t1; # End of 5.1 tests # +# Bug #904345: MIN/MAX optimization with constant FALSE condition +# +CREATE TABLE t1 (a int NOT NULL, KEY(a)); +INSERT INTO t1 VALUES (10), (8), (11), (7), (15), (12), (9); +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES +(8,2), (6,9), (8,4), (5,3), (9,1); +EXPLAIN EXTENDED +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT 3,4) AND a<10; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 range a a 4 NULL 4 100.00 Using where; Using index +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select max(`test`.`t1`.`a`) AS `MAX(a)` from `test`.`t1` where (<(1),(2)>((((1,2)),(select 3,4 having (((1 = 3) or isnull(3)) and ((2 = 4) or isnull(4)) and (3) and (4))))) and (`test`.`t1`.`a` < 10)) +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT 3,4) AND a<10; +MAX(a) +NULL +EXPLAIN EXTENDED +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT a,b FROM t2 WHERE b<5) and a<10; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY eq_ref distinct_key distinct_key 10 func,func 1 100.00 +1 PRIMARY t1 range a a 4 NULL 4 100.00 Using where; Using index; Using join buffer (flat, BNL join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where +Warnings: +Note 1003 select max(`test`.`t1`.`a`) AS `MAX(a)` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = 1) and (`test`.`t1`.`a` < 10)) +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT a,b FROM t2 WHERE b<5) and a<10; +MAX(a) +NULL +EXPLAIN EXTENDED +SELECT MAX(a) FROM t1 WHERE RAND()*0<>0 AND a<10; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range a a 4 NULL 4 100.00 Using where; Using index +Warnings: +Note 1003 select max(`test`.`t1`.`a`) AS `MAX(a)` from `test`.`t1` where (((rand() * 0) <> 0) and (`test`.`t1`.`a` < 10)) +SELECT MAX(a) FROM t1 WHERE RAND()*0<>0 AND a<10; +MAX(a) +NULL +DROP TABLE t1,t2; +# +# Bug #879860: MIN/MAX for subquery returning empty set +# +CREATE TABLE t1 (a int PRIMARY KEY); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (a int NOT NULL); +INSERT INTO t2 VALUES (10); +CREATE TABLE t3 ( a int, b int); +INSERT INTO t3 VALUES (19,1), (20,5); +EXPLAIN EXTENDED +SELECT (SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b) FROM t3; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 +2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00 +2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1276 Field or reference 'test.t3.b' of SELECT #2 was resolved in SELECT #1 +Note 1003 select <`test`.`t3`.`b`>((select min(1) from dual where (10 = `test`.`t3`.`b`))) AS `(SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b)` from `test`.`t3` +SELECT (SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b) FROM t3; +(SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b) +NULL +NULL +DROP TABLE t1,t2,t3; +# +End of 5.2 tests +# # BUG#46680 - Assertion failed in file item_subselect.cc, # line 305 crashing on HAVING subquery # diff --git a/mysql-test/r/handler_read_last.result b/mysql-test/r/handler_read_last.result index a21e9ed9564..574c3c25ab1 100644 --- a/mysql-test/r/handler_read_last.result +++ b/mysql-test/r/handler_read_last.result @@ -13,6 +13,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; SELECT a FROM t1 ORDER BY a DESC LIMIT 1; @@ -26,6 +27,7 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; SELECT a FROM t1 ORDER BY a LIMIT 3; @@ -41,6 +43,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; SELECT a FROM t1 ORDER BY a DESC LIMIT 3; @@ -56,5 +59,6 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 2 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 DROP TABLE t1; diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 538d6ddd0fd..04754375103 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -698,6 +698,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 1 DROP TABLE t1; CREATE TABLE t1 ( diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index d8230826048..d826fbe2aa7 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -861,6 +861,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 5 drop table t1, t2, t3; create table t1 (a int); @@ -1271,6 +1272,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 1 DROP TABLE t1, t2; End of 5.1 tests diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index 07ceb573f85..19de0fb0a5a 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5392,4 +5392,184 @@ x 5 5 4 SET join_cache_level = DEFAULT; SET optimizer_switch=@tmp_optimizer_switch; DROP TABLE t1,t2,t3,t4; +# +# Bug#53305 Duplicate weedout + join buffer (join cache --level=7,8) +# +create table t1 (uid int, fid int, index(uid)); +insert into t1 values +(1,1), (1,2), (1,3), (1,4), +(2,5), (2,6), (2,7), (2,8), +(3,1), (3,2), (3,9); +create table t2 (uid int primary key, name varchar(128), index(name)); +insert into t2 values +(1, "A"), (2, "B"), (3, "C"), (4, "D"), (5, "E"), +(6, "F"), (7, "G"), (8, "H"), (9, "I"); +create table t3 (uid int, fid int, index(uid)); +insert into t3 values +(1,1), (1,2), (1,3),(1,4), +(2,5), (2,6), (2,7), (2,8), +(3,1), (3,2), (3,9); +set @tmp_optimizer_switch=@@optimizer_switch; +set @@optimizer_switch='semijoin=on'; +set optimizer_switch='materialization=off'; +set optimizer_switch='loosescan=off,firstmatch=off'; +set optimizer_switch='mrr_sort_keys=off'; +set join_cache_level=7; +create table t4 (uid int primary key, name varchar(128), index(name)); +insert into t4 values +(1, "A"), (2, "B"), (3, "C"), (4, "D"), (5, "E"), +(6, "F"), (7, "G"), (8, "H"), (9, "I"); +explain select name from t2, t1 +where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid) +and t2.uid=t1.fid; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ref uid uid 5 const 4 Using where; Start temporary +1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t3.fid 1 Using index +1 PRIMARY t1 ALL uid NULL NULL NULL 11 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.fid 1 Using join buffer (flat, BKAH join); Rowid-ordered scan +select name from t2, t1 +where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid) +and t2.uid=t1.fid; +name +A +A +B +B +C +D +E +F +G +H +I +set join_cache_level = default; +set optimizer_switch=@tmp_optimizer_switch; +drop table t1,t2,t3,t4; +# +# Bug#50358 - semijoin execution of subquery with outerjoin +# emplying join buffer +# +CREATE TABLE t1 (i int); +CREATE TABLE t2 (i int); +CREATE TABLE t3 (i int); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (6); +INSERT INTO t3 VALUES (1), (2); +set @tmp_optimizer_switch=@@optimizer_switch; +set @@optimizer_switch='semijoin=on'; +set optimizer_switch='materialization=on'; +set join_cache_level=0; +EXPLAIN +SELECT * FROM t1 WHERE t1.i IN +(SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 2 +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1 Using where +SELECT * FROM t1 WHERE t1.i IN +(SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); +i +1 +2 +set join_cache_level=2; +EXPLAIN +SELECT * FROM t1 WHERE t1.i IN +(SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 2 +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join) +SELECT * FROM t1 WHERE t1.i IN +(SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); +i +1 +2 +set join_cache_level = default; +set optimizer_switch=@tmp_optimizer_switch; +DROP TABLE t1,t2,t3; +# +# Bug #12546542: missing row with semijoin=off + join cache +# (LP bug #922971) +# +CREATE TABLE t1 (a varchar(1024)); +INSERT INTO t1 VALUES ('v'), ('we'); +CREATE TABLE t2 ( +a varchar(1024) CHARACTER SET utf8 DEFAULT NULL, b int, c int +); +INSERT INTO t2 VALUES ('we',4,NULL), ('v',1305673728,6); +CREATE TABLE t3 (b int, c int); +INSERT INTO t3 VALUES (4,4); +set @tmp_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off'; +set optimizer_switch='materialization=off'; +set join_cache_level=0; +EXPLAIN +SELECT * FROM t1 +WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b +WHERE t2.c < 10 OR t3.c > 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 1 Using where +SELECT * FROM t1 +WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b +WHERE t2.c < 10 OR t3.c > 1); +a +v +we +set join_cache_level=2; +EXPLAIN +SELECT * FROM t1 +WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b +WHERE t2.c < 10 OR t3.c > 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join) +SELECT * FROM t1 +WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b +WHERE t2.c < 10 OR t3.c > 1); +a +v +we +set join_cache_level = default; +set optimizer_switch=@tmp_optimizer_switch; +DROP TABLE t1,t2,t3; +# +# Bug #925985: LEFT JOIN with optimize_join_buffer_size=off + +# join_buffer_size > join_buffer_space_limit +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (5), (3); +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES +(3,30), (1,10), (7,70), (2,20), +(3,31), (1,11), (7,71), (2,21), +(3,32), (1,12), (7,72), (2,22); +CREATE TABLE t3 (b int, c int); +INSERT INTO t3 VALUES (32, 302), (42,400), (30,300); +set @tmp_optimizer_switch=@@optimizer_switch; +set optimizer_switch='optimize_join_buffer_size=off'; +set join_buffer_space_limit=4096; +set join_buffer_size=4096*2; +set join_cache_level=2; +set optimizer_switch='outer_join_with_cache=on'; +EXPLAIN +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t2 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join) +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; +a a b b c +3 3 30 30 300 +3 3 31 NULL NULL +3 3 32 32 302 +set join_buffer_space_limit=default; +set join_buffer_size=default; +set join_cache_level=default; +set optimizer_switch=@tmp_optimizer_switch; +DROP TABLE t1,t2,t3; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 16913864f5d..842ac2e81cd 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1245,6 +1245,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 6 DROP TABLE t1,t2; CREATE TABLE t1 (c int PRIMARY KEY, e int NOT NULL); @@ -1747,6 +1748,7 @@ Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 1048581 flush status; select sum(t3.b) from t2 left join t3 on t3.a=t2.a and t2.a <> 10; @@ -1760,6 +1762,7 @@ Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 1048581 drop table t1,t2,t3; # diff --git a/mysql-test/r/join_outer_innodb.result b/mysql-test/r/join_outer_innodb.result index 749cb2ab212..5a99cb83b90 100644 --- a/mysql-test/r/join_outer_innodb.result +++ b/mysql-test/r/join_outer_innodb.result @@ -52,3 +52,11 @@ pk DROP TABLE t1,t2; # End BUG#58456 +CREATE TABLE t1(a int, b int, KEY (a), PRIMARY KEY (b)) ENGINE=InnoDB; +CREATE TABLE t2 (b int, PRIMARY KEY (b)); +INSERT INTO t2 VALUES (4),(9); +SELECT STRAIGHT_JOIN t1.a FROM t1 RIGHT JOIN t2 ON t1.b = t2.b +WHERE (t1.b NOT BETWEEN 1 AND 7 OR t1.a IS NULL AND t1.b = t2.b) AND t2.b = 4 +GROUP BY 1; +a +DROP TABLE t1,t2; diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result index 7605af40a6f..046c758a751 100644 --- a/mysql-test/r/join_outer_jcl6.result +++ b/mysql-test/r/join_outer_jcl6.result @@ -1256,6 +1256,7 @@ Handler_read_last 0 Handler_read_next 9 Handler_read_prev 0 Handler_read_rnd 3 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 6 DROP TABLE t1,t2; CREATE TABLE t1 (c int PRIMARY KEY, e int NOT NULL); @@ -1758,6 +1759,7 @@ Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 1048581 flush status; select sum(t3.b) from t2 left join t3 on t3.a=t2.a and t2.a <> 10; @@ -1771,6 +1773,7 @@ Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 1048581 drop table t1,t2,t3; # diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index a1feb3ad40d..ab07b7b1f5d 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -817,3 +817,19 @@ set global keycache1.key_buffer_size=0; set global keycache2.key_buffer_size=0; set global key_buffer_size=@save_key_buffer_size; set global key_cache_segments=@save_key_cache_segments; +# +# Bug#12361113: crash when load index into cache +# +# Note that this creates an empty disabled key cache! +SET GLOBAL key_cache_none.key_cache_block_size = 1024; +CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1, 1); +CACHE INDEX t1 in key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +# The bug crashed the server at LOAD INDEX below. Now it will succeed +# since the default cache is used due to CACHE INDEX failed for +# key_cache_none. +LOAD INDEX INTO CACHE t1; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +DROP TABLE t1; diff --git a/mysql-test/r/myisam_mrr.result b/mysql-test/r/myisam_mrr.result index 9dd3602bab7..01d3e6aeb5d 100644 --- a/mysql-test/r/myisam_mrr.result +++ b/mysql-test/r/myisam_mrr.result @@ -557,4 +557,66 @@ COUNT(alias2.f2) set @@join_cache_level= @tmp_730133_jcl; set @@optimizer_switch= @tmp_730133_os; drop table t1; +# +# Test of MRR handler counters +# +flush status; +show status like 'Handler_mrr%'; +Variable_name Value +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int, filler char(200), key(a)); +insert into t1 +select A.a+10*B.a+100*C.a+1000*D.a, 123,'filler' from t0 A, t0 B, t0 C, t0 D; +explain select sum(b) from t1 where a < 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 8 Using index condition; Rowid-ordered scan +# This should show one MRR scan and no re-fills: +flush status; +select sum(b) from t1 where a < 10; +sum(b) +1230 +show status like 'handler_mrr%'; +Variable_name Value +set @mrr_buffer_size_save= @@mrr_buffer_size; +set mrr_buffer_size=128; +explain select sum(b) from t1 where a < 1600; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 5 NULL 1380 Using index condition; Rowid-ordered scan +# This should show one MRR scan and one extra rowid sort: +flush status; +select sum(b) from t1 where a < 1600; +sum(b) +196800 +show status like 'handler_mrr%'; +Variable_name Value +set @@mrr_buffer_size= @mrr_buffer_size_save; +#Now, let's check BKA: +set @join_cache_level_save= @@join_cache_level; +set @join_buffer_size_save= @@join_buffer_size; +set join_cache_level=6; +explain select sum(t1.b) from t0,t1 where t0.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where +1 SIMPLE t1 ref a a 5 test.t0.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +flush status; +select sum(t1.b) from t0,t1 where t0.a=t1.a; +sum(t1.b) +1230 +show status like 'handler_mrr%'; +Variable_name Value +set join_buffer_size=10; +explain select sum(t1.b) from t0,t1 where t0.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where +1 SIMPLE t1 ref a a 5 test.t0.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +flush status; +select sum(t1.b) from t0,t1 where t0.a=t1.a; +sum(t1.b) +1230 +show status like 'handler_mrr%'; +Variable_name Value +set join_cache_level= @join_cache_level_save; +set join_buffer_size= @join_buffer_size_save; +drop table t0, t1; set optimizer_switch= @myisam_mrr_tmp; diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index ca9d3a20404..ab707ceef80 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -191,6 +191,7 @@ CREATE TABLE `я` (a INT) engine=myisam; SET NAMES DEFAULT; call mtr.add_suppression("@003f.frm' \\(errno: 22\\)"); mysqlcheck --default-character-set="latin1" --databases test +call mtr.add_suppression("Can't find file: '..test.@003f.frm'"); test.? Error : Table doesn't exist status : Operation failed diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 022523d4749..3db422657e3 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -4770,79 +4770,11 @@ INSERT INTO b12809202_db.t2 VALUES (1), (2), (3); -- Retrieving table structure for table t1... -- Sending SELECT query... -- Retrieving rows... --- --- Host: localhost Database: b12809202_db --- ------------------------------------------------------ - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `t1` --- - -DROP TABLE IF EXISTS `t1`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `t1` ( - `c1` int(11) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `t1` --- - -LOCK TABLES `t1` WRITE; -/*!40000 ALTER TABLE `t1` DISABLE KEYS */; -INSERT INTO `t1` VALUES (1),(2),(3); -- Retrieving table structure for table t2... -- Sending SELECT query... -- Retrieving rows... -/*!40000 ALTER TABLE `t1` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `t2` --- - -DROP TABLE IF EXISTS `t2`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `t2` ( - `c1` int(11) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `t2` --- - -LOCK TABLES `t2` WRITE; -/*!40000 ALTER TABLE `t2` DISABLE KEYS */; -INSERT INTO `t2` VALUES (1),(2),(3); -/*!40000 ALTER TABLE `t2` ENABLE KEYS */; -UNLOCK TABLES; -- Disconnecting from localhost... -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed #### Dump ends here #### DROP TABLE b12809202_db.t1; DROP TABLE b12809202_db.t2; diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 4e28f73caad..35c6ebe1442 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -428,6 +428,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 5 DROP TABLE t1,t2,t3,t4; CREATE TABLE t1 ( diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 270e74ddf52..d320b5b669f 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1759,3 +1759,57 @@ i1 i2 4 4 5 5 DROP TABLE t1, t2, t3; +# +# Fix of LP BUG#793589 Wrong result with double ORDER BY +# +CREATE TABLE t1 ( b int) ; +INSERT INTO t1 VALUES (8),(9); +CREATE TABLE t2 ( a int, b int, PRIMARY KEY (a)) ; +INSERT INTO t2 VALUES (6,7),(7,7),(8,1),(9,7),(10,1),(11,5),(12,2),(13,0),(14,1),(15,8),(16,1),(17,1),(18,9),(19,1),(20,5); +SELECT t2.b AS field1 FROM t1, t2 WHERE t1.b = t2.a GROUP BY field1 ORDER BY t1.b, field1; +field1 +1 +7 +SELECT t2.b, t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b, t2.b; +b b +1 8 +7 9 +SELECT t2.b,t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; +b b +1 8 +7 9 +SELECT t2.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; +b +1 +7 +# field1 removed from ORDER BY +explain extended +SELECT t2.b AS field1 FROM t1, t2 WHERE t1.b = t2.a GROUP BY field1 ORDER BY t1.b, field1; +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 Using where; Using temporary; Using filesort +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 +Warnings: +Note 1003 select `test`.`t2`.`b` AS `field1` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`a` = `test`.`t1`.`b`) group by `test`.`t2`.`b` order by `test`.`t1`.`b` +explain extended +SELECT t2.b, t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b, t2.b; +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 Using where; Using temporary; Using filesort +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 +Warnings: +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t1`.`b` AS `b` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`a` = `test`.`t1`.`b`) group by `test`.`t2`.`b` order by `test`.`t1`.`b` +explain extended +SELECT t2.b,t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; +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 Using where; Using temporary; Using filesort +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 +Warnings: +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t1`.`b` AS `b` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`a` = `test`.`t1`.`b`) group by `test`.`t2`.`b` order by `test`.`t1`.`b` +explain extended +SELECT t2.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; +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 Using where; Using temporary; Using filesort +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 +Warnings: +Note 1003 select `test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`a` = `test`.`t1`.`b`) group by `test`.`t2`.`b` order by `test`.`t1`.`b` +drop table t1,t2; +End of 5.2 tests diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 2e90bf8e27b..7c38fa18faa 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -521,6 +521,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 EXPLAIN PARTITIONS SELECT c1 FROM t2 WHERE (c1 > 10 AND c1 < 13) OR (c1 > 17 AND c1 < 20); id select_type table partitions type possible_keys key key_len ref rows Extra @@ -540,6 +541,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 DROP TABLE t1,t2; CREATE TABLE `t1` ( @@ -571,6 +573,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 EXPLAIN PARTITIONS SELECT c1 FROM t2 WHERE (c1 > 2 AND c1 < 5); id select_type table partitions type possible_keys key key_len ref rows Extra @@ -588,6 +591,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 EXPLAIN PARTITIONS SELECT c1 FROM t1 WHERE (c1 > 12 AND c1 < 15); id select_type table partitions type possible_keys key key_len ref rows Extra @@ -605,6 +609,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 EXPLAIN PARTITIONS SELECT c1 FROM t2 WHERE (c1 > 12 AND c1 < 15); id select_type table partitions type possible_keys key key_len ref rows Extra @@ -622,6 +627,7 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 DROP TABLE t1,t2; create table t1 (a int) partition by list ((a/3)*10 div 1) diff --git a/mysql-test/r/partition_key_cache.result b/mysql-test/r/partition_key_cache.result index 653d2f29d54..f1b174ca249 100644 --- a/mysql-test/r/partition_key_cache.result +++ b/mysql-test/r/partition_key_cache.result @@ -397,6 +397,33 @@ test.t1 assign_to_keycache error Subpartition sp0 returned error test.t1 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't1' test.t1 assign_to_keycache status Operation failed DROP TABLE t1,t2; +# +# Bug#12361113: crash when load index into cache +# +# Note that this creates an empty disabled key cache! +SET GLOBAL key_cache_none.key_cache_block_size = 1024; +CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) +ENGINE = MYISAM +PARTITION BY HASH(a) PARTITIONS 2; +INSERT INTO t1 VALUES (1, 1); +CACHE INDEX t1 IN key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +CACHE INDEX t1 PARTITION (p0) IN key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +CACHE INDEX t1 PARTITION (p1) IN key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +CACHE INDEX t1 PARTITION (p0) KEY (`b`) IN key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +CACHE INDEX t1 PARTITION (p1) KEY (`b`) IN key_cache_none; +ERROR HY000: Unknown key cache 'key_cache_none' +# The bug crashed the server at LOAD INDEX below. Now it will succeed +# since the default cache is used due to CACHE INDEX failed for +# key_cache_none. +LOAD INDEX INTO CACHE t1; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +DROP TABLE t1; +# Clean up SET GLOBAL hot_cache.key_buffer_size = 0; SET GLOBAL warm_cache.key_buffer_size = 0; SET @@global.cold_cache.key_buffer_size = 0; diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index eb0849e2cad..32c0cd34942 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -2968,7 +2968,10 @@ flush status; delete from t2 where b > 5; show status like 'Handler_read_rnd_next'; Variable_name Value -Handler_read_rnd_next 1215 +Handler_read_rnd_next 815 +show status like 'Handler_read_rnd_deleted'; +Variable_name Value +Handler_read_rnd_deleted 400 show status like 'Handler_read_key'; Variable_name Value Handler_read_key 0 @@ -2982,7 +2985,10 @@ flush status; delete from t2 where b < 5 or b > 3; show status like 'Handler_read_rnd_next'; Variable_name Value -Handler_read_rnd_next 1215 +Handler_read_rnd_next 515 +show status like 'Handler_read_rnd_deleted'; +Variable_name Value +Handler_read_rnd_deleted 700 show status like 'Handler_read_key'; Variable_name Value Handler_read_key 0 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 7d793f16c1a..b4a09091aa6 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -3790,6 +3790,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; execute st; @@ -3803,6 +3804,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; select * from t1 use index() where a=3; @@ -3816,6 +3818,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 8 flush status; execute st; @@ -3829,6 +3832,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 deallocate prepare st; drop table t1; diff --git a/mysql-test/r/ps_11bugs.result b/mysql-test/r/ps_11bugs.result index f9f0525646d..56894302505 100644 --- a/mysql-test/r/ps_11bugs.result +++ b/mysql-test/r/ps_11bugs.result @@ -121,8 +121,8 @@ insert into t1 values (1); explain select * from t1 where 3 in (select (1+1) union select 1); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used -3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used NULL UNION RESULT ALL NULL NULL NULL NULL NULL select * from t1 where 3 in (select (1+1) union select 1); a diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 7f035ca749a..d2e3594dfc6 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2783,10 +2783,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 index key1 key1 5 NULL 4 Using where; Using index explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 range key1 key1 5 NULL 3 Using where; Using index select max(key1) from t1 where key1 <= 0.6158; max(key1) 0.6158000230789185 @@ -2805,10 +2805,10 @@ max(key1) min(key2) 0.6158000230789185 1.3761999607086182 select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; max(key1) -0.6158000230789185 +0.38449999690055847 select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; min(key1) -0.37619999051094055 +0.38449999690055847 DROP TABLE t1,t2; CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); @@ -4346,6 +4346,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 6 DROP TABLE t1, t2; CREATE TABLE t1 (f1 bigint(20) NOT NULL default '0', diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result index 54eed1ebaae..f5aa02fe94c 100644 --- a/mysql-test/r/select_jcl6.result +++ b/mysql-test/r/select_jcl6.result @@ -2794,10 +2794,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 index key1 key1 5 NULL 4 Using where; Using index explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 range key1 key1 5 NULL 3 Using where; Using index select max(key1) from t1 where key1 <= 0.6158; max(key1) 0.6158000230789185 @@ -2816,10 +2816,10 @@ max(key1) min(key2) 0.6158000230789185 1.3761999607086182 select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; max(key1) -0.6158000230789185 +0.38449999690055847 select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; min(key1) -0.37619999051094055 +0.38449999690055847 DROP TABLE t1,t2; CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); @@ -4357,7 +4357,8 @@ Handler_read_last 0 Handler_read_next 10 Handler_read_prev 0 Handler_read_rnd 10 -Handler_read_rnd_next 7 +Handler_read_rnd_deleted 1 +Handler_read_rnd_next 6 DROP TABLE t1, t2; CREATE TABLE t1 (f1 bigint(20) NOT NULL default '0', f2 int(11) NOT NULL default '0', diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result index 7f035ca749a..d2e3594dfc6 100644 --- a/mysql-test/r/select_pkeycache.result +++ b/mysql-test/r/select_pkeycache.result @@ -2783,10 +2783,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 index key1 key1 5 NULL 4 Using where; Using index explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 range key1 key1 5 NULL 3 Using where; Using index select max(key1) from t1 where key1 <= 0.6158; max(key1) 0.6158000230789185 @@ -2805,10 +2805,10 @@ max(key1) min(key2) 0.6158000230789185 1.3761999607086182 select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; max(key1) -0.6158000230789185 +0.38449999690055847 select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; min(key1) -0.37619999051094055 +0.38449999690055847 DROP TABLE t1,t2; CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); @@ -4346,6 +4346,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 6 DROP TABLE t1, t2; CREATE TABLE t1 (f1 bigint(20) NOT NULL default '0', diff --git a/mysql-test/r/single_delete_update.result b/mysql-test/r/single_delete_update.result index 72419c6ec9d..d4534a2c2d8 100644 --- a/mysql-test/r/single_delete_update.result +++ b/mysql-test/r/single_delete_update.result @@ -29,6 +29,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; @@ -46,6 +47,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; a i @@ -80,6 +82,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; @@ -97,6 +100,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; a i @@ -128,6 +132,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -145,6 +150,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 ## should be 5 (previous LIMIT) SELECT 1 - COUNT(*) FROM t2 WHERE b = 10; @@ -180,6 +186,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -197,6 +204,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 ## should be 5 (previous LIMIT) SELECT 257 - COUNT(*) FROM t2 WHERE b = 10; @@ -226,6 +234,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -243,6 +252,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; a b c d @@ -270,6 +280,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -287,6 +298,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; a b c d @@ -317,6 +329,7 @@ Handler_read_last 0 Handler_read_next 7 Handler_read_prev 0 Handler_read_rnd 4 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; id select_type table type possible_keys key key_len ref rows filtered Extra @@ -339,6 +352,7 @@ Handler_read_last 0 Handler_read_next 7 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; i key1 key2 @@ -375,6 +389,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; @@ -392,6 +407,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; a i @@ -426,6 +442,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; DELETE FROM t2 ORDER BY a, b DESC LIMIT 5; @@ -443,6 +460,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 ORDER BY a, b DESC; a b c @@ -486,6 +504,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; @@ -509,6 +528,7 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5; @@ -526,6 +546,7 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC; a b c @@ -561,6 +582,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; @@ -578,6 +600,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; a i @@ -617,6 +640,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; @@ -634,6 +658,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; a i @@ -670,6 +695,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -687,6 +713,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 ## should be 5 (previous LIMIT) SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c; @@ -722,6 +749,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -739,6 +767,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 ## should be 5 (previous LIMIT) SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c; @@ -768,6 +797,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -785,6 +815,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; a b c d @@ -813,6 +844,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -830,6 +862,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE b = 10 ORDER BY a, c; a b c d @@ -861,6 +894,7 @@ Handler_read_last 0 Handler_read_next 7 Handler_read_prev 0 Handler_read_rnd 4 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; id select_type table type possible_keys key key_len ref rows filtered Extra @@ -883,6 +917,7 @@ Handler_read_last 0 Handler_read_next 7 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; i key1 key2 @@ -923,6 +958,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; @@ -940,6 +976,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i; a i @@ -979,6 +1016,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 FLUSH STATUS; UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5; @@ -996,6 +1034,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 SELECT * FROM t2 WHERE c = 10 ORDER BY a, b DESC; a b c @@ -1033,6 +1072,7 @@ Handler_read_last 0 Handler_read_next 4 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; @@ -1056,6 +1096,7 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 FLUSH STATUS; UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5; @@ -1073,6 +1114,7 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 4 Handler_read_rnd 5 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC; a b c diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index 91a120313ae..0182ffac880 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -282,6 +282,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 7 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 23 Handler_rollback 0 Handler_savepoint 0 @@ -297,7 +298,35 @@ Created_tmp_files 0 Created_tmp_tables 2 Handler_tmp_update 2 Handler_tmp_write 7 -Rows_tmp_read 35 +Rows_tmp_read 36 +drop table t1; +CREATE TABLE t1 (i int(11) DEFAULT NULL, KEY i (i) ) ENGINE=MyISAM; +insert into t1 values (1),(2),(3),(4),(5); +flush status; +select * from t1 where i=5 union select * from t1 where i=5; +i +5 +show status like "handler%"; +Variable_name Value +Handler_commit 0 +Handler_delete 0 +Handler_discover 0 +Handler_prepare 0 +Handler_read_first 0 +Handler_read_key 2 +Handler_read_last 0 +Handler_read_next 2 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 1 +Handler_read_rnd_next 2 +Handler_rollback 0 +Handler_savepoint 0 +Handler_savepoint_rollback 0 +Handler_tmp_update 0 +Handler_tmp_write 2 +Handler_update 0 +Handler_write 0 drop table t1; set @@global.concurrent_insert= @old_concurrent_insert; SET GLOBAL log_output = @old_log_output; diff --git a/mysql-test/r/status_user.result b/mysql-test/r/status_user.result index cd8e5af3004..96edd1c4207 100644 --- a/mysql-test/r/status_user.result +++ b/mysql-test/r/status_user.result @@ -107,6 +107,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 5 Handler_rollback 2 Handler_savepoint 0 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 7d3877e678d..e7883c5801e 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4620,6 +4620,13 @@ CREATE TABLE t1(a1 int); INSERT INTO t1 VALUES (1),(2); SELECT @@session.sql_mode INTO @old_sql_mode; SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select 1 AS `1` from `test`.`t1` where ((1,((select max(`test`.`t1`.`a1`) from `test`.`t1`) > 1))) SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); 1 1 @@ -5322,7 +5329,6 @@ EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, WHERE t1.a = d1.a; ERROR 42S22: Unknown column 'd1.a' in 'where clause' DROP TABLE t1; -End of 5.1 tests. Set up test tables. CREATE TABLE t1 ( t1_id INT UNSIGNED, @@ -5847,10 +5853,161 @@ NULL NULL 5 DROP TABLE t1, t2, t3; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; +# +# BUG#50257: Missing info in REF column of the EXPLAIN +# lines for subselects +# +CREATE TABLE t1 (a INT, b INT, INDEX (a)); +INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20); +EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 5 const 1 +EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +2 SUBQUERY t1 ref a a 5 const 1 Using index +DROP TABLE t1; +# +# BUG#12616253 - WRONG RESULT WITH EXISTS(SUBQUERY) (MISSING ROWS) +# (duplicate of LP bug #888456) +# +CREATE TABLE t1 (f1 varchar(1)); +INSERT INTO t1 VALUES ('v'),('s'); +CREATE TABLE t2 (f1_key varchar(1), KEY (f1_key)); +INSERT INTO t2 VALUES ('j'),('v'),('c'),('m'),('d'), +('d'),('y'),('t'),('d'),('s'); +EXPLAIN +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY table1 ALL NULL NULL NULL NULL 2 +1 PRIMARY table2 index NULL f1_key 4 NULL 10 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index f1_key f1_key 4 NULL 10 Using where; Using index +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +f1 f1_key +v j +s j +v v +s v +v c +s c +v m +s m +v d +s d +v d +s d +v y +s y +v t +s t +v d +s d +v s +s s +DROP TABLE t1,t2; +# +# LP bug 919427: EXPLAIN for a query over a single-row table +# with IN subquery in WHERE condition +# +CREATE TABLE ot ( +col_int_nokey int(11), +col_varchar_nokey varchar(1) +) ; +INSERT INTO ot VALUES (1,'x'); +CREATE TABLE it1( +col_int_key int(11), +col_varchar_key varchar(1), +KEY idx_cvk_cik (col_varchar_key,col_int_key) +); +INSERT INTO it1 VALUES (NULL,'x'), (NULL,'f'); +CREATE TABLE it2 ( +col_int_key int(11), +col_varchar_key varchar(1), +col_varchar_key2 varchar(1), +KEY idx_cvk_cvk2_cik (col_varchar_key, col_varchar_key2, col_int_key), +KEY idx_cvk_cik (col_varchar_key, col_int_key) +); +INSERT INTO it2 VALUES (NULL,'x','x'), (NULL,'f','f'); +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +1 PRIMARY eq_ref distinct_key distinct_key 5 func 1 +2 MATERIALIZED it1 ref idx_cvk_cik idx_cvk_cik 9 const,const 1 Using where; Using index +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +col_int_nokey +1 +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +1 PRIMARY eq_ref distinct_key distinct_key 10 func,func 1 +2 MATERIALIZED it2 ref idx_cvk_cvk2_cik,idx_cvk_cik idx_cvk_cvk2_cik 8 const,const 1 Using where; Using index +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +col_int_nokey +1 +DROP TABLE ot,it1,it2; End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in -# maria-5.3 # CREATE TABLE t1 ( f1 int ); INSERT INTO t1 VALUES (19), (20); @@ -5897,32 +6054,6 @@ b c 9 NULL SET optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; -End of 5.3 tests -# -# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER -# -CREATE TABLE t1(a1 int); -INSERT INTO t1 VALUES (1),(2); -CREATE TABLE t2(a1 int); -INSERT INTO t2 VALUES (3); -SELECT @@session.sql_mode INTO @old_sql_mode; -SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); -1 -1 -1 -SET SESSION sql_mode=@old_sql_mode; -DROP TABLE t1, t2; # # BUG#50257: Missing info in REF column of the EXPLAIN # lines for subselects @@ -5945,6 +6076,54 @@ id select_type table type possible_keys key key_len ref rows Extra DROP TABLE t1; # +# Bug#11764086: Null left operand to NOT IN in WHERE clause +# behaves differently than real NULL +# +CREATE TABLE parent (id int); +INSERT INTO parent VALUES (1), (2); +CREATE TABLE child (parent_id int, other int); +INSERT INTO child VALUES (1,NULL); +# Offending query (c.parent_id is NULL for null-complemented rows only) +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id NOT IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +); +id parent_id +1 1 +2 NULL +# Some syntactic variations with IS FALSE and IS NOT TRUE +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS NOT TRUE; +id parent_id +1 1 +2 NULL +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS FALSE; +id parent_id +1 1 +2 NULL +DROP TABLE parent, child; +# End of test for bug#11764086. +# # Bug 11765699 - 58690: !TABLE || (!TABLE->READ_SET || # BITMAP_IS_SET(TABLE->READ_SET, FIELD_INDEX # @@ -6283,5 +6462,14 @@ SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1; 1 NULL drop table t1,t2,t3; +# +# LP BUG#905353 Wrong non-empty result with a constant table, +# aggregate function in subquery, MyISAM or Aria +# +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); +a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 833d6f203c2..d5d75b68628 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -125,6 +125,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 50 select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z; Z diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result index 5d7fee48d87..d794d35cf1a 100644 --- a/mysql-test/r/subselect3_jcl6.result +++ b/mysql-test/r/subselect3_jcl6.result @@ -135,6 +135,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 50 select 'No key lookups, seq reads: 29= 5 reads from t2 + 4 * 6 reads from t1.' Z; Z @@ -1153,7 +1154,7 @@ insert into t4 select a from t3; explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20 and t4.pk=t1.c); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using where; Rowid-ordered scan; LooseScan +1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using where; LooseScan 1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1) 1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) drop table t1, t3, t4; diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 1fd638fd42c..14c4254028d 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -711,7 +711,7 @@ EXPLAIN SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2); f1 f2 SET @@optimizer_switch = 'materialization=off,in_to_exists=on,semijoin=off'; @@ -802,7 +802,7 @@ EXPLAIN SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2); f1 f2 INSERT INTO t1 VALUES (1, 2); @@ -897,7 +897,7 @@ EXPLAIN SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); f1 f2 SET @@optimizer_switch = 'materialization=off,in_to_exists=on,semijoin=off'; @@ -988,7 +988,7 @@ EXPLAIN SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); f1 f2 set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/r/subselect_cache.result b/mysql-test/r/subselect_cache.result index d8ac44005f9..e38e8b42e9a 100644 --- a/mysql-test/r/subselect_cache.result +++ b/mysql-test/r/subselect_cache.result @@ -37,6 +37,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 31 set optimizer_switch='subquery_cache=off'; flush status; @@ -64,6 +65,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 61 set optimizer_switch='subquery_cache=on'; #single value subquery test (where) @@ -90,6 +92,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 31 set optimizer_switch='subquery_cache=off'; flush status; @@ -115,6 +118,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 61 set optimizer_switch='subquery_cache=on'; #single value subquery test (having) @@ -141,6 +145,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 31 set optimizer_switch='subquery_cache=off'; flush status; @@ -166,6 +171,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 61 set optimizer_switch='subquery_cache=on'; #single value subquery test (OUTER JOIN ON) @@ -264,6 +270,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 442 set optimizer_switch='subquery_cache=off'; flush status; @@ -361,6 +368,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 472 set optimizer_switch='subquery_cache=on'; #single value subquery test (GROUP BY) @@ -383,6 +391,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 4 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 36 set optimizer_switch='subquery_cache=off'; flush status; @@ -404,6 +413,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 4 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 86 set optimizer_switch='subquery_cache=on'; #single value subquery test (distinct GROUP BY) @@ -426,6 +436,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 4 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 41 set optimizer_switch='subquery_cache=off'; flush status; @@ -447,6 +458,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 4 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 91 set optimizer_switch='subquery_cache=on'; #single value subquery test (ORDER BY) @@ -475,6 +487,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 10 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 42 set optimizer_switch='subquery_cache=off'; flush status; @@ -502,6 +515,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 10 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 72 set optimizer_switch='subquery_cache=on'; #single value subquery test (distinct ORDER BY) @@ -524,7 +538,8 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 4 -Handler_read_rnd_next 37 +Handler_read_rnd_deleted 1 +Handler_read_rnd_next 36 set optimizer_switch='subquery_cache=off'; flush status; select distinct a from t1 ORDER BY (select d from t2 where b=c); @@ -545,7 +560,8 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 4 -Handler_read_rnd_next 67 +Handler_read_rnd_deleted 1 +Handler_read_rnd_next 66 set optimizer_switch='subquery_cache=on'; #single value subquery test (LEFT JOIN ON) flush status; @@ -643,6 +659,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 141 set optimizer_switch='subquery_cache=off'; flush status; @@ -740,6 +757,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 671 set optimizer_switch='subquery_cache=on'; #single value subquery test (PS) @@ -1364,6 +1382,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 145 set optimizer_switch='subquery_cache=on'; flush status; @@ -1393,6 +1412,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 84 #several subqueries (several levels) set optimizer_switch='subquery_cache=off'; @@ -1425,6 +1445,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 127 set optimizer_switch='subquery_cache=on'; flush status; @@ -1454,6 +1475,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 69 #clean up drop table t1,t2; @@ -1644,6 +1666,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 57 set optimizer_switch='subquery_cache=on'; flush status; @@ -1669,6 +1692,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 37 argument of aggregate function as parameter of subquery (illegal use) set optimizer_switch='subquery_cache=off'; @@ -1695,6 +1719,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 57 set optimizer_switch='subquery_cache=on'; flush status; @@ -1720,6 +1745,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 8 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 41 drop table t1,t2; #test of flattening subquery optimisations and cache @@ -1761,6 +1787,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 16 alter table t2 drop primary key; set optimizer_switch='default,semijoin=off,materialization=off,subquery_cache=off'; @@ -1798,6 +1825,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 151 set optimizer_switch='default,semijoin=off,materialization=off,subquery_cache=on'; explain select * from t1 where a in (select pk from t2); @@ -1834,6 +1862,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 43 set optimizer_switch='default,semijoin=off,materialization=on,subquery_cache=on'; explain select * from t1 where a in (select pk from t2); @@ -1870,6 +1899,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 27 drop table t0,t1,t2; set optimizer_switch='default'; diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index 5c750e8b078..097e65fa94f 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -1793,7 +1793,7 @@ SELECT * FROM t1 WHERE a IN ( SELECT MIN(a) FROM t1 ); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away Warnings: Note 1003 select 8 AS `a` from dual where <8>((8,(select min(`test`.`t1`.`a`) from `test`.`t1` having ((8) = (min(`test`.`t1`.`a`)))))) DROP TABLE t1; @@ -1811,6 +1811,43 @@ a b c 4 4 2 4 4 4 DROP TABLE t1,t2; +# +# BUG#922254: Assertion `0' failed at item_cmpfunc.cc:5899: Item* Item_equal::get_first(JOIN_TAB*, Item*) +# +CREATE TABLE t1 ( a VARCHAR(3) ); +CREATE TABLE t2 ( b VARCHAR(3), c VARCHAR(8), KEY(c) ); +INSERT INTO t2 VALUES ('USA','Abilene'),('USA','Akron'); +EXPLAIN +SELECT * FROM +( SELECT * FROM t1 ) AS alias1, +t2 AS alias2 +WHERE b = a AND a IN ( +SELECT alias3.c +FROM t2 AS alias3, t2 AS alias4 +WHERE alias4.c = alias3.b +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +3 MATERIALIZED alias3 ALL NULL NULL NULL NULL 2 +3 MATERIALIZED alias4 index c c 11 NULL 2 Using where; Using index; Using join buffer (flat, BNL join) +DROP TABLE t1,t2; +# +# BUG#928048: Query containing IN subquery with OR in the where clause returns a wrong result +# +create table t1 (a int, b int); +insert into t1 values (7,5), (3,3), (5,4), (9,3); +create table t2 (a int, b int, index i_a(a)); +insert into t2 values +(4,2), (7,9), (7,4), (3,1), (5,3), (3,1), (9,4), (8,1); +explain select * from t1 where t1.a in (select a from t2 where t2.a=7 or t2.b<=1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +2 MATERIALIZED t2 ALL i_a NULL NULL NULL 8 Using where +select * from t1 where t1.a in (select a from t2 where t2.a=7 or t2.b<=1); +a b +7 5 +3 3 +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/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 8ac856857eb..b515ea39f9e 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -4622,6 +4622,13 @@ CREATE TABLE t1(a1 int); INSERT INTO t1 VALUES (1),(2); SELECT @@session.sql_mode INTO @old_sql_mode; SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select 1 AS `1` from `test`.`t1` where ((1,((select max(`test`.`t1`.`a1`) from `test`.`t1`) > 1))) SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); 1 1 @@ -5324,7 +5331,6 @@ EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, WHERE t1.a = d1.a; ERROR 42S22: Unknown column 'd1.a' in 'where clause' DROP TABLE t1; -End of 5.1 tests. Set up test tables. CREATE TABLE t1 ( t1_id INT UNSIGNED, @@ -5848,10 +5854,159 @@ NULL NULL 5 DROP TABLE t1, t2, t3; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; +# +# BUG#50257: Missing info in REF column of the EXPLAIN +# lines for subselects +# +CREATE TABLE t1 (a INT, b INT, INDEX (a)); +INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20); +EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 5 const 1 +EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +2 SUBQUERY t1 ref a a 5 const 1 Using index +DROP TABLE t1; +# +# BUG#12616253 - WRONG RESULT WITH EXISTS(SUBQUERY) (MISSING ROWS) +# (duplicate of LP bug #888456) +# +CREATE TABLE t1 (f1 varchar(1)); +INSERT INTO t1 VALUES ('v'),('s'); +CREATE TABLE t2 (f1_key varchar(1), KEY (f1_key)); +INSERT INTO t2 VALUES ('j'),('v'),('c'),('m'),('d'), +('d'),('y'),('t'),('d'),('s'); +EXPLAIN +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY table1 ALL NULL NULL NULL NULL 2 +1 PRIMARY table2 index NULL f1_key 4 NULL 10 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index f1_key f1_key 4 NULL 10 Using where; Using index +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +f1 f1_key +v j +s j +v v +s v +v c +s c +v m +s m +v d +s d +v d +s d +v y +s y +v t +s t +v d +s d +v s +s s +DROP TABLE t1,t2; +# +# LP bug 919427: EXPLAIN for a query over a single-row table +# with IN subquery in WHERE condition +# +CREATE TABLE ot ( +col_int_nokey int(11), +col_varchar_nokey varchar(1) +) ; +INSERT INTO ot VALUES (1,'x'); +CREATE TABLE it1( +col_int_key int(11), +col_varchar_key varchar(1), +KEY idx_cvk_cik (col_varchar_key,col_int_key) +); +INSERT INTO it1 VALUES (NULL,'x'), (NULL,'f'); +CREATE TABLE it2 ( +col_int_key int(11), +col_varchar_key varchar(1), +col_varchar_key2 varchar(1), +KEY idx_cvk_cvk2_cik (col_varchar_key, col_varchar_key2, col_int_key), +KEY idx_cvk_cik (col_varchar_key, col_int_key) +); +INSERT INTO it2 VALUES (NULL,'x','x'), (NULL,'f','f'); +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +1 PRIMARY it1 ref idx_cvk_cik idx_cvk_cik 9 const,const 1 Using where; Using index; FirstMatch(ot) +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +col_int_nokey +1 +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +1 PRIMARY it2 ref idx_cvk_cvk2_cik,idx_cvk_cik idx_cvk_cvk2_cik 8 const,const 1 Using where; Using index; FirstMatch(ot) +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +col_int_nokey +1 +DROP TABLE ot,it1,it2; End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in -# maria-5.3 # CREATE TABLE t1 ( f1 int ); INSERT INTO t1 VALUES (19), (20); @@ -5898,32 +6053,6 @@ b c 9 NULL SET optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; -End of 5.3 tests -# -# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER -# -CREATE TABLE t1(a1 int); -INSERT INTO t1 VALUES (1),(2); -CREATE TABLE t2(a1 int); -INSERT INTO t2 VALUES (3); -SELECT @@session.sql_mode INTO @old_sql_mode; -SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); -1 -1 -1 -SET SESSION sql_mode=@old_sql_mode; -DROP TABLE t1, t2; # # BUG#50257: Missing info in REF column of the EXPLAIN # lines for subselects @@ -5946,6 +6075,54 @@ id select_type table type possible_keys key key_len ref rows Extra DROP TABLE t1; # +# Bug#11764086: Null left operand to NOT IN in WHERE clause +# behaves differently than real NULL +# +CREATE TABLE parent (id int); +INSERT INTO parent VALUES (1), (2); +CREATE TABLE child (parent_id int, other int); +INSERT INTO child VALUES (1,NULL); +# Offending query (c.parent_id is NULL for null-complemented rows only) +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id NOT IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +); +id parent_id +1 1 +2 NULL +# Some syntactic variations with IS FALSE and IS NOT TRUE +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS NOT TRUE; +id parent_id +1 1 +2 NULL +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS FALSE; +id parent_id +1 1 +2 NULL +DROP TABLE parent, child; +# End of test for bug#11764086. +# # Bug 11765699 - 58690: !TABLE || (!TABLE->READ_SET || # BITMAP_IS_SET(TABLE->READ_SET, FIELD_INDEX # @@ -6284,6 +6461,15 @@ SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1; 1 NULL drop table t1,t2,t3; +# +# LP BUG#905353 Wrong non-empty result with a constant table, +# aggregate function in subquery, MyISAM or Aria +# +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); +a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 518f9366b80..c50ee1bac69 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -4618,6 +4618,13 @@ CREATE TABLE t1(a1 int); INSERT INTO t1 VALUES (1),(2); SELECT @@session.sql_mode INTO @old_sql_mode; SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select 1 AS `1` from `test`.`t1` where ((1,((select max(`test`.`t1`.`a1`) from `test`.`t1`) > 1))) SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); 1 1 @@ -5320,7 +5327,6 @@ EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, WHERE t1.a = d1.a; ERROR 42S22: Unknown column 'd1.a' in 'where clause' DROP TABLE t1; -End of 5.1 tests. Set up test tables. CREATE TABLE t1 ( t1_id INT UNSIGNED, @@ -5844,10 +5850,159 @@ NULL NULL 5 DROP TABLE t1, t2, t3; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; +# +# BUG#50257: Missing info in REF column of the EXPLAIN +# lines for subselects +# +CREATE TABLE t1 (a INT, b INT, INDEX (a)); +INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20); +EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 5 const 1 +EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +2 SUBQUERY t1 ref a a 5 const 1 Using index +DROP TABLE t1; +# +# BUG#12616253 - WRONG RESULT WITH EXISTS(SUBQUERY) (MISSING ROWS) +# (duplicate of LP bug #888456) +# +CREATE TABLE t1 (f1 varchar(1)); +INSERT INTO t1 VALUES ('v'),('s'); +CREATE TABLE t2 (f1_key varchar(1), KEY (f1_key)); +INSERT INTO t2 VALUES ('j'),('v'),('c'),('m'),('d'), +('d'),('y'),('t'),('d'),('s'); +EXPLAIN +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY table1 ALL NULL NULL NULL NULL 2 +1 PRIMARY table2 index NULL f1_key 4 NULL 10 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index f1_key f1_key 4 NULL 10 Using where; Using index +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +f1 f1_key +v j +s j +v v +s v +v c +s c +v m +s m +v d +s d +v d +s d +v y +s y +v t +s t +v d +s d +v s +s s +DROP TABLE t1,t2; +# +# LP bug 919427: EXPLAIN for a query over a single-row table +# with IN subquery in WHERE condition +# +CREATE TABLE ot ( +col_int_nokey int(11), +col_varchar_nokey varchar(1) +) ; +INSERT INTO ot VALUES (1,'x'); +CREATE TABLE it1( +col_int_key int(11), +col_varchar_key varchar(1), +KEY idx_cvk_cik (col_varchar_key,col_int_key) +); +INSERT INTO it1 VALUES (NULL,'x'), (NULL,'f'); +CREATE TABLE it2 ( +col_int_key int(11), +col_varchar_key varchar(1), +col_varchar_key2 varchar(1), +KEY idx_cvk_cvk2_cik (col_varchar_key, col_varchar_key2, col_int_key), +KEY idx_cvk_cik (col_varchar_key, col_int_key) +); +INSERT INTO it2 VALUES (NULL,'x','x'), (NULL,'f','f'); +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY it1 index_subquery idx_cvk_cik idx_cvk_cik 9 func,const 2 Using index; Using where +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +col_int_nokey +1 +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY it2 index_subquery idx_cvk_cvk2_cik,idx_cvk_cik idx_cvk_cvk2_cik 8 func,const 1 Using index; Using where +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +col_int_nokey +1 +DROP TABLE ot,it1,it2; End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in -# maria-5.3 # CREATE TABLE t1 ( f1 int ); INSERT INTO t1 VALUES (19), (20); @@ -5894,32 +6049,6 @@ b c 9 NULL SET optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; -End of 5.3 tests -# -# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER -# -CREATE TABLE t1(a1 int); -INSERT INTO t1 VALUES (1),(2); -CREATE TABLE t2(a1 int); -INSERT INTO t2 VALUES (3); -SELECT @@session.sql_mode INTO @old_sql_mode; -SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); -1 -1 -1 -SET SESSION sql_mode=@old_sql_mode; -DROP TABLE t1, t2; # # BUG#50257: Missing info in REF column of the EXPLAIN # lines for subselects @@ -5942,6 +6071,54 @@ id select_type table type possible_keys key key_len ref rows Extra DROP TABLE t1; # +# Bug#11764086: Null left operand to NOT IN in WHERE clause +# behaves differently than real NULL +# +CREATE TABLE parent (id int); +INSERT INTO parent VALUES (1), (2); +CREATE TABLE child (parent_id int, other int); +INSERT INTO child VALUES (1,NULL); +# Offending query (c.parent_id is NULL for null-complemented rows only) +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id NOT IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +); +id parent_id +1 1 +2 NULL +# Some syntactic variations with IS FALSE and IS NOT TRUE +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS NOT TRUE; +id parent_id +1 1 +2 NULL +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS FALSE; +id parent_id +1 1 +2 NULL +DROP TABLE parent, child; +# End of test for bug#11764086. +# # Bug 11765699 - 58690: !TABLE || (!TABLE->READ_SET || # BITMAP_IS_SET(TABLE->READ_SET, FIELD_INDEX # @@ -6280,6 +6457,15 @@ SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1; 1 NULL drop table t1,t2,t3; +# +# LP BUG#905353 Wrong non-empty result with a constant table, +# aggregate function in subquery, MyISAM or Aria +# +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); +a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index 320e51da39e..3e2305ebe73 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -4626,6 +4626,13 @@ CREATE TABLE t1(a1 int); INSERT INTO t1 VALUES (1),(2); SELECT @@session.sql_mode INTO @old_sql_mode; SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select 1 AS `1` from `test`.`t1` where ((1,((select max(`test`.`t1`.`a1`) from `test`.`t1`) > 1))) SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); 1 1 @@ -5328,7 +5335,6 @@ EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, WHERE t1.a = d1.a; ERROR 42S22: Unknown column 'd1.a' in 'where clause' DROP TABLE t1; -End of 5.1 tests. Set up test tables. CREATE TABLE t1 ( t1_id INT UNSIGNED, @@ -5853,10 +5859,161 @@ NULL NULL 5 DROP TABLE t1, t2, t3; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; +# +# BUG#50257: Missing info in REF column of the EXPLAIN +# lines for subselects +# +CREATE TABLE t1 (a INT, b INT, INDEX (a)); +INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20); +EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 5 const 1 +EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +2 SUBQUERY t1 ref a a 5 const 1 Using index +DROP TABLE t1; +# +# BUG#12616253 - WRONG RESULT WITH EXISTS(SUBQUERY) (MISSING ROWS) +# (duplicate of LP bug #888456) +# +CREATE TABLE t1 (f1 varchar(1)); +INSERT INTO t1 VALUES ('v'),('s'); +CREATE TABLE t2 (f1_key varchar(1), KEY (f1_key)); +INSERT INTO t2 VALUES ('j'),('v'),('c'),('m'),('d'), +('d'),('y'),('t'),('d'),('s'); +EXPLAIN +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY table1 ALL NULL NULL NULL NULL 2 +1 PRIMARY table2 index NULL f1_key 4 NULL 10 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index f1_key f1_key 4 NULL 10 Using where; Using index +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +f1 f1_key +v j +s j +v v +s v +v c +s c +v m +s m +v d +s d +v d +s d +v y +s y +v t +s t +v d +s d +v s +s s +DROP TABLE t1,t2; +# +# LP bug 919427: EXPLAIN for a query over a single-row table +# with IN subquery in WHERE condition +# +CREATE TABLE ot ( +col_int_nokey int(11), +col_varchar_nokey varchar(1) +) ; +INSERT INTO ot VALUES (1,'x'); +CREATE TABLE it1( +col_int_key int(11), +col_varchar_key varchar(1), +KEY idx_cvk_cik (col_varchar_key,col_int_key) +); +INSERT INTO it1 VALUES (NULL,'x'), (NULL,'f'); +CREATE TABLE it2 ( +col_int_key int(11), +col_varchar_key varchar(1), +col_varchar_key2 varchar(1), +KEY idx_cvk_cvk2_cik (col_varchar_key, col_varchar_key2, col_int_key), +KEY idx_cvk_cik (col_varchar_key, col_int_key) +); +INSERT INTO it2 VALUES (NULL,'x','x'), (NULL,'f','f'); +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +1 PRIMARY eq_ref distinct_key distinct_key 5 func 1 +2 MATERIALIZED it1 ref idx_cvk_cik idx_cvk_cik 9 const,const 1 Using where; Using index +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +col_int_nokey +1 +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +1 PRIMARY eq_ref distinct_key distinct_key 10 func,func 1 +2 MATERIALIZED it2 ref idx_cvk_cvk2_cik,idx_cvk_cik idx_cvk_cvk2_cik 8 const,const 1 Using where; Using index +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +col_int_nokey +1 +DROP TABLE ot,it1,it2; End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in -# maria-5.3 # CREATE TABLE t1 ( f1 int ); INSERT INTO t1 VALUES (19), (20); @@ -5903,32 +6060,6 @@ b c 9 NULL SET optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; -End of 5.3 tests -# -# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER -# -CREATE TABLE t1(a1 int); -INSERT INTO t1 VALUES (1),(2); -CREATE TABLE t2(a1 int); -INSERT INTO t2 VALUES (3); -SELECT @@session.sql_mode INTO @old_sql_mode; -SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); -1 -1 -1 -SET SESSION sql_mode=@old_sql_mode; -DROP TABLE t1, t2; # # BUG#50257: Missing info in REF column of the EXPLAIN # lines for subselects @@ -5951,6 +6082,54 @@ id select_type table type possible_keys key key_len ref rows Extra DROP TABLE t1; # +# Bug#11764086: Null left operand to NOT IN in WHERE clause +# behaves differently than real NULL +# +CREATE TABLE parent (id int); +INSERT INTO parent VALUES (1), (2); +CREATE TABLE child (parent_id int, other int); +INSERT INTO child VALUES (1,NULL); +# Offending query (c.parent_id is NULL for null-complemented rows only) +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id NOT IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +); +id parent_id +1 1 +2 NULL +# Some syntactic variations with IS FALSE and IS NOT TRUE +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS NOT TRUE; +id parent_id +1 1 +2 NULL +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS FALSE; +id parent_id +1 1 +2 NULL +DROP TABLE parent, child; +# End of test for bug#11764086. +# # Bug 11765699 - 58690: !TABLE || (!TABLE->READ_SET || # BITMAP_IS_SET(TABLE->READ_SET, FIELD_INDEX # @@ -6289,6 +6468,15 @@ SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1; 1 NULL drop table t1,t2,t3; +# +# LP BUG#905353 Wrong non-empty result with a constant table, +# aggregate function in subquery, MyISAM or Aria +# +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); +a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 0c41f612ae9..47368b1eca7 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -4618,6 +4618,13 @@ CREATE TABLE t1(a1 int); INSERT INTO t1 VALUES (1),(2); SELECT @@session.sql_mode INTO @old_sql_mode; SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select 1 AS `1` from `test`.`t1` where ((1,((select max(`test`.`t1`.`a1`) from `test`.`t1`) > 1))) SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); 1 1 @@ -5320,7 +5327,6 @@ EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1, WHERE t1.a = d1.a; ERROR 42S22: Unknown column 'd1.a' in 'where clause' DROP TABLE t1; -End of 5.1 tests. Set up test tables. CREATE TABLE t1 ( t1_id INT UNSIGNED, @@ -5844,10 +5850,159 @@ NULL NULL 5 DROP TABLE t1, t2, t3; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; +# +# BUG#50257: Missing info in REF column of the EXPLAIN +# lines for subselects +# +CREATE TABLE t1 (a INT, b INT, INDEX (a)); +INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20); +EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 5 const 1 +EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +2 SUBQUERY t1 ref a a 5 const 1 Using index +DROP TABLE t1; +# +# BUG#12616253 - WRONG RESULT WITH EXISTS(SUBQUERY) (MISSING ROWS) +# (duplicate of LP bug #888456) +# +CREATE TABLE t1 (f1 varchar(1)); +INSERT INTO t1 VALUES ('v'),('s'); +CREATE TABLE t2 (f1_key varchar(1), KEY (f1_key)); +INSERT INTO t2 VALUES ('j'),('v'),('c'),('m'),('d'), +('d'),('y'),('t'),('d'),('s'); +EXPLAIN +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY table1 ALL NULL NULL NULL NULL 2 +1 PRIMARY table2 index NULL f1_key 4 NULL 10 Using where; Using index; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t2 index f1_key f1_key 4 NULL 10 Using where; Using index +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 +WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 +WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +f1 f1_key +v j +s j +v v +s v +v c +s c +v m +s m +v d +s d +v d +s d +v y +s y +v t +s t +v d +s d +v s +s s +DROP TABLE t1,t2; +# +# LP bug 919427: EXPLAIN for a query over a single-row table +# with IN subquery in WHERE condition +# +CREATE TABLE ot ( +col_int_nokey int(11), +col_varchar_nokey varchar(1) +) ; +INSERT INTO ot VALUES (1,'x'); +CREATE TABLE it1( +col_int_key int(11), +col_varchar_key varchar(1), +KEY idx_cvk_cik (col_varchar_key,col_int_key) +); +INSERT INTO it1 VALUES (NULL,'x'), (NULL,'f'); +CREATE TABLE it2 ( +col_int_key int(11), +col_varchar_key varchar(1), +col_varchar_key2 varchar(1), +KEY idx_cvk_cvk2_cik (col_varchar_key, col_varchar_key2, col_int_key), +KEY idx_cvk_cik (col_varchar_key, col_int_key) +); +INSERT INTO it2 VALUES (NULL,'x','x'), (NULL,'f','f'); +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY it1 index_subquery idx_cvk_cik idx_cvk_cik 9 func,const 2 Using index; Using where +SELECT col_int_nokey FROM ot +WHERE col_varchar_nokey IN +(SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +col_int_nokey +1 +EXPLAIN +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot system NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY it2 index_subquery idx_cvk_cvk2_cik,idx_cvk_cik idx_cvk_cvk2_cik 8 func,const 1 Using index; Using where +SELECT col_int_nokey FROM ot +WHERE (col_varchar_nokey, 'x') IN +(SELECT col_varchar_key, col_varchar_key2 FROM it2); +col_int_nokey +1 +DROP TABLE ot,it1,it2; End of 5.2 tests # # BUG#779885: Crash in eliminate_item_equal with materialization=on in -# maria-5.3 # CREATE TABLE t1 ( f1 int ); INSERT INTO t1 VALUES (19), (20); @@ -5894,32 +6049,6 @@ b c 9 NULL SET optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; -End of 5.3 tests -# -# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER -# -CREATE TABLE t1(a1 int); -INSERT INTO t1 VALUES (1),(2); -CREATE TABLE t2(a1 int); -INSERT INTO t2 VALUES (3); -SELECT @@session.sql_mode INTO @old_sql_mode; -SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); -1 -1 -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); -1 -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); -1 -1 -1 -SET SESSION sql_mode=@old_sql_mode; -DROP TABLE t1, t2; # # BUG#50257: Missing info in REF column of the EXPLAIN # lines for subselects @@ -5942,6 +6071,54 @@ id select_type table type possible_keys key key_len ref rows Extra DROP TABLE t1; # +# Bug#11764086: Null left operand to NOT IN in WHERE clause +# behaves differently than real NULL +# +CREATE TABLE parent (id int); +INSERT INTO parent VALUES (1), (2); +CREATE TABLE child (parent_id int, other int); +INSERT INTO child VALUES (1,NULL); +# Offending query (c.parent_id is NULL for null-complemented rows only) +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id NOT IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +); +id parent_id +1 1 +2 NULL +# Some syntactic variations with IS FALSE and IS NOT TRUE +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS NOT TRUE; +id parent_id +1 1 +2 NULL +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( +SELECT parent_id +FROM child +WHERE parent_id = 3 +) IS FALSE; +id parent_id +1 1 +2 NULL +DROP TABLE parent, child; +# End of test for bug#11764086. +# # Bug 11765699 - 58690: !TABLE || (!TABLE->READ_SET || # BITMAP_IS_SET(TABLE->READ_SET, FIELD_INDEX # @@ -6280,6 +6457,15 @@ SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1; 1 NULL drop table t1,t2,t3; +# +# LP BUG#905353 Wrong non-empty result with a constant table, +# aggregate function in subquery, MyISAM or Aria +# +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); +a +drop table t1; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 8fcedc5807f..3bc1d1f4293 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -1231,6 +1231,364 @@ IN (SELECT t3.pk, t3.pk FROM t2 LEFT JOIN t3 ON t3.varchar_key) AND pk = 9; datetime_key DROP TABLE t1, t2, t3; +# +# BUG#53060: LooseScan semijoin strategy does not return all rows +# +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=on,materialization=off'; +set optimizer_switch='firstmatch=off,loosescan=on'; +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +CREATE TABLE t2 (i INTEGER, j INTEGER, KEY k(i, j)); +INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1); +EXPLAIN +SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0); +i +1 +2 +DROP TABLE t1, t2; +set optimizer_switch=@save_optimizer_switch; +# +# BUG#49453: re-execution of prepared statement with view +# and semijoin crashes +# +CREATE TABLE t1 (city VARCHAR(50), country_id INT); +CREATE TABLE t2 (country_id INT, country VARCHAR(50)); +INSERT INTO t1 VALUES +('Batna',2),('Bchar',2),('Skikda',2),('Tafuna',3),('Algeria',2) ; +INSERT INTO t2 VALUES (2,'Algeria'),(2,'AlgeriaDup'),(3,'XAmerican Samoa'); +CREATE VIEW v1 AS +SELECT country_id as vf_country_id +FROM t2 +WHERE LEFT(country,1) = "A"; +PREPARE stmt FROM " +SELECT city, country_id +FROM t1 +WHERE country_id IN (SELECT vf_country_id FROM v1); +"; + +EXECUTE stmt; +city country_id +Batna 2 +Bchar 2 +Skikda 2 +Algeria 2 +EXECUTE stmt; +city country_id +Batna 2 +Bchar 2 +Skikda 2 +Algeria 2 +DROP TABLE t1,t2; +DROP VIEW v1; +# +# Bug#54437 Extra rows with LEFT JOIN + semijoin +# +create table t1 (a int); +create table t2 (a int); +create table t3 (a int); +insert into t1 values(1),(1); +insert into t2 values(1),(1),(1),(1); +insert into t3 values(2),(2); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='materialization=off'; +set optimizer_switch='semijoin=off'; +explain +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +a +1 +1 +set optimizer_switch='semijoin=on'; +explain +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Start temporary +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +a +1 +1 +set optimizer_switch=@save_optimizer_switch; +drop table t1,t2,t3; +# +# Bug#55955: crash in MEMORY engine with IN(LEFT JOIN (JOIN)) +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +INSERT INTO t1 VALUES(1),(1); +INSERT INTO t2 VALUES(1),(1); +INSERT INTO t3 VALUES(2),(2); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off,materialization=off'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2inner ALL NULL NULL NULL NULL 2 +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +a +1 +1 +set optimizer_switch='semijoin=off,materialization=on'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 +2 MATERIALIZED t2inner ALL NULL NULL NULL NULL 2 +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +a +1 +1 +set optimizer_switch='semijoin=on,materialization=off'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary +1 PRIMARY t2inner ALL NULL NULL NULL NULL 2 +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +a +1 +1 +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t2,t3; +# +# BUG#52329 - Wrong result: subquery materialization, IN, +# non-null field followed by nullable +# +CREATE TABLE t1 (a1 CHAR(8) NOT NULL, a2 char(8) NOT NULL); +CREATE TABLE t2a (b1 char(8), b2 char(8)); +CREATE TABLE t2b (b1 CHAR(8), b2 char(8) NOT NULL); +CREATE TABLE t2c (b1 CHAR(8) NOT NULL, b2 char(8)); +INSERT INTO t1 VALUES ('1 - 12', '2 - 22'); +INSERT INTO t2a VALUES ('1 - 11', '2 - 21'), +('1 - 11', '2 - 21'), +('1 - 12', '2 - 22'), +('1 - 12', '2 - 22'), +('1 - 13', '2 - 23'); +INSERT INTO t2b SELECT * FROM t2a; +INSERT INTO t2c SELECT * FROM t2a; +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off,materialization=on'; +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2c WHERE b1 > '0' GROUP BY b1, b2); +a1 a2 +1 - 12 2 - 22 +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2a WHERE b1 > '0'); +a1 a2 +1 - 12 2 - 22 +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2b WHERE b1 > '0'); +a1 a2 +1 - 12 2 - 22 +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2c WHERE b1 > '0'); +a1 a2 +1 - 12 2 - 22 +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t2a,t2b,t2c; +# +# Bug#57623: subquery within before insert trigger causes crash (sj=on) +# +CREATE TABLE ot1(a INT); +CREATE TABLE ot2(a INT); +CREATE TABLE ot3(a INT); +CREATE TABLE it1(a INT); +INSERT INTO ot1 VALUES(0),(1),(2),(3),(4),(5),(6),(7); +INSERT INTO ot2 VALUES(0),(2),(4),(6); +INSERT INTO ot3 VALUES(0),(3),(6); +INSERT INTO it1 VALUES(0),(1),(2),(3),(4),(5),(6),(7); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=on'; +set optimizer_switch='materialization=off'; +explain SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot1 ALL NULL NULL NULL NULL 8 +1 PRIMARY ot3 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY ot2 ALL NULL NULL NULL NULL 4 Using where +2 DEPENDENT SUBQUERY it1 ALL NULL NULL NULL NULL 8 Using where +SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +a a a +0 0 0 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +6 6 6 +7 NULL NULL +prepare s from 'SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1)'; +execute s; +a a a +0 0 0 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +6 6 6 +7 NULL NULL +execute s; +a a a +0 0 0 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +6 6 6 +7 NULL NULL +deallocate prepare s; +set optimizer_switch='materialization=on'; +explain SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot1 ALL NULL NULL NULL NULL 8 +1 PRIMARY ot3 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY ot2 ALL NULL NULL NULL NULL 4 Using where +2 MATERIALIZED it1 ALL NULL NULL NULL NULL 8 +SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +a a a +0 0 0 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +6 6 6 +7 NULL NULL +prepare s from 'SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1)'; +execute s; +a a a +0 0 0 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +6 6 6 +7 NULL NULL +execute s; +a a a +0 0 0 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +6 6 6 +7 NULL NULL +deallocate prepare s; +set optimizer_switch=@save_optimizer_switch; +DROP TABLE ot1, ot2, ot3, it1; +# +# Bug#59919/11766739: Crash in tmp_table_param::init() with semijoin=on +# +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER, f2 INTEGER) ENGINE=MyISAM; +CREATE TABLE t3 (f1 INTEGER, f2 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1,1), (2,1); +INSERT INTO t3 VALUES +(1,1), (2,1), (5,4), (7,3), (8,2), (8,1), (7,3), +(9,5), (4,3), (7,2), (7,7), (3,1), (5,8), (9,7); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off,materialization=on'; +EXPLAIN +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 14 Using where +2 MATERIALIZED t1 system NULL NULL NULL NULL 1 +2 MATERIALIZED b1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED b2 ALL NULL NULL NULL NULL 2 +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +f1 f2 +1 1 +2 1 +8 1 +3 1 +set optimizer_switch='semijoin=on,materialization=on'; +EXPLAIN +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +1 PRIMARY ALL distinct_key NULL NULL NULL 1 +1 PRIMARY t3 ALL NULL NULL NULL NULL 14 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED b1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED b2 ALL NULL NULL NULL NULL 2 +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +f1 f2 +1 1 +2 1 +8 1 +3 1 +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1, t2, t3 ; +# # # BUG#784723: Wrong result with semijoin + nested subqueries in maria-5.3 # @@ -2179,4 +2537,105 @@ WHERE c = b AND b = a a COUNT(*) NULL 0 DROP TABLE t1, t2, t3; +# +# BUG#920255: Wrong result (extra rows) with loosescan and IN subquery +# +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, KEY(b) ); +INSERT INTO t1 VALUES +(1,2),(2,1),(3,3),(4,2),(5,5), +(6,3),(7,1),(8,4),(9,3),(10,2); +CREATE TABLE t2 ( c INT, d INT, UNIQUE KEY(c) ); +INSERT INTO t2 VALUES +(1,2),(2,1),(3,3),(4,2),(5,5),(6,3),(7,1); +SELECT a, b, d FROM t1, t2 +WHERE ( b, d ) IN +( SELECT b, d FROM t1, t2 WHERE b = c ); +a b d +2 1 2 +7 1 2 +2 1 2 +7 1 2 +1 2 1 +4 2 1 +10 2 1 +1 2 1 +4 2 1 +10 2 1 +3 3 3 +6 3 3 +9 3 3 +3 3 3 +6 3 3 +9 3 3 +8 4 2 +8 4 2 +5 5 5 +DROP TABLE t1, t2; +# +# BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ... +# +CREATE TABLE t1 ( a VARCHAR(1) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('e'),('w'),('a'),('h'),('x'),('k'),('g'); +CREATE TABLE t2 ( b INT, c VARCHAR(1) ); +INSERT INTO t2 VALUES (0,'j'),(8,'v'); +SELECT * FROM t1 alias1, t2 alias2 +WHERE alias2.c IN ( +SELECT alias4.c FROM t1 alias3, t2 alias4 +); +a b c +e 0 j +e 8 v +w 0 j +w 8 v +a 0 j +a 8 v +h 0 j +h 8 v +x 0 j +x 8 v +k 0 j +k 8 v +g 0 j +g 8 v +DROP TABLE t1, t2; +# +# BUG#923246: Loosescan reports different result than other semijoin methods +# +set @tmp_923246= @@optimizer_switch; +set optimizer_switch='mrr=on,materialization=off'; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (kp1 int, kp2 int, c int, filler char(100), key(kp1, kp2)); +insert into t1 select A.a+10*(B.a+10*C.a), 0, 0, 'filler' from t0 A, t0 B, t0 C; +insert into t1 select * from t1 where kp1 < 20; +create table t3 (a int); +insert into t3 select A.a + 10*B.a from t0 A, t0 B; +select * from t3 where a in (select kp1 from t1 where kp1<20); +a +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +explain select * from t3 where a in (select kp1 from t1 where kp1<20); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan +1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) +drop table t0,t1,t3; +set optimizer_switch= @tmp_923246; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result index 85a3b6971bd..2d8c189942e 100644 --- a/mysql-test/r/subselect_sj2.result +++ b/mysql-test/r/subselect_sj2.result @@ -886,5 +886,19 @@ a b b a c c NULL NULL DROP VIEW v1; DROP TABLE t1,t2,t3,t4; +# +# BUG#912538: Wrong result (missing rows) with semijoin=on, firstmatch=on, ... +# +CREATE TABLE t1 ( a INT NOT NULL, UNIQUE KEY(a) ); +INSERT INTO t1 VALUES (1),(2),(3),(4); +CREATE TABLE t2 ( b INT, c INT ) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1); +SELECT * FROM t1, t2 WHERE c IN (SELECT c FROM t1, t2 WHERE a = b); +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +DROP TABLE t1,t2; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result index b179a735f20..f2895662196 100644 --- a/mysql-test/r/subselect_sj2_jcl6.result +++ b/mysql-test/r/subselect_sj2_jcl6.result @@ -900,6 +900,20 @@ a b b a c c NULL NULL DROP VIEW v1; DROP TABLE t1,t2,t3,t4; +# +# BUG#912538: Wrong result (missing rows) with semijoin=on, firstmatch=on, ... +# +CREATE TABLE t1 ( a INT NOT NULL, UNIQUE KEY(a) ); +INSERT INTO t1 VALUES (1),(2),(3),(4); +CREATE TABLE t2 ( b INT, c INT ) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1); +SELECT * FROM t1, t2 WHERE c IN (SELECT c FROM t1, t2 WHERE a = b); +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +DROP TABLE t1,t2; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; # @@ -921,9 +935,9 @@ SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b WHERE c IN (SELECT t4.b FROM t4 JOIN t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where -1 PRIMARY t2 ALL NULL NULL NULL NULL 1 +1 PRIMARY t2 ALL NULL NULL NULL NULL 1 FirstMatch(t3) 1 PRIMARY t1 ref b b 4 test.t3.b 1 Using index -1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t2) +1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t1) SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b WHERE c IN (SELECT t4.b FROM t4 JOIN t2); b c @@ -949,12 +963,13 @@ EXPLAIN SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 -1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where +1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2) 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t4) +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t1) SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk); pk a b 1 6 8 +2 8 8 set optimizer_switch=@tmp_optimizer_switch; set join_cache_level=default; DROP TABLE t1,t2,t3,t4; diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index 0284bab0972..3e68c9ebeb5 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -888,6 +888,20 @@ a b b a c c NULL NULL DROP VIEW v1; DROP TABLE t1,t2,t3,t4; +# +# BUG#912538: Wrong result (missing rows) with semijoin=on, firstmatch=on, ... +# +CREATE TABLE t1 ( a INT NOT NULL, UNIQUE KEY(a) ); +INSERT INTO t1 VALUES (1),(2),(3),(4); +CREATE TABLE t2 ( b INT, c INT ) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1); +SELECT * FROM t1, t2 WHERE c IN (SELECT c FROM t1, t2 WHERE a = b); +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +DROP TABLE t1,t2; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 88acba0ebea..8bb262af7ca 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -1244,6 +1244,364 @@ IN (SELECT t3.pk, t3.pk FROM t2 LEFT JOIN t3 ON t3.varchar_key) AND pk = 9; datetime_key DROP TABLE t1, t2, t3; +# +# BUG#53060: LooseScan semijoin strategy does not return all rows +# +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=on,materialization=off'; +set optimizer_switch='firstmatch=off,loosescan=on'; +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +CREATE TABLE t2 (i INTEGER, j INTEGER, KEY k(i, j)); +INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1); +EXPLAIN +SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0); +i +1 +2 +DROP TABLE t1, t2; +set optimizer_switch=@save_optimizer_switch; +# +# BUG#49453: re-execution of prepared statement with view +# and semijoin crashes +# +CREATE TABLE t1 (city VARCHAR(50), country_id INT); +CREATE TABLE t2 (country_id INT, country VARCHAR(50)); +INSERT INTO t1 VALUES +('Batna',2),('Bchar',2),('Skikda',2),('Tafuna',3),('Algeria',2) ; +INSERT INTO t2 VALUES (2,'Algeria'),(2,'AlgeriaDup'),(3,'XAmerican Samoa'); +CREATE VIEW v1 AS +SELECT country_id as vf_country_id +FROM t2 +WHERE LEFT(country,1) = "A"; +PREPARE stmt FROM " +SELECT city, country_id +FROM t1 +WHERE country_id IN (SELECT vf_country_id FROM v1); +"; + +EXECUTE stmt; +city country_id +Batna 2 +Bchar 2 +Skikda 2 +Algeria 2 +EXECUTE stmt; +city country_id +Batna 2 +Bchar 2 +Skikda 2 +Algeria 2 +DROP TABLE t1,t2; +DROP VIEW v1; +# +# Bug#54437 Extra rows with LEFT JOIN + semijoin +# +create table t1 (a int); +create table t2 (a int); +create table t3 (a int); +insert into t1 values(1),(1); +insert into t2 values(1),(1),(1),(1); +insert into t3 values(2),(2); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='materialization=off'; +set optimizer_switch='semijoin=off'; +explain +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +a +1 +1 +set optimizer_switch='semijoin=on'; +explain +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (incremental, BNL join) +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +a +1 +1 +set optimizer_switch=@save_optimizer_switch; +drop table t1,t2,t3; +# +# Bug#55955: crash in MEMORY engine with IN(LEFT JOIN (JOIN)) +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +INSERT INTO t1 VALUES(1),(1); +INSERT INTO t2 VALUES(1),(1); +INSERT INTO t3 VALUES(2),(2); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off,materialization=off'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY t2inner ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (incremental, BNL join) +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +a +1 +1 +set optimizer_switch='semijoin=off,materialization=on'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 +2 MATERIALIZED t2inner ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (incremental, BNL join) +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +a +1 +1 +set optimizer_switch='semijoin=on,materialization=off'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary; Using join buffer (flat, BNL join) +1 PRIMARY t2inner ALL NULL NULL NULL NULL 2 Using join buffer (incremental, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (incremental, BNL join) +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a +FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +a +1 +1 +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t2,t3; +# +# BUG#52329 - Wrong result: subquery materialization, IN, +# non-null field followed by nullable +# +CREATE TABLE t1 (a1 CHAR(8) NOT NULL, a2 char(8) NOT NULL); +CREATE TABLE t2a (b1 char(8), b2 char(8)); +CREATE TABLE t2b (b1 CHAR(8), b2 char(8) NOT NULL); +CREATE TABLE t2c (b1 CHAR(8) NOT NULL, b2 char(8)); +INSERT INTO t1 VALUES ('1 - 12', '2 - 22'); +INSERT INTO t2a VALUES ('1 - 11', '2 - 21'), +('1 - 11', '2 - 21'), +('1 - 12', '2 - 22'), +('1 - 12', '2 - 22'), +('1 - 13', '2 - 23'); +INSERT INTO t2b SELECT * FROM t2a; +INSERT INTO t2c SELECT * FROM t2a; +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off,materialization=on'; +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2c WHERE b1 > '0' GROUP BY b1, b2); +a1 a2 +1 - 12 2 - 22 +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2a WHERE b1 > '0'); +a1 a2 +1 - 12 2 - 22 +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2b WHERE b1 > '0'); +a1 a2 +1 - 12 2 - 22 +SELECT * FROM t1 +WHERE (a1, a2) IN ( +SELECT b1, b2 FROM t2c WHERE b1 > '0'); +a1 a2 +1 - 12 2 - 22 +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t2a,t2b,t2c; +# +# Bug#57623: subquery within before insert trigger causes crash (sj=on) +# +CREATE TABLE ot1(a INT); +CREATE TABLE ot2(a INT); +CREATE TABLE ot3(a INT); +CREATE TABLE it1(a INT); +INSERT INTO ot1 VALUES(0),(1),(2),(3),(4),(5),(6),(7); +INSERT INTO ot2 VALUES(0),(2),(4),(6); +INSERT INTO ot3 VALUES(0),(3),(6); +INSERT INTO it1 VALUES(0),(1),(2),(3),(4),(5),(6),(7); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=on'; +set optimizer_switch='materialization=off'; +explain SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot1 ALL NULL NULL NULL NULL 8 +1 PRIMARY ot3 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +1 PRIMARY ot2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (incremental, BNL join) +2 DEPENDENT SUBQUERY it1 ALL NULL NULL NULL NULL 8 Using where +SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +a a a +0 0 0 +6 6 6 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +7 NULL NULL +prepare s from 'SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1)'; +execute s; +a a a +0 0 0 +6 6 6 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +7 NULL NULL +execute s; +a a a +0 0 0 +6 6 6 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +7 NULL NULL +deallocate prepare s; +set optimizer_switch='materialization=on'; +explain SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ot1 ALL NULL NULL NULL NULL 8 +1 PRIMARY ot3 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +1 PRIMARY ot2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (incremental, BNL join) +2 MATERIALIZED it1 ALL NULL NULL NULL NULL 8 +SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); +a a a +0 0 0 +6 6 6 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +7 NULL NULL +prepare s from 'SELECT * +FROM ot1 +LEFT JOIN +(ot2 JOIN ot3 on ot2.a=ot3.a) +ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1)'; +execute s; +a a a +0 0 0 +6 6 6 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +7 NULL NULL +execute s; +a a a +0 0 0 +6 6 6 +1 NULL NULL +2 NULL NULL +3 NULL NULL +4 NULL NULL +5 NULL NULL +7 NULL NULL +deallocate prepare s; +set optimizer_switch=@save_optimizer_switch; +DROP TABLE ot1, ot2, ot3, it1; +# +# Bug#59919/11766739: Crash in tmp_table_param::init() with semijoin=on +# +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER, f2 INTEGER) ENGINE=MyISAM; +CREATE TABLE t3 (f1 INTEGER, f2 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1,1), (2,1); +INSERT INTO t3 VALUES +(1,1), (2,1), (5,4), (7,3), (8,2), (8,1), (7,3), +(9,5), (4,3), (7,2), (7,7), (3,1), (5,8), (9,7); +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off,materialization=on'; +EXPLAIN +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 14 Using where +2 MATERIALIZED t1 system NULL NULL NULL NULL 1 +2 MATERIALIZED b1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED b2 ALL NULL NULL NULL NULL 2 +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +f1 f2 +1 1 +2 1 +8 1 +3 1 +set optimizer_switch='semijoin=on,materialization=on'; +EXPLAIN +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +1 PRIMARY ALL distinct_key NULL NULL NULL 1 +1 PRIMARY t3 ALL NULL NULL NULL NULL 14 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED b1 ALL NULL NULL NULL NULL 2 Using where +2 MATERIALIZED b2 ALL NULL NULL NULL NULL 2 +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 +FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +f1 f2 +1 1 +2 1 +8 1 +3 1 +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1, t2, t3 ; +# # # BUG#784723: Wrong result with semijoin + nested subqueries in maria-5.3 # @@ -2193,6 +2551,107 @@ WHERE c = b AND b = a a COUNT(*) NULL 0 DROP TABLE t1, t2, t3; +# +# BUG#920255: Wrong result (extra rows) with loosescan and IN subquery +# +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, KEY(b) ); +INSERT INTO t1 VALUES +(1,2),(2,1),(3,3),(4,2),(5,5), +(6,3),(7,1),(8,4),(9,3),(10,2); +CREATE TABLE t2 ( c INT, d INT, UNIQUE KEY(c) ); +INSERT INTO t2 VALUES +(1,2),(2,1),(3,3),(4,2),(5,5),(6,3),(7,1); +SELECT a, b, d FROM t1, t2 +WHERE ( b, d ) IN +( SELECT b, d FROM t1, t2 WHERE b = c ); +a b d +1 2 1 +1 2 1 +2 1 2 +2 1 2 +3 3 3 +3 3 3 +4 2 1 +4 2 1 +5 5 5 +6 3 3 +6 3 3 +7 1 2 +7 1 2 +8 4 2 +8 4 2 +9 3 3 +9 3 3 +10 2 1 +10 2 1 +DROP TABLE t1, t2; +# +# BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ... +# +CREATE TABLE t1 ( a VARCHAR(1) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('e'),('w'),('a'),('h'),('x'),('k'),('g'); +CREATE TABLE t2 ( b INT, c VARCHAR(1) ); +INSERT INTO t2 VALUES (0,'j'),(8,'v'); +SELECT * FROM t1 alias1, t2 alias2 +WHERE alias2.c IN ( +SELECT alias4.c FROM t1 alias3, t2 alias4 +); +a b c +e 0 j +e 8 v +w 0 j +w 8 v +a 0 j +a 8 v +h 0 j +h 8 v +x 0 j +x 8 v +k 0 j +k 8 v +g 0 j +g 8 v +DROP TABLE t1, t2; +# +# BUG#923246: Loosescan reports different result than other semijoin methods +# +set @tmp_923246= @@optimizer_switch; +set optimizer_switch='mrr=on,materialization=off'; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (kp1 int, kp2 int, c int, filler char(100), key(kp1, kp2)); +insert into t1 select A.a+10*(B.a+10*C.a), 0, 0, 'filler' from t0 A, t0 B, t0 C; +insert into t1 select * from t1 where kp1 < 20; +create table t3 (a int); +insert into t3 select A.a + 10*B.a from t0 A, t0 B; +select * from t3 where a in (select kp1 from t1 where kp1<20); +a +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +explain select * from t3 where a in (select kp1 from t1 where kp1<20); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan +1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) +drop table t0,t1,t3; +set optimizer_switch= @tmp_923246; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off @@ -2274,6 +2733,35 @@ w 5 19:11:10 set optimizer_switch=@save_optimizer_switch; set join_cache_level=default; DROP TABLE t1,t2,t3; +# +# BUG#912513: Wrong result (missing rows) with join_cache_hashed+materialization+semijoin=on +# +set @os_912513= @@optimizer_switch; +set @jcl_912513= @@join_cache_level; +SET optimizer_switch = 'semijoin=on,materialization=on,join_cache_hashed=on'; +SET join_cache_level = 3; +CREATE TABLE t1 ( a INT, b INT, KEY(a) ); +INSERT INTO t1 VALUES +(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +CREATE TABLE t2 ( c INT ); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6),(7); +SELECT alias1.* FROM +t1 AS alias1 INNER JOIN t1 AS alias2 +ON alias2.a = alias1.b +WHERE alias1.b IN ( +SELECT a FROM t1, t2 +); +a b +1 1 +2 2 +3 3 +4 4 +5 5 +6 6 +7 7 +DROP table t1, t2; +set @@optimizer_switch= @os_912513; +set @@join_cache_level= @jcl_912513; # End set join_cache_level=default; show variables like 'join_cache_level'; diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index ee8a365327c..b3a205eb071 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -1849,6 +1849,42 @@ a b c 4 4 2 4 4 4 DROP TABLE t1,t2; +# +# BUG#922254: Assertion `0' failed at item_cmpfunc.cc:5899: Item* Item_equal::get_first(JOIN_TAB*, Item*) +# +CREATE TABLE t1 ( a VARCHAR(3) ); +CREATE TABLE t2 ( b VARCHAR(3), c VARCHAR(8), KEY(c) ); +INSERT INTO t2 VALUES ('USA','Abilene'),('USA','Akron'); +EXPLAIN +SELECT * FROM +( SELECT * FROM t1 ) AS alias1, +t2 AS alias2 +WHERE b = a AND a IN ( +SELECT alias3.c +FROM t2 AS alias3, t2 AS alias4 +WHERE alias4.c = alias3.b +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1,t2; +# +# BUG#928048: Query containing IN subquery with OR in the where clause returns a wrong result +# +create table t1 (a int, b int); +insert into t1 values (7,5), (3,3), (5,4), (9,3); +create table t2 (a int, b int, index i_a(a)); +insert into t2 values +(4,2), (7,9), (7,4), (3,1), (5,3), (3,1), (9,4), (8,1); +explain select * from t1 where t1.a in (select a from t2 where t2.a=7 or t2.b<=1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +1 PRIMARY eq_ref distinct_key distinct_key 5 func 1 +2 MATERIALIZED t2 ALL i_a NULL NULL NULL 8 Using where +select * from t1 where t1.a in (select a from t2 where t2.a=7 or t2.b<=1); +a b +7 5 +3 3 +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/r/sum_distinct.result b/mysql-test/r/sum_distinct.result index c615817f52d..2746f5a09f4 100644 --- a/mysql-test/r/sum_distinct.result +++ b/mysql-test/r/sum_distinct.result @@ -95,3 +95,15 @@ SELECT SUM(DISTINCT id % 11) FROM t1; SUM(DISTINCT id % 11) 55 DROP TABLE t1; +# +# Bug #777654: empty subselect in FROM clause returning +# SUM(DISTINCT) over non-nullable field +# +CREATE TABLE t1 (a int NOT NULL) ; +SELECT SUM(DISTINCT a) FROM t1; +SUM(DISTINCT a) +NULL +SELECT * FROM (SELECT SUM(DISTINCT a) FROM t1) AS t; +SUM(DISTINCT a) +NULL +DROP TABLE t1; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 54170ae3dad..427374fd995 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -277,6 +277,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; update t1 set a=9999 order by a limit 1; @@ -289,6 +290,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 2 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 9 flush status; delete from t1 order by a limit 1; @@ -300,6 +302,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; delete from t1 order by a desc limit 1; @@ -311,6 +314,7 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 alter table t1 disable keys; flush status; @@ -323,7 +327,8 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 1 -Handler_read_rnd_next 9 +Handler_read_rnd_deleted 2 +Handler_read_rnd_next 7 select * from t1; a b 0 0 @@ -377,6 +382,7 @@ Handler_read_last 0 Handler_read_next 1 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 drop table t1, t2; create table t1(f1 int, `*f2` int); @@ -415,6 +421,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 SELECT user_id FROM t1 WHERE request_id=999999999999999999999999999999; user_id @@ -426,6 +433,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 UPDATE t1 SET user_id=null WHERE request_id=9999999999999; show status like '%Handler_read%'; @@ -436,6 +444,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 UPDATE t1 SET user_id=null WHERE request_id=999999999999999999999999999999; show status like '%Handler_read%'; @@ -446,6 +455,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 DROP TABLE t1; CREATE TABLE t1 ( diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f2d3820ff58..9b6ae60b3b5 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -304,7 +304,7 @@ a+1 4 explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 4 +1 PRIMARY ALL NULL NULL NULL NULL 2 2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort drop view v1; drop table t1; @@ -4045,6 +4045,63 @@ drop table t1,t2; # -- End of 5.1 tests. # ----------------------------------------------------------------- # +# Bug #794005: crash in st_table::mark_virtual_columns_for_write +# +CREATE TABLE t1 (a int); +insert into t1 values (1); +CREATE TABLE t2 (a int); +insert into t2 values (1); +CREATE VIEW v2 AS SELECT * FROM t2; +CREATE VIEW v1 AS SELECT * FROM v2; +CREATE VIEW v3 AS SELECT t2.a,v1.a as b FROM t2,v1 where t2.a=v1.a; +CREATE OR REPLACE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT * FROM t1; +UPDATE v1 SET a = 10; +ERROR HY000: The target table v1 of the UPDATE is not updatable +REPLACE v1 SET a = 10; +ERROR HY000: The target table v1 of the INSERT is not insertable-into +INSERT into v1 values (20); +ERROR HY000: The target table v1 of the INSERT is not insertable-into +DELETE from v1; +ERROR HY000: The target table v1 of the DELETE is not updatable +UPDATE v3 SET b= 10; +ERROR HY000: The target table v2 of the UPDATE is not updatable +REPLACE v3 SET b= 10; +ERROR HY000: The target table v3 of the INSERT is not insertable-into +INSERT into v3(b) values (20); +ERROR HY000: The target table v3 of the INSERT is not insertable-into +DELETE from v3 where b=20; +ERROR HY000: Can not delete from join view 'test.v3' +DELETE from v3 where a=20; +ERROR HY000: Can not delete from join view 'test.v3' +DELETE v1 from v1,t1 where v1.a=t1.a; +ERROR HY000: The target table v1 of the DELETE is not updatable +UPDATE v3 SET a = 10; +REPLACE v3 SET a = 11; +INSERT INTO v3(a) values (20); +select * from t1; +a +1 +select * from t2; +a +10 +11 +20 +CREATE OR REPLACE ALGORITHM = MERGE VIEW v2 AS SELECT * FROM t2; +DELETE from v1 where a=11; +DELETE v1 from v1,t1 where v1.a=t1.a; +select * from t1; +a +1 +select * from t2; +a +10 +20 +DROP VIEW v1,v2,v3; +DROP TABLE t1,t2; +# ----------------------------------------------------------------- +# -- End of 5.2 tests. +# ----------------------------------------------------------------- +# # Bug #59696 Optimizer does not use equalities for conditions over view # CREATE TABLE t1 (a int NOT NULL); @@ -4075,6 +4132,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 CREATE VIEW v AS SELECT * FROM t2; EXPLAIN EXTENDED @@ -4097,6 +4155,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 17 DROP VIEW v; DROP TABLE t1, t2; @@ -4569,4 +4628,7 @@ NULL NULL 1 0 NULL NULL 1 0 DROP VIEW v2; DROP TABLE t1, t2, t3; +# ----------------------------------------------------------------- +# -- End of 5.3 tests. +# ----------------------------------------------------------------- SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/suite/maria/r/maria-gis-recovery.result b/mysql-test/suite/maria/r/maria-gis-recovery.result new file mode 100644 index 00000000000..d1088dd1ba0 --- /dev/null +++ b/mysql-test/suite/maria/r/maria-gis-recovery.result @@ -0,0 +1,66 @@ +set global aria_log_file_size=4294967295; +Warnings: +Warning 1292 Truncated incorrect aria_log_file_size value: '4294967295' +drop database if exists mysqltest; +create database mysqltest; +use mysqltest; +* shut down mysqld, removed logs, restarted it +CREATE TABLE t1 ( +i int, +shape GEOMETRY NOT NULL, +SPATIAL (shape) +) ENGINE=ARIA; +insert into t1 values(1,POINT(1, 1)); +* copied t1 for feeding_recovery +insert into t1 values(2,POINT(2, 2)), (3,POINT(3, 3)), (4,POINT(4, 4)); +flush table t1; +* copied t1 for comparison +SET SESSION debug_dbug="+d,maria_flush_whole_log,maria_crash"; +* crashing mysqld intentionally +set global aria_checkpoint_interval=1; +ERROR HY000: Lost connection to MySQL server during query +* copied t1 back for feeding_recovery +* recovery happens +check table t1 extended; +Table Op Msg_type Msg_text +mysqltest.t1 check status OK +* testing that checksum after recovery is as expected +Checksum-check +ok +use mysqltest; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) DEFAULT NULL, + `shape` geometry NOT NULL, + SPATIAL KEY `shape` (`shape`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 +* TEST of UPDATE vs state.auto_increment +* copied t1 for feeding_recovery +update t1 set shape=POINT(5, 5) where i=2; +flush table t1; +* copied t1 for comparison +SET SESSION debug_dbug="+d,maria_flush_whole_log,maria_crash"; +* crashing mysqld intentionally +set global aria_checkpoint_interval=1; +ERROR HY000: Lost connection to MySQL server during query +* copied t1 back for feeding_recovery +* recovery happens +check table t1 extended; +Table Op Msg_type Msg_text +mysqltest.t1 check status OK +* testing that checksum after recovery is as expected +Checksum-check +ok +use mysqltest; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) DEFAULT NULL, + `shape` geometry NOT NULL, + SPATIAL KEY `shape` (`shape`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 +drop table t1; +drop database mysqltest_for_feeding_recovery; +drop database mysqltest_for_comparison; +drop database mysqltest; diff --git a/mysql-test/suite/maria/t/maria-gis-recovery.opt b/mysql-test/suite/maria/t/maria-gis-recovery.opt new file mode 100644 index 00000000000..58d0d012c54 --- /dev/null +++ b/mysql-test/suite/maria/t/maria-gis-recovery.opt @@ -0,0 +1 @@ +--skip-stack-trace --skip-core-file --loose-aria-log-dir-path=$MYSQLTEST_VARDIR/tmp diff --git a/mysql-test/suite/maria/t/maria-gis-recovery.test b/mysql-test/suite/maria/t/maria-gis-recovery.test new file mode 100644 index 00000000000..c40cc3788de --- /dev/null +++ b/mysql-test/suite/maria/t/maria-gis-recovery.test @@ -0,0 +1,64 @@ +--source include/not_embedded.inc +# Don't test this under valgrind, memory leaks will occur as we crash +--source include/not_valgrind.inc +# Binary must be compiled with debug for crash to occur +--source include/have_debug.inc +--source include/have_maria.inc +--source include/have_geometry.inc + +set global aria_log_file_size=4294967295; +let $MARIA_LOG=../../tmp; + +--disable_warnings +drop database if exists mysqltest; +--enable_warnings +create database mysqltest; +let $mms_tname=t; + +# Include scripts can perform SQL. For it to not influence the main test +# they use a separate connection. This way if they use a DDL it would +# not autocommit in the main test. +connect (admin, localhost, root,,mysqltest,,); +--enable_reconnect + +connection default; +use mysqltest; +--enable_reconnect + +-- source include/maria_empty_logs.inc +let $mms_tables=1; +CREATE TABLE t1 ( + i int, + shape GEOMETRY NOT NULL, + SPATIAL (shape) +) ENGINE=ARIA; +insert into t1 values(1,POINT(1, 1)); +-- source include/maria_make_snapshot_for_feeding_recovery.inc +insert into t1 values(2,POINT(2, 2)), (3,POINT(3, 3)), (4,POINT(4, 4)); +-- source include/maria_make_snapshot_for_comparison.inc +let $mvr_restore_old_snapshot=1; +let $mms_compare_physically=0; +let $mvr_debug_option="+d,maria_flush_whole_log,maria_crash"; +let $mvr_crash_statement= set global aria_checkpoint_interval=1; +-- source include/maria_verify_recovery.inc +show create table t1; + +# Test that UPDATE's effect on auto-increment is recovered +--echo * TEST of UPDATE vs state.auto_increment +-- source include/maria_make_snapshot_for_feeding_recovery.inc +update t1 set shape=POINT(5, 5) where i=2; +-- source include/maria_make_snapshot_for_comparison.inc +let $mvr_restore_old_snapshot=1; +let $mms_compare_physically=0; +let $mvr_debug_option="+d,maria_flush_whole_log,maria_crash"; +let $mvr_crash_statement= set global aria_checkpoint_interval=1; +-- source include/maria_verify_recovery.inc +show create table t1; +drop table t1; + +# clean up everything +let $mms_purpose=feeding_recovery; +eval drop database mysqltest_for_$mms_purpose; +let $mms_purpose=comparison; +eval drop database mysqltest_for_$mms_purpose; +drop database mysqltest; diff --git a/mysql-test/suite/pbxt/r/heap.result.THIS b/mysql-test/suite/pbxt/r/heap.result.THIS deleted file mode 100644 index 0404e8b98f9..00000000000 --- a/mysql-test/suite/pbxt/r/heap.result.THIS +++ /dev/null @@ -1,733 +0,0 @@ -drop table if exists t1,t2,t3; -create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100; -insert into t1 values(1,1),(2,2),(3,3),(4,4); -delete from t1 where a=1 or a=0; -show keys from t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 0 PRIMARY 1 a NULL 3 NULL NULL HASH -select * from t1; -a b -2 2 -3 3 -4 4 -select * from t1 where a=4; -a b -4 4 -update t1 set b=5 where a=4; -update t1 set b=b+1 where a>=3; -replace t1 values (3,3); -select * from t1; -a b -2 2 -3 3 -4 6 -alter table t1 add c int not null, add key (c,a); -drop table t1; -create table t1 (a int not null,b int not null, primary key (a)) engine=memory comment="testing heaps"; -insert into t1 values(1,1),(2,2),(3,3),(4,4); -delete from t1 where a > 0; -select * from t1; -a b -drop table t1; -create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps"; -insert into t1 values(1,1),(2,2),(3,3),(4,4); -alter table t1 modify a int not null auto_increment, engine=myisam, comment="new myisam table"; -select * from t1; -a b -1 1 -2 2 -3 3 -4 4 -drop table t1; -create table t1 (a int not null) engine=heap; -insert into t1 values (869751),(736494),(226312),(802616),(728912); -select * from t1 where a > 736494; -a -869751 -802616 -alter table t1 add unique uniq_id(a); -select * from t1 where a > 736494; -a -869751 -802616 -select * from t1 where a = 736494; -a -736494 -select * from t1 where a=869751 or a=736494; -a -736494 -869751 -select * from t1 where a in (869751,736494,226312,802616); -a -226312 -736494 -802616 -869751 -alter table t1 engine=myisam; -explain select * from t1 where a in (869751,736494,226312,802616); -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range uniq_id uniq_id 4 NULL 4 Using where; Using index -drop table t1; -create table t1 (x int not null, y int not null, key x (x), unique y (y)) -engine=heap; -insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6); -select * from t1 where x=1; -x y -1 3 -1 1 -select * from t1,t1 as t2 where t1.x=t2.y; -x y x y -1 1 1 1 -2 2 2 2 -1 3 1 1 -2 4 2 2 -2 5 2 2 -2 6 2 2 -explain select * from t1,t1 as t2 where t1.x=t2.y; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL x NULL NULL NULL 6 -1 SIMPLE t2 eq_ref y y 4 test.t1.x 1 -drop table t1; -create table t1 (a int) engine=heap; -insert into t1 values(1); -select max(a) from t1; -max(a) -1 -drop table t1; -CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key(a), key(b) ) ENGINE=HEAP; -insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6); -select * from t1 where a=1; -a b -1 6 -1 5 -1 4 -1 3 -1 2 -1 1 -insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6); -select * from t1 where a=1; -a b -1 6 -1 5 -1 4 -1 3 -1 2 -1 1 -1 6 -1 5 -1 4 -1 3 -1 2 -1 1 -drop table t1; -create table t1 (id int unsigned not null, primary key (id)) engine=HEAP; -insert into t1 values(1); -select max(id) from t1; -max(id) -1 -insert into t1 values(2); -select max(id) from t1; -max(id) -2 -replace into t1 values(1); -drop table t1; -create table t1 (n int) engine=heap; -drop table t1; -create table t1 (n int) engine=heap; -drop table if exists t1; -CREATE table t1(f1 int not null,f2 char(20) not -null,index(f2)) engine=heap; -INSERT into t1 set f1=12,f2="bill"; -INSERT into t1 set f1=13,f2="bill"; -INSERT into t1 set f1=14,f2="bill"; -INSERT into t1 set f1=15,f2="bill"; -INSERT into t1 set f1=16,f2="ted"; -INSERT into t1 set f1=12,f2="ted"; -INSERT into t1 set f1=12,f2="ted"; -INSERT into t1 set f1=12,f2="ted"; -INSERT into t1 set f1=12,f2="ted"; -delete from t1 where f2="bill"; -select * from t1; -f1 f2 -16 ted -12 ted -12 ted -12 ted -12 ted -drop table t1; -create table t1 (btn char(10) not null, key(btn)) engine=heap; -insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i"); -explain select * from t1 where btn like "q%"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where -select * from t1 where btn like "q%"; -btn -alter table t1 add column new_col char(1) not null, add key (btn,new_col), drop key btn; -update t1 set new_col=left(btn,1); -explain select * from t1 where btn="a"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where -explain select * from t1 where btn="a" and new_col="a"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref btn btn 11 const,const 2 Using where -drop table t1; -CREATE TABLE t1 ( -a int default NULL, -b int default NULL, -KEY a (a), -UNIQUE b (b) -) engine=heap; -INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3); -SELECT * FROM t1 WHERE a=NULL; -a b -explain SELECT * FROM t1 WHERE a IS NULL; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 2 Using where -SELECT * FROM t1 WHERE a<=>NULL; -a b -NULL 99 -SELECT * FROM t1 WHERE b=NULL; -a b -explain SELECT * FROM t1 WHERE b IS NULL; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref b b 5 const 1 Using where -SELECT * FROM t1 WHERE b<=>NULL; -a b -99 NULL -INSERT INTO t1 VALUES (1,3); -ERROR 23000: Duplicate entry '3' for key 'b' -DROP TABLE t1; -CREATE TABLE t1 ( -a int default NULL, -key a (a) -) ENGINE=HEAP; -INSERT INTO t1 VALUES (10), (10), (10); -EXPLAIN SELECT * FROM t1 WHERE a=10; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 3 -SELECT * FROM t1 WHERE a=10; -a -10 -10 -10 -DROP TABLE t1; -CREATE TABLE t1 (a int not null, primary key(a)) engine=heap; -INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11); -DELETE from t1 where a < 100; -SELECT * from t1; -a -DROP TABLE t1; -CREATE TABLE `job_titles` ( -`job_title_id` int(6) unsigned NOT NULL default '0', -`job_title` char(18) NOT NULL default '', -PRIMARY KEY (`job_title_id`), -UNIQUE KEY `job_title_id` (`job_title_id`,`job_title`) -) ENGINE=HEAP; -SELECT MAX(job_title_id) FROM job_titles; -MAX(job_title_id) -NULL -DROP TABLE job_titles; -CREATE TABLE t1 (a INT NOT NULL, B INT, KEY(B)) ENGINE=HEAP; -INSERT INTO t1 VALUES(1,1), (1,NULL); -SELECT * FROM t1 WHERE B is not null; -a B -1 1 -DROP TABLE t1; -CREATE TABLE t1 (pseudo char(35) PRIMARY KEY, date int(10) unsigned NOT NULL) ENGINE=HEAP; -INSERT INTO t1 VALUES ('massecot',1101106491),('altec',1101106492),('stitch+',1101106304),('Seb Corgan',1101106305),('beerfilou',1101106263),('flaker',1101106529),('joce8',5),('M4vrick',1101106418),('gabay008',1101106525),('Vamp irX',1101106291),('ZoomZip',1101106546),('rip666',1101106502),('CBP ',1101106397),('guezpard',1101106496); -DELETE FROM t1 WHERE date<1101106546; -SELECT * FROM t1; -pseudo date -ZoomZip 1101106546 -DROP TABLE t1; -create table t1(a char(2)) engine=memory; -insert into t1 values (NULL), (NULL); -delete from t1 where a is null; -insert into t1 values ('2'), ('3'); -select * from t1; -a -3 -2 -drop table t1; -set storage_engine=HEAP; -create table t1 (v varchar(10), c char(10), t varchar(50)); -insert into t1 values('+ ', '+ ', '+ '); -set @a=repeat(' ',20); -insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a)); -Warnings: -Note 1265 Data truncated for column 'v' at row 1 -select concat('*',v,'*',c,'*',t,'*') from t1; -concat('*',v,'*',c,'*',t,'*') -*+ *+*+ * -*+ *+*+ * -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(10) DEFAULT NULL, - `c` char(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -create table t2 like t1; -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `v` varchar(10) DEFAULT NULL, - `c` char(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -create table t3 select * from t1; -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `v` varchar(10) DEFAULT NULL, - `c` char(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -alter table t1 modify c varchar(10); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(10) DEFAULT NULL, - `c` varchar(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -alter table t1 modify v char(10); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` char(10) DEFAULT NULL, - `c` varchar(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -alter table t1 modify t varchar(10); -Warnings: -Warning 1265 Data truncated for column 't' at row 2 -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` char(10) DEFAULT NULL, - `c` varchar(10) DEFAULT NULL, - `t` varchar(10) DEFAULT NULL -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -select concat('*',v,'*',c,'*',t,'*') from t1; -concat('*',v,'*',c,'*',t,'*') -*+*+*+ * -*+*+*+ * -drop table t1,t2,t3; -create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10))); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(10) DEFAULT NULL, - `c` char(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL, - KEY `v` (`v`), - KEY `c` (`c`), - KEY `t` (`t`(10)) -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -select count(*) from t1; -count(*) -270 -insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1))); -select count(*) from t1 where v='a'; -count(*) -10 -select count(*) from t1 where c='a'; -count(*) -10 -select count(*) from t1 where t='a'; -count(*) -10 -select count(*) from t1 where v='a '; -count(*) -10 -select count(*) from t1 where c='a '; -count(*) -10 -select count(*) from t1 where t='a '; -count(*) -10 -select count(*) from t1 where v between 'a' and 'a '; -count(*) -10 -select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n'; -count(*) -10 -select count(*) from t1 where v like 'a%'; -count(*) -11 -select count(*) from t1 where c like 'a%'; -count(*) -11 -select count(*) from t1 where t like 'a%'; -count(*) -11 -select count(*) from t1 where v like 'a %'; -count(*) -9 -explain select count(*) from t1 where v='a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const 10 Using where -explain select count(*) from t1 where c='a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref c c 11 const 10 Using where -explain select count(*) from t1 where t='a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref t t 13 const 10 Using where -explain select count(*) from t1 where v like 'a%'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where -explain select count(*) from t1 where v between 'a' and 'a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const 10 Using where -explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const 10 Using where -alter table t1 add unique(v); -ERROR 23000: Duplicate entry '{ ' for key 'v_2' -select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*')); -qq -*a*a*a* -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -explain select * from t1 where v='a'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const 10 Using where -select v,count(*) from t1 group by v limit 10; -v count(*) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select v,count(t) from t1 group by v limit 10; -v count(t) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select v,count(c) from t1 group by v limit 10; -v count(c) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select sql_big_result trim(v),count(t) from t1 group by v limit 10; -trim(v) count(t) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select sql_big_result trim(v),count(c) from t1 group by v limit 10; -trim(v) count(c) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select c,count(*) from t1 group by c limit 10; -c count(*) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select c,count(t) from t1 group by c limit 10; -c count(t) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select sql_big_result c,count(t) from t1 group by c limit 10; -c count(t) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select t,count(*) from t1 group by t limit 10; -t count(*) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select t,count(t) from t1 group by t limit 10; -t count(t) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -select sql_big_result trim(t),count(t) from t1 group by t limit 10; -trim(t) count(t) -a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 -drop table t1; -create table t1 (a char(10), unique (a)); -insert into t1 values ('a'); -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a' for key 'a' -alter table t1 modify a varchar(10); -insert into t1 values ('a '),('a '),('a '),('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -update t1 set a='a ' where a like 'a '; -update t1 set a='a ' where a like 'a '; -drop table t1; -create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10))); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(10) DEFAULT NULL, - `c` char(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL, - KEY `v` (`v`) USING BTREE, - KEY `c` (`c`) USING BTREE, - KEY `t` (`t`(10)) USING BTREE -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -select count(*) from t1; -count(*) -270 -insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1))); -select count(*) from t1 where v='a'; -count(*) -10 -select count(*) from t1 where c='a'; -count(*) -10 -select count(*) from t1 where t='a'; -count(*) -10 -select count(*) from t1 where v='a '; -count(*) -10 -select count(*) from t1 where c='a '; -count(*) -10 -select count(*) from t1 where t='a '; -count(*) -10 -select count(*) from t1 where v between 'a' and 'a '; -count(*) -10 -select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n'; -count(*) -10 -explain select count(*) from t1 where v='a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const # Using where -explain select count(*) from t1 where c='a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref c c 11 const # Using where -explain select count(*) from t1 where t='a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref t t 13 const # Using where -explain select count(*) from t1 where v like 'a%'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 13 NULL # Using where -explain select count(*) from t1 where v between 'a' and 'a '; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const # Using where -explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const # Using where -alter table t1 add unique(v); -ERROR 23000: Duplicate entry '{ ' for key 'v_2' -select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*')); -qq -*a*a*a* -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -*a *a*a * -explain select * from t1 where v='a'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const # Using where -drop table t1; -create table t1 (a char(10), unique using btree (a)) engine=heap; -insert into t1 values ('a'); -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a' for key 'a' -alter table t1 modify a varchar(10); -insert into t1 values ('a '),('a '),('a '),('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -insert into t1 values ('a '); -ERROR 23000: Duplicate entry 'a ' for key 'a' -update t1 set a='a ' where a like 'a '; -update t1 set a='a ' where a like 'a '; -drop table t1; -create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)), key(t(5))); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(10) DEFAULT NULL, - `c` char(10) DEFAULT NULL, - `t` varchar(50) DEFAULT NULL, - KEY `v` (`v`(5)), - KEY `c` (`c`(5)), - KEY `t` (`t`(5)) -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -drop table t1; -create table t1 (v varchar(65530), key(v(10))); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(65530) DEFAULT NULL, - KEY `v` (`v`(10)) -) ENGINE=MEMORY DEFAULT CHARSET=latin1 -insert into t1 values(repeat('a',65530)); -select length(v) from t1 where v=repeat('a',65530); -length(v) -65530 -drop table t1; -set storage_engine=PBXT; -create table t1 (a bigint unsigned auto_increment primary key, b int, -key (b, a)) engine=heap; -insert t1 (b) values (1),(1),(1),(1),(1),(1),(1),(1); -select * from t1; -a b -1 1 -2 1 -3 1 -4 1 -5 1 -6 1 -7 1 -8 1 -drop table t1; -create table t1 (a int not null, b int not null auto_increment, -primary key(a, b), key(b)) engine=heap; -insert t1 (a) values (1),(1),(1),(1),(1),(1),(1),(1); -select * from t1; -a b -1 1 -1 2 -1 3 -1 4 -1 5 -1 6 -1 7 -1 8 -drop table t1; -create table t1 (a int not null, b int not null auto_increment, -primary key(a, b)) engine=heap; -ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key -create table t1 (c char(255), primary key(c(90))); -insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); -insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); -ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 'PRIMARY' -drop table t1; -CREATE TABLE t1 (a int, key(a)) engine=heap; -insert into t1 values (0); -delete from t1; -select * from t1; -a -insert into t1 values (0), (1); -select * from t1 where a = 0; -a -0 -drop table t1; -create table t1 (c char(10)) engine=memory; -create table t2 (c varchar(10)) engine=memory; -show table status like 't_'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MEMORY 10 Fixed 0 11 0 # 0 0 NULL # NULL NULL latin1_swedish_ci NULL -t2 MEMORY 10 Fixed 0 12 0 # 0 0 NULL # NULL NULL latin1_swedish_ci NULL -drop table t1, t2; -CREATE TABLE t1(a VARCHAR(1), b VARCHAR(2), c VARCHAR(256), -KEY(a), KEY(b), KEY(c)) ENGINE=MEMORY; -INSERT INTO t1 VALUES('a','aa',REPEAT('a', 256)),('a','aa',REPEAT('a',256)); -SELECT COUNT(*) FROM t1 WHERE a='a'; -COUNT(*) -2 -SELECT COUNT(*) FROM t1 WHERE b='aa'; -COUNT(*) -2 -SELECT COUNT(*) FROM t1 WHERE c=REPEAT('a',256); -COUNT(*) -2 -DROP TABLE t1; diff --git a/mysql-test/suite/pbxt/r/null_key.result b/mysql-test/suite/pbxt/r/null_key.result index 7ef554af946..a997cf913c9 100644 --- a/mysql-test/suite/pbxt/r/null_key.result +++ b/mysql-test/suite/pbxt/r/null_key.result @@ -428,5 +428,6 @@ Handler_read_last 0 Handler_read_next 2 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 5 DROP TABLE t1,t2,t3,t4; diff --git a/mysql-test/suite/pbxt/r/ps_11bugs.result b/mysql-test/suite/pbxt/r/ps_11bugs.result index dd09e9d14f3..5a2743436e1 100644 --- a/mysql-test/suite/pbxt/r/ps_11bugs.result +++ b/mysql-test/suite/pbxt/r/ps_11bugs.result @@ -121,8 +121,8 @@ insert into t1 values (1); explain select * from t1 where 3 in (select (1+1) union select 1); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL PRIMARY 4 NULL 1 Using index -2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used -3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used NULL UNION RESULT ALL NULL NULL NULL NULL NULL select * from t1 where 3 in (select (1+1) union select 1); a diff --git a/mysql-test/suite/pbxt/r/select.result b/mysql-test/suite/pbxt/r/select.result index a3ed13f3de0..18ffdd30abe 100644 --- a/mysql-test/suite/pbxt/r/select.result +++ b/mysql-test/suite/pbxt/r/select.result @@ -2789,10 +2789,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 index key1 key1 5 NULL 4 Using where; Using index explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE t1 index key1 key1 5 NULL 4 Using where; Using index select max(key1) from t1 where key1 <= 0.6158; max(key1) 0.6158000230789185 @@ -2811,10 +2811,18 @@ max(key1) min(key2) 0.6158000230789185 1.3761999607086182 select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; max(key1) +<<<<<<< TREE 0.6158000230789185 +======= +0.384499996900558 +>>>>>>> MERGE-SOURCE select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; min(key1) +<<<<<<< TREE 0.37619999051094055 +======= +0.384499996900558 +>>>>>>> MERGE-SOURCE DROP TABLE t1,t2; CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); diff --git a/mysql-test/suite/pbxt/r/update.result b/mysql-test/suite/pbxt/r/update.result index 13d50071bfd..83b284b794d 100644 --- a/mysql-test/suite/pbxt/r/update.result +++ b/mysql-test/suite/pbxt/r/update.result @@ -277,6 +277,7 @@ Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 flush status; update t1 set a=9999 order by a limit 1; @@ -292,6 +293,21 @@ Handler_read_last 1 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 2 +<<<<<<< TREE +======= +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 18 +flush status; +delete from t1 order by a limit 1; +show status like 'handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_deleted 0 +>>>>>>> MERGE-SOURCE Handler_read_rnd_next 9 flush status; delete from t1 order by a limit 1; @@ -313,8 +329,14 @@ Handler_read_key 0 Handler_read_last 1 Handler_read_next 0 Handler_read_prev 0 +<<<<<<< TREE Handler_read_rnd 0 Handler_read_rnd_next 0 +======= +Handler_read_rnd 1 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 8 +>>>>>>> MERGE-SOURCE alter table t1 disable keys; Warnings: Note 1031 Table storage engine for 't1' doesn't have this option @@ -327,8 +349,14 @@ Handler_read_key 0 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 +<<<<<<< TREE Handler_read_rnd 0 Handler_read_rnd_next 0 +======= +Handler_read_rnd 1 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 7 +>>>>>>> MERGE-SOURCE select * from t1; a b 0 0 @@ -382,6 +410,7 @@ Handler_read_last 0 Handler_read_next 1 Handler_read_prev 0 Handler_read_rnd 1 +Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 drop table t1, t2; create table t1(f1 int, `*f2` int); diff --git a/mysql-test/suite/pbxt/r/view_grant.result.THIS b/mysql-test/suite/pbxt/r/view_grant.result.THIS deleted file mode 100644 index cef441efc77..00000000000 --- a/mysql-test/suite/pbxt/r/view_grant.result.THIS +++ /dev/null @@ -1,959 +0,0 @@ -drop database if exists mysqltest; -drop view if exists v1,v2,v3; -grant create view on test.* to test@localhost; -show grants for test@localhost; -Grants for test@localhost -GRANT USAGE ON *.* TO 'test'@'localhost' -GRANT CREATE VIEW ON `test`.* TO 'test'@'localhost' -revoke create view on test.* from test@localhost; -show grants for test@localhost; -Grants for test@localhost -GRANT USAGE ON *.* TO 'test'@'localhost' -drop user test@localhost; -create database mysqltest; -create table mysqltest.t1 (a int, b int); -create table mysqltest.t2 (a int, b int); -grant select on mysqltest.t1 to mysqltest_1@localhost; -grant create view,select on test.* to mysqltest_1@localhost; -create definer=root@localhost view v1 as select * from mysqltest.t1; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation -create view v1 as select * from mysqltest.t1; -alter view v1 as select * from mysqltest.t1; -ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 'v1' -create or replace view v1 as select * from mysqltest.t1; -ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 'v1' -create view mysqltest.v2 as select * from mysqltest.t1; -ERROR 42000: CREATE VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2' -create view v2 as select * from mysqltest.t2; -ERROR 42000: ANY command denied to user 'mysqltest_1'@'localhost' for table 't2' -show create view v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` latin1 latin1_swedish_ci -grant create view,drop,select on test.* to mysqltest_1@localhost; -use test; -alter view v1 as select * from mysqltest.t1; -create or replace view v1 as select * from mysqltest.t1; -revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; -revoke all privileges on test.* from mysqltest_1@localhost; -drop database mysqltest; -drop view test.v1; -create database mysqltest; -create table mysqltest.t1 (a int, b int); -create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1; -grant select (c) on mysqltest.v1 to mysqltest_1@localhost; -select c from mysqltest.v1; -c -select d from mysqltest.v1; -ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 'v1' -revoke all privileges on mysqltest.v1 from mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int); -create algorithm=temptable view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1; -grant select (c) on mysqltest.v1 to mysqltest_1@localhost; -select c from mysqltest.v1; -c -select d from mysqltest.v1; -ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 'v1' -revoke all privileges on mysqltest.v1 from mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int); -create table mysqltest.t2 (a int, b int); -create view mysqltest.v1 (c,d) as select a+1,b+1 from mysqltest.t1; -create algorithm=temptable view mysqltest.v2 (c,d) as select a+1,b+1 from mysqltest.t1; -create view mysqltest.v3 (c,d) as select a+1,b+1 from mysqltest.t2; -create algorithm=temptable view mysqltest.v4 (c,d) as select a+1,b+1 from mysqltest.t2; -grant select on mysqltest.v1 to mysqltest_1@localhost; -grant select on mysqltest.v2 to mysqltest_1@localhost; -grant select on mysqltest.v3 to mysqltest_1@localhost; -grant select on mysqltest.v4 to mysqltest_1@localhost; -select c from mysqltest.v1; -c -select c from mysqltest.v2; -c -select c from mysqltest.v3; -c -select c from mysqltest.v4; -c -show columns from mysqltest.v1; -Field Type Null Key Default Extra -c bigint(12) YES NULL -d bigint(12) YES NULL -show columns from mysqltest.v2; -Field Type Null Key Default Extra -c bigint(12) YES NULL -d bigint(12) YES NULL -explain select c from mysqltest.v1; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table -show create view mysqltest.v1; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' -explain select c from mysqltest.v2; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table -show create view mysqltest.v2; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2' -explain select c from mysqltest.v3; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table -show create view mysqltest.v3; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v3' -explain select c from mysqltest.v4; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table -show create view mysqltest.v4; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v4' -grant select on mysqltest.t1 to mysqltest_1@localhost; -explain select c from mysqltest.v1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 -show create view mysqltest.v1; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' -explain select c from mysqltest.v2; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 2 -2 DERIVED t1 ALL NULL NULL NULL NULL 0 -show create view mysqltest.v2; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2' -explain select c from mysqltest.v3; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table -show create view mysqltest.v3; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v3' -explain select c from mysqltest.v4; -ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table -show create view mysqltest.v4; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v4' -grant show view on mysqltest.* to mysqltest_1@localhost; -explain select c from mysqltest.v1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 -show create view mysqltest.v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` latin1 latin1_swedish_ci -explain select c from mysqltest.v2; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 2 -2 DERIVED t1 ALL NULL NULL NULL NULL 0 -show create view mysqltest.v2; -View Create View character_set_client collation_connection -v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` latin1 latin1_swedish_ci -explain select c from mysqltest.v3; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 0 -show create view mysqltest.v3; -View Create View character_set_client collation_connection -v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` latin1 latin1_swedish_ci -explain select c from mysqltest.v4; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 2 -2 DERIVED t2 ALL NULL NULL NULL NULL 0 -show create view mysqltest.v4; -View Create View character_set_client collation_connection -v4 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v4` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` latin1 latin1_swedish_ci -revoke all privileges on mysqltest.* from mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int, primary key(a)); -insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10); -create table mysqltest.t2 (x int); -insert into mysqltest.t2 values (3), (4), (5), (6); -create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1; -create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1; -create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1; -grant update (a) on mysqltest.v2 to mysqltest_1@localhost; -grant update on mysqltest.v1 to mysqltest_1@localhost; -grant select on mysqltest.* to mysqltest_1@localhost; -use mysqltest; -update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.c; -select * from t1 order by a; -a b -13 2 -24 3 -35 4 -46 5 -50 10 -update v1 set a=a+c; -select * from t1 order by a; -a b -16 2 -28 3 -40 4 -52 5 -61 10 -update t2,v2 set v2.a=v2.a+v2.c where t2.x=v2.c; -select * from t1 order by a; -a b -16 2 -31 3 -44 4 -57 5 -61 10 -update v2 set a=a+c; -select * from t1 order by a; -a b -18 2 -34 3 -48 4 -62 5 -71 10 -update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c; -ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for column 'c' in table 'v2' -update v2 set c=a+c; -ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for column 'c' in table 'v2' -update t2,v3 set v3.a=v3.a+v3.c where t2.x=v3.c; -ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for table 'v3' -update v3 set a=a+c; -ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for table 'v3' -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int, primary key(a)); -insert into mysqltest.t1 values (1,2), (2,3), (3,4), (4,5), (5,10); -create table mysqltest.t2 (x int); -insert into mysqltest.t2 values (3), (4), (5), (6); -create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1; -create view mysqltest.v2 (a,c) as select a, b+1 from mysqltest.t1; -grant delete on mysqltest.v1 to mysqltest_1@localhost; -grant select on mysqltest.* to mysqltest_1@localhost; -use mysqltest; -delete from v1 where c < 4; -select * from t1; -a b -2 3 -3 4 -4 5 -5 10 -delete v1 from t2,v1 where t2.x=v1.c; -select * from t1; -a b -5 10 -delete v2 from t2,v2 where t2.x=v2.c; -ERROR 42000: DELETE command denied to user 'mysqltest_1'@'localhost' for table 'v2' -delete from v2 where c < 4; -ERROR 42000: DELETE command denied to user 'mysqltest_1'@'localhost' for table 'v2' -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int, primary key(a)); -insert into mysqltest.t1 values (1,2), (2,3); -create table mysqltest.t2 (x int, y int); -insert into mysqltest.t2 values (3,4); -create view mysqltest.v1 (a,c) as select a, b from mysqltest.t1; -create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1; -grant insert on mysqltest.v1 to mysqltest_1@localhost; -grant select on mysqltest.* to mysqltest_1@localhost; -use mysqltest; -insert into v1 values (5,6); -select * from t1; -a b -1 2 -2 3 -5 6 -insert into v1 select x,y from t2; -select * from t1; -a b -1 2 -2 3 -5 6 -3 4 -insert into v2 values (5,6); -ERROR 42000: INSERT command denied to user 'mysqltest_1'@'localhost' for table 'v2' -insert into v2 select x,y from t2; -ERROR 42000: INSERT command denied to user 'mysqltest_1'@'localhost' for table 'v2' -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int); -create table mysqltest.t2 (a int, b int); -grant update on mysqltest.t1 to mysqltest_1@localhost; -grant update(b) on mysqltest.t2 to mysqltest_1@localhost; -grant create view,update on test.* to mysqltest_1@localhost; -create view v1 as select * from mysqltest.t1; -create view v2 as select b from mysqltest.t2; -create view mysqltest.v1 as select * from mysqltest.t1; -ERROR 42000: CREATE VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' -create view v3 as select a from mysqltest.t2; -ERROR 42000: ANY command denied to user 'mysqltest_1'@'localhost' for column 'a' in table 't2' -create table mysqltest.v3 (b int); -grant create view on mysqltest.v3 to mysqltest_1@localhost; -drop table mysqltest.v3; -create view mysqltest.v3 as select b from mysqltest.t2; -grant create view, update on mysqltest.v3 to mysqltest_1@localhost; -drop view mysqltest.v3; -create view mysqltest.v3 as select b from mysqltest.t2; -create view v4 as select b+1 from mysqltest.t2; -ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't2' -grant create view,update,select on test.* to mysqltest_1@localhost; -create view v4 as select b+1 from mysqltest.t2; -ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't2' -grant update,select(b) on mysqltest.t2 to mysqltest_1@localhost; -create view v4 as select b+1 from mysqltest.t2; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -drop view v1,v2,v4; -create database mysqltest; -create table mysqltest.t1 (a int); -grant all privileges on mysqltest.* to mysqltest_1@localhost; -use mysqltest; -create view v1 as select * from t1; -use test; -revoke all privileges on mysqltest.* from mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -create table mysqltest.t1 (a int, b int); -grant select on mysqltest.t1 to mysqltest_1@localhost; -grant create view,select on test.* to mysqltest_1@localhost; -create view v1 as select * from mysqltest.t1; -show create view v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` latin1 latin1_swedish_ci -revoke select on mysqltest.t1 from mysqltest_1@localhost; -select * from v1; -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -grant select on mysqltest.t1 to mysqltest_1@localhost; -select * from v1; -a b -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop view v1; -drop database mysqltest; -create database mysqltest; -use mysqltest; -create table t1 (a int); -insert into t1 values (1); -create table t2 (s1 int); -drop function if exists f2; -create function f2 () returns int begin declare v int; select s1 from t2 -into v; return v; end// -create algorithm=TEMPTABLE view v1 as select f2() from t1; -create algorithm=MERGE view v2 as select f2() from t1; -create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; -create algorithm=MERGE SQL SECURITY INVOKER view v4 as select f2() from t1; -create SQL SECURITY INVOKER view v5 as select * from v4; -grant select on v1 to mysqltest_1@localhost; -grant select on v2 to mysqltest_1@localhost; -grant select on v3 to mysqltest_1@localhost; -grant select on v4 to mysqltest_1@localhost; -grant select on v5 to mysqltest_1@localhost; -use mysqltest; -select * from v1; -f2() -NULL -Warnings: -Warning 1329 No data - zero rows fetched, selected, or processed -select * from v2; -f2() -NULL -Warnings: -Warning 1329 No data - zero rows fetched, selected, or processed -select * from v3; -ERROR HY000: View 'mysqltest.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v4; -ERROR HY000: View 'mysqltest.v4' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v5; -ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -use test; -drop view v1, v2, v3, v4, v5; -drop function f2; -drop table t1, t2; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -use mysqltest; -create table t1 (a int); -insert into t1 values (1); -create table t2 (s1 int); -drop function if exists f2; -create function f2 () returns int begin declare v int; select s1 from t2 -into v; return v; end// -grant select on t1 to mysqltest_1@localhost; -grant execute on function f2 to mysqltest_1@localhost; -grant create view on mysqltest.* to mysqltest_1@localhost; -use mysqltest; -create algorithm=TEMPTABLE view v1 as select f2() from t1; -create algorithm=MERGE view v2 as select f2() from t1; -create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; -create algorithm=MERGE SQL SECURITY INVOKER view v4 as select f2() from t1; -use test; -create view v5 as select * from v1; -revoke execute on function f2 from mysqltest_1@localhost; -select * from v1; -ERROR HY000: View 'mysqltest.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v2; -ERROR HY000: View 'mysqltest.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v3; -f2() -NULL -Warnings: -Warning 1329 No data - zero rows fetched, selected, or processed -select * from v4; -f2() -NULL -Warnings: -Warning 1329 No data - zero rows fetched, selected, or processed -select * from v5; -ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -drop view v1, v2, v3, v4, v5; -drop function f2; -drop table t1, t2; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -use mysqltest; -create table t1 (a int); -create table v1 (a int); -insert into t1 values (1); -grant select on t1 to mysqltest_1@localhost; -grant select on v1 to mysqltest_1@localhost; -grant create view on mysqltest.* to mysqltest_1@localhost; -drop table v1; -use mysqltest; -create algorithm=TEMPTABLE view v1 as select *, a as b from t1; -create algorithm=MERGE view v2 as select *, a as b from t1; -create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select *, a as b from t1; -create algorithm=MERGE SQL SECURITY INVOKER view v4 as select *, a as b from t1; -create view v5 as select * from v1; -use test; -revoke select on t1 from mysqltest_1@localhost; -select * from v1; -ERROR HY000: View 'mysqltest.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v2; -ERROR HY000: View 'mysqltest.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v3; -a b -1 1 -select * from v4; -a b -1 1 -select * from v5; -ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -drop table t1; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -create database mysqltest; -use mysqltest; -create table t1 (a int); -insert into t1 values (1); -create algorithm=TEMPTABLE view v1 as select *, a as b from t1; -create algorithm=MERGE view v2 as select *, a as b from t1; -create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select *, a as b from t1; -create algorithm=MERGE SQL SECURITY INVOKER view v4 as select *, a as b from t1; -create SQL SECURITY INVOKER view v5 as select * from v4; -grant select on v1 to mysqltest_1@localhost; -grant select on v2 to mysqltest_1@localhost; -grant select on v3 to mysqltest_1@localhost; -grant select on v4 to mysqltest_1@localhost; -grant select on v5 to mysqltest_1@localhost; -use mysqltest; -select * from v1; -a b -1 1 -select * from v2; -a b -1 1 -select * from v3; -ERROR HY000: View 'mysqltest.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v4; -ERROR HY000: View 'mysqltest.v4' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -select * from v5; -ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -use test; -drop view v1, v2, v3, v4, v5; -drop table t1; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; -drop database mysqltest; -drop view if exists v1; -drop table if exists t1; -create table t1 as select * from mysql.user where user=''; -delete from mysql.user where user=''; -flush privileges; -grant all on test.* to 'test14256'@'%'; -use test; -create view v1 as select 42; -show create view v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`test14256`@`%` SQL SECURITY DEFINER VIEW `v1` AS select 42 AS `42` latin1 latin1_swedish_ci -select definer into @v1def1 from information_schema.views -where table_schema = 'test' and table_name='v1'; -drop view v1; -create definer=`test14256`@`%` view v1 as select 42; -show create view v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`test14256`@`%` SQL SECURITY DEFINER VIEW `v1` AS select 42 AS `42` latin1 latin1_swedish_ci -select definer into @v1def2 from information_schema.views -where table_schema = 'test' and table_name='v1'; -drop view v1; -select @v1def1, @v1def2, @v1def1=@v1def2; -@v1def1 @v1def2 @v1def1=@v1def2 -test14256@% test14256@% 1 -drop user test14256; -insert into mysql.user select * from t1; -flush privileges; -drop table t1; -create database mysqltest; -use mysqltest; -CREATE TABLE t1 (i INT); -CREATE VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci -GRANT SELECT, LOCK TABLES ON mysqltest.* TO mysqltest_1@localhost; -use mysqltest; -LOCK TABLES v1 READ; -SHOW CREATE TABLE v1; -ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' -UNLOCK TABLES; -use test; -use test; -drop user mysqltest_1@localhost; -drop database mysqltest; -create definer=some_user@`` sql security invoker view v1 as select 1; -Warnings: -Note 1449 The user specified as a definer ('some_user'@'') does not exist -create definer=some_user@localhost sql security invoker view v2 as select 1; -Warnings: -Note 1449 The user specified as a definer ('some_user'@'localhost') does not exist -show create view v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1` latin1 latin1_swedish_ci -show create view v2; -View Create View character_set_client collation_connection -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1` latin1 latin1_swedish_ci -drop view v1; -drop view v2; -CREATE DATABASE mysqltest1; -CREATE USER readonly@localhost; -CREATE TABLE mysqltest1.t1 (x INT); -INSERT INTO mysqltest1.t1 VALUES (1), (2); -CREATE SQL SECURITY INVOKER VIEW mysqltest1.v_t1 AS SELECT * FROM mysqltest1.t1; -CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ts AS SELECT * FROM mysqltest1.t1; -CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_ti AS SELECT * FROM mysqltest1.t1; -CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tu AS SELECT * FROM mysqltest1.t1; -CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tus AS SELECT * FROM mysqltest1.t1; -CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_td AS SELECT * FROM mysqltest1.t1; -CREATE SQL SECURITY DEFINER VIEW mysqltest1.v_tds AS SELECT * FROM mysqltest1.t1; -GRANT SELECT, INSERT, UPDATE, DELETE ON mysqltest1.v_t1 TO readonly@localhost; -GRANT SELECT ON mysqltest1.v_ts TO readonly@localhost; -GRANT INSERT ON mysqltest1.v_ti TO readonly@localhost; -GRANT UPDATE ON mysqltest1.v_tu TO readonly@localhost; -GRANT UPDATE,SELECT ON mysqltest1.v_tus TO readonly@localhost; -GRANT DELETE ON mysqltest1.v_td TO readonly@localhost; -GRANT DELETE,SELECT ON mysqltest1.v_tds TO readonly@localhost; -SELECT * FROM mysqltest1.v_t1; -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -INSERT INTO mysqltest1.v_t1 VALUES(4); -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -DELETE FROM mysqltest1.v_t1 WHERE x = 1; -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -UPDATE mysqltest1.v_t1 SET x = 3 WHERE x = 2; -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -UPDATE mysqltest1.v_t1 SET x = 3; -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -DELETE FROM mysqltest1.v_t1; -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -SELECT 1 FROM mysqltest1.v_t1; -ERROR HY000: View 'mysqltest1.v_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -SELECT * FROM mysqltest1.t1; -ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 't1' -SELECT * FROM mysqltest1.v_ts; -x -1 -2 -SELECT * FROM mysqltest1.v_ts, mysqltest1.t1 WHERE mysqltest1.t1.x = mysqltest1.v_ts.x; -ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 't1' -SELECT * FROM mysqltest1.v_ti; -ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for table 'v_ti' -INSERT INTO mysqltest1.v_ts VALUES (100); -ERROR 42000: INSERT command denied to user 'readonly'@'localhost' for table 'v_ts' -INSERT INTO mysqltest1.v_ti VALUES (100); -UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100; -ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts' -UPDATE mysqltest1.v_ts SET x= 200; -ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts' -UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100; -UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100; -UPDATE mysqltest1.v_tu SET x= 200; -DELETE FROM mysqltest1.v_ts WHERE x= 200; -ERROR 42000: DELETE command denied to user 'readonly'@'localhost' for table 'v_ts' -DELETE FROM mysqltest1.v_ts; -ERROR 42000: DELETE command denied to user 'readonly'@'localhost' for table 'v_ts' -DELETE FROM mysqltest1.v_td WHERE x= 200; -ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_td' -DELETE FROM mysqltest1.v_tds WHERE x= 200; -DELETE FROM mysqltest1.v_td; -DROP VIEW mysqltest1.v_tds; -DROP VIEW mysqltest1.v_td; -DROP VIEW mysqltest1.v_tus; -DROP VIEW mysqltest1.v_tu; -DROP VIEW mysqltest1.v_ti; -DROP VIEW mysqltest1.v_ts; -DROP VIEW mysqltest1.v_t1; -DROP TABLE mysqltest1.t1; -DROP USER readonly@localhost; -DROP DATABASE mysqltest1; -CREATE TABLE t1 (a INT PRIMARY KEY); -INSERT INTO t1 VALUES (1), (2), (3); -CREATE DEFINER = 'no-such-user'@localhost VIEW v AS SELECT a from t1; -Warnings: -Note 1449 The user specified as a definer ('no-such-user'@'localhost') does not exist -SHOW CREATE VIEW v; -View Create View character_set_client collation_connection -v CREATE ALGORITHM=UNDEFINED DEFINER=`no-such-user`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select `test`.`t1`.`a` AS `a` from `t1` latin1 latin1_swedish_ci -Warnings: -Note 1449 The user specified as a definer ('no-such-user'@'localhost') does not exist -SELECT * FROM v; -ERROR HY000: The user specified as a definer ('no-such-user'@'localhost') does not exist -DROP VIEW v; -DROP TABLE t1; -USE test; -CREATE USER mysqltest_db1@localhost identified by 'PWD'; -GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION; -CREATE SCHEMA mysqltest_db1 ; -USE mysqltest_db1 ; -CREATE TABLE t1 (f1 INTEGER); -CREATE VIEW view1 AS -SELECT * FROM t1; -SHOW CREATE VIEW view1; -View Create View character_set_client collation_connection -view1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view1` AS select `t1`.`f1` AS `f1` from `t1` latin1 latin1_swedish_ci -CREATE VIEW view2 AS -SELECT * FROM view1; -# Here comes a suspicious warning -SHOW CREATE VIEW view2; -View Create View character_set_client collation_connection -view2 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view2` AS select `view1`.`f1` AS `f1` from `view1` latin1 latin1_swedish_ci -# But the view view2 is usable -SELECT * FROM view2; -f1 -CREATE VIEW view3 AS -SELECT * FROM view2; -SELECT * from view3; -f1 -DROP VIEW mysqltest_db1.view3; -DROP VIEW mysqltest_db1.view2; -DROP VIEW mysqltest_db1.view1; -DROP TABLE mysqltest_db1.t1; -DROP SCHEMA mysqltest_db1; -DROP USER mysqltest_db1@localhost; -CREATE DATABASE test1; -CREATE DATABASE test2; -CREATE TABLE test1.t0 (a VARCHAR(20)) engine=myisam; -CREATE TABLE test2.t1 (a VARCHAR(20)); -CREATE VIEW test2.t3 AS SELECT * FROM test1.t0; -CREATE OR REPLACE VIEW test.v1 AS -SELECT ta.a AS col1, tb.a AS col2 FROM test2.t3 ta, test2.t1 tb; -DROP VIEW test.v1; -DROP VIEW test2.t3; -DROP TABLE test2.t1, test1.t0; -DROP DATABASE test2; -DROP DATABASE test1; -DROP VIEW IF EXISTS v1; -DROP VIEW IF EXISTS v2; -DROP VIEW IF EXISTS v3; -DROP FUNCTION IF EXISTS f1; -DROP FUNCTION IF EXISTS f2; -DROP PROCEDURE IF EXISTS p1; -CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu; -CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER -RETURN CURRENT_USER(); -CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu; -CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER -SET cu= CURRENT_USER(); -CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER -BEGIN -DECLARE cu VARCHAR(77); -CALL p1(cu); -RETURN cu; -END| -CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu; -CREATE USER mysqltest_u1@localhost; -GRANT ALL ON test.* TO mysqltest_u1@localhost; - -The following tests should all return 1. - -SELECT CURRENT_USER() = 'mysqltest_u1@localhost'; -CURRENT_USER() = 'mysqltest_u1@localhost' -1 -SELECT f1() = 'mysqltest_u1@localhost'; -f1() = 'mysqltest_u1@localhost' -1 -CALL p1(@cu); -SELECT @cu = 'mysqltest_u1@localhost'; -@cu = 'mysqltest_u1@localhost' -1 -SELECT f2() = 'mysqltest_u1@localhost'; -f2() = 'mysqltest_u1@localhost' -1 -SELECT cu = 'root@localhost' FROM v1; -cu = 'root@localhost' -1 -SELECT cu = 'root@localhost' FROM v2; -cu = 'root@localhost' -1 -SELECT cu = 'root@localhost' FROM v3; -cu = 'root@localhost' -1 -DROP VIEW v3; -DROP FUNCTION f2; -DROP PROCEDURE p1; -DROP FUNCTION f1; -DROP VIEW v2; -DROP VIEW v1; -DROP USER mysqltest_u1@localhost; -CREATE DATABASE db17254; -USE db17254; -CREATE TABLE t1 (f1 INT); -INSERT INTO t1 VALUES (10),(20); -CREATE USER def_17254@localhost; -GRANT SELECT ON db17254.* TO def_17254@localhost; -CREATE USER inv_17254@localhost; -GRANT SELECT ON db17254.t1 TO inv_17254@localhost; -GRANT CREATE VIEW ON db17254.* TO def_17254@localhost; -CREATE VIEW v1 AS SELECT * FROM t1; -DROP USER def_17254@localhost; -for a user -SELECT * FROM v1; -ERROR 42000: SELECT command denied to user 'inv_17254'@'localhost' for table 'v1' -for a superuser -SELECT * FROM v1; -ERROR HY000: The user specified as a definer ('def_17254'@'localhost') does not exist -DROP USER inv_17254@localhost; -DROP DATABASE db17254; -DROP DATABASE IF EXISTS mysqltest_db1; -DROP DATABASE IF EXISTS mysqltest_db2; -DROP USER mysqltest_u1; -DROP USER mysqltest_u2; -CREATE USER mysqltest_u1@localhost; -CREATE USER mysqltest_u2@localhost; -CREATE DATABASE mysqltest_db1; -CREATE DATABASE mysqltest_db2; -GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost WITH GRANT OPTION; -GRANT ALL ON mysqltest_db2.* TO mysqltest_u2@localhost; -CREATE TABLE t1 (i INT); -INSERT INTO t1 VALUES (1); -CREATE VIEW v1 AS SELECT i FROM t1 WHERE 1 IN (SELECT * FROM t1); -CREATE TABLE t2 (s CHAR(7)); -INSERT INTO t2 VALUES ('public'); -GRANT SELECT ON v1 TO mysqltest_u2@localhost; -GRANT SELECT ON t2 TO mysqltest_u2@localhost; -SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2; -i s -1 public -PREPARE stmt1 FROM "SELECT * FROM mysqltest_db1.t2"; -EXECUTE stmt1; -s -public -PREPARE stmt2 FROM "SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2"; -EXECUTE stmt2; -i s -1 public -REVOKE SELECT ON t2 FROM mysqltest_u2@localhost; -UPDATE t2 SET s = 'private' WHERE s = 'public'; -SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2; -ERROR 42000: SELECT command denied to user 'mysqltest_u2'@'localhost' for table 't2' -EXECUTE stmt1; -ERROR 42000: SELECT command denied to user 'mysqltest_u2'@'localhost' for table 't2' -EXECUTE stmt2; -ERROR 42000: SELECT command denied to user 'mysqltest_u2'@'localhost' for table 't2' -REVOKE ALL ON mysqltest_db1.* FROM mysqltest_u1@localhost; -REVOKE ALL ON mysqltest_db2.* FROM mysqltest_u2@localhost; -DROP DATABASE mysqltest_db1; -DROP DATABASE mysqltest_db2; -DROP USER mysqltest_u1@localhost; -DROP USER mysqltest_u2@localhost; -CREATE DATABASE db26813; -USE db26813; -CREATE TABLE t1(f1 INT, f2 INT); -CREATE VIEW v1 AS SELECT f1 FROM t1; -CREATE VIEW v2 AS SELECT f1 FROM t1; -CREATE VIEW v3 AS SELECT f1 FROM t1; -CREATE USER u26813@localhost; -GRANT DROP ON db26813.v1 TO u26813@localhost; -GRANT CREATE VIEW ON db26813.v2 TO u26813@localhost; -GRANT DROP, CREATE VIEW ON db26813.v3 TO u26813@localhost; -GRANT SELECT ON db26813.t1 TO u26813@localhost; -ALTER VIEW v1 AS SELECT f2 FROM t1; -ERROR 42000: CREATE VIEW command denied to user 'u26813'@'localhost' for table 'v1' -ALTER VIEW v2 AS SELECT f2 FROM t1; -ERROR 42000: DROP command denied to user 'u26813'@'localhost' for table 'v2' -ALTER VIEW v3 AS SELECT f2 FROM t1; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation -SHOW CREATE VIEW v3; -View Create View character_set_client collation_connection -v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`f1` AS `f1` from `t1` latin1 latin1_swedish_ci -DROP USER u26813@localhost; -DROP DATABASE db26813; -# -# Bug#29908 A user can gain additional access through the ALTER VIEW. -# -CREATE DATABASE mysqltest_29908; -USE mysqltest_29908; -CREATE TABLE t1(f1 INT, f2 INT); -CREATE USER u29908_1@localhost; -CREATE DEFINER = u29908_1@localhost VIEW v1 AS SELECT f1 FROM t1; -CREATE DEFINER = u29908_1@localhost SQL SECURITY INVOKER VIEW v2 AS -SELECT f1 FROM t1; -GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v1 TO u29908_1@localhost; -GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_1@localhost; -GRANT SELECT ON mysqltest_29908.t1 TO u29908_1@localhost; -CREATE USER u29908_2@localhost; -GRANT SELECT, DROP, CREATE VIEW ON mysqltest_29908.v1 TO u29908_2@localhost; -GRANT SELECT, DROP, CREATE VIEW, SHOW VIEW ON mysqltest_29908.v2 TO u29908_2@localhost; -GRANT SELECT ON mysqltest_29908.t1 TO u29908_2@localhost; -ALTER VIEW v1 AS SELECT f2 FROM t1; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation -ALTER VIEW v2 AS SELECT f2 FROM t1; -ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation -SHOW CREATE VIEW v2; -View Create View character_set_client collation_connection -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select `t1`.`f1` AS `f1` from `t1` latin1 latin1_swedish_ci -ALTER VIEW v1 AS SELECT f2 FROM t1; -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f2` AS `f2` from `t1` latin1 latin1_swedish_ci -ALTER VIEW v2 AS SELECT f2 FROM t1; -SHOW CREATE VIEW v2; -View Create View character_set_client collation_connection -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select `t1`.`f2` AS `f2` from `t1` latin1 latin1_swedish_ci -ALTER VIEW v1 AS SELECT f1 FROM t1; -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` latin1 latin1_swedish_ci -ALTER VIEW v2 AS SELECT f1 FROM t1; -SHOW CREATE VIEW v2; -View Create View character_set_client collation_connection -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`u29908_1`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select `t1`.`f1` AS `f1` from `t1` latin1 latin1_swedish_ci -DROP USER u29908_1@localhost; -DROP USER u29908_2@localhost; -DROP DATABASE mysqltest_29908; -####################################################################### -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; -CREATE DATABASE mysqltest1; -CREATE DATABASE mysqltest2; -CREATE TABLE mysqltest1.t1(c1 INT); -CREATE TABLE mysqltest1.t2(c2 INT); -CREATE TABLE mysqltest1.t3(c3 INT); -CREATE TABLE mysqltest1.t4(c4 INT); -INSERT INTO mysqltest1.t1 VALUES (11), (12), (13), (14); -INSERT INTO mysqltest1.t2 VALUES (21), (22), (23), (24); -INSERT INTO mysqltest1.t3 VALUES (31), (32), (33), (34); -INSERT INTO mysqltest1.t4 VALUES (41), (42), (43), (44); -GRANT SELECT ON mysqltest1.t1 TO mysqltest_u1@localhost; -GRANT INSERT ON mysqltest1.t2 TO mysqltest_u1@localhost; -GRANT SELECT, UPDATE ON mysqltest1.t3 TO mysqltest_u1@localhost; -GRANT SELECT, DELETE ON mysqltest1.t4 TO mysqltest_u1@localhost; -GRANT ALL PRIVILEGES ON mysqltest2.* TO mysqltest_u1@localhost; - ----> connection: bug24040_con -SELECT * FROM mysqltest1.t1; -c1 -11 -12 -13 -14 -INSERT INTO mysqltest1.t2 VALUES(25); -UPDATE mysqltest1.t3 SET c3 = 331 WHERE c3 = 31; -DELETE FROM mysqltest1.t4 WHERE c4 = 44; -CREATE VIEW v1 AS SELECT * FROM mysqltest1.t1; -CREATE VIEW v2 AS SELECT * FROM mysqltest1.t2; -CREATE VIEW v3 AS SELECT * FROM mysqltest1.t3; -CREATE VIEW v4 AS SELECT * FROM mysqltest1.t4; -SELECT * FROM v1; -c1 -11 -12 -13 -14 -INSERT INTO v2 VALUES(26); -UPDATE v3 SET c3 = 332 WHERE c3 = 32; -DELETE FROM v4 WHERE c4 = 43; -CREATE VIEW v12 AS SELECT c1, c2 FROM mysqltest1.t1, mysqltest1.t2; -ERROR 42000: create view command denied to user 'mysqltest_u1'@'localhost' for column 'c2' in table 'v12' -CREATE VIEW v13 AS SELECT c1, c3 FROM mysqltest1.t1, mysqltest1.t3; -CREATE VIEW v14 AS SELECT c1, c4 FROM mysqltest1.t1, mysqltest1.t4; -CREATE VIEW v21 AS SELECT c2, c1 FROM mysqltest1.t2, mysqltest1.t1; -ERROR 42000: create view command denied to user 'mysqltest_u1'@'localhost' for column 'c1' in table 'v21' -CREATE VIEW v23 AS SELECT c2, c3 FROM mysqltest1.t2, mysqltest1.t3; -ERROR 42000: create view command denied to user 'mysqltest_u1'@'localhost' for column 'c3' in table 'v23' -CREATE VIEW v24 AS SELECT c2, c4 FROM mysqltest1.t2, mysqltest1.t4; -ERROR 42000: create view command denied to user 'mysqltest_u1'@'localhost' for column 'c4' in table 'v24' -CREATE VIEW v31 AS SELECT c3, c1 FROM mysqltest1.t3, mysqltest1.t1; -CREATE VIEW v32 AS SELECT c3, c2 FROM mysqltest1.t3, mysqltest1.t2; -ERROR 42000: create view command denied to user 'mysqltest_u1'@'localhost' for column 'c2' in table 'v32' -CREATE VIEW v34 AS SELECT c3, c4 FROM mysqltest1.t3, mysqltest1.t4; -CREATE VIEW v41 AS SELECT c4, c1 FROM mysqltest1.t4, mysqltest1.t1; -CREATE VIEW v42 AS SELECT c4, c2 FROM mysqltest1.t4, mysqltest1.t2; -ERROR 42000: create view command denied to user 'mysqltest_u1'@'localhost' for column 'c2' in table 'v42' -CREATE VIEW v43 AS SELECT c4, c3 FROM mysqltest1.t4, mysqltest1.t3; - ----> connection: default -SELECT * FROM mysqltest1.t1; -c1 -11 -12 -13 -14 -SELECT * FROM mysqltest1.t2; -c2 -21 -22 -23 -24 -25 -26 -SELECT * FROM mysqltest1.t3 order by c3; -c3 -33 -34 -331 -332 -SELECT * FROM mysqltest1.t4; -c4 -41 -42 -DROP DATABASE mysqltest1; -DROP DATABASE mysqltest2; -DROP USER mysqltest_u1@localhost; -End of 5.0 tests. -DROP VIEW IF EXISTS v1; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 (i INT); -CREATE VIEW v1 AS SELECT * FROM t1; -ALTER VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci -ALTER DEFINER=no_such@user_1 VIEW v1 AS SELECT * FROM t1; -Warnings: -Note 1449 The user specified as a definer ('no_such'@'user_1') does not exist -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci -Warnings: -Note 1449 The user specified as a definer ('no_such'@'user_1') does not exist -ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; -Warnings: -Note 1449 The user specified as a definer ('no_such'@'user_1') does not exist -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=MERGE DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci -Warnings: -Note 1449 The user specified as a definer ('no_such'@'user_1') does not exist -ALTER ALGORITHM=TEMPTABLE DEFINER=no_such@user_2 VIEW v1 AS SELECT * FROM t1; -Warnings: -Note 1449 The user specified as a definer ('no_such'@'user_2') does not exist -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`no_such`@`user_2` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci -Warnings: -Note 1449 The user specified as a definer ('no_such'@'user_2') does not exist -DROP VIEW v1; -DROP TABLE t1; -End of 5.1 tests. diff --git a/mysql-test/suite/percona/percona_flush_contiguous_neighbors-master.opt b/mysql-test/suite/percona/percona_flush_contiguous_neighbors-master.opt new file mode 100644 index 00000000000..075af88054f --- /dev/null +++ b/mysql-test/suite/percona/percona_flush_contiguous_neighbors-master.opt @@ -0,0 +1 @@ +--innodb_flush_neighbor_pages=cont diff --git a/mysql-test/suite/percona/percona_flush_contiguous_neighbors.result b/mysql-test/suite/percona/percona_flush_contiguous_neighbors.result new file mode 100644 index 00000000000..8c6b81f0848 --- /dev/null +++ b/mysql-test/suite/percona/percona_flush_contiguous_neighbors.result @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB; +INSERT INTO t1(foo) VALUES ('a'), ('b'); +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/percona/percona_flush_contiguous_neighbors.test b/mysql-test/suite/percona/percona_flush_contiguous_neighbors.test new file mode 100644 index 00000000000..4eb967fcd16 --- /dev/null +++ b/mysql-test/suite/percona/percona_flush_contiguous_neighbors.test @@ -0,0 +1,37 @@ +# Test for innodb_flush_neighbor_pages=contiguous. +# The test is very crude: we simply overflow the buffer pool with such a number of +# new/modified pages that some flushing is bound to happen. + +--source include/have_innodb.inc +--source include/big_test.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB; + +INSERT INTO t1(foo) VALUES ('a'), ('b'); +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; +INSERT INTO t1(foo) SELECT foo FROM t1; + +# TODO: cannot record a stable value here. A check of > 0 should be enough, +# but the variable is not accessible through INFORMATION_SCHEMA currently. +# SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_flushed'; + +DROP TABLE t1; diff --git a/mysql-test/suite/percona/percona_query_response_time-replication.result b/mysql-test/suite/percona/percona_query_response_time-replication.result index c00520110c2..a6e88be6103 100644 --- a/mysql-test/suite/percona/percona_query_response_time-replication.result +++ b/mysql-test/suite/percona/percona_query_response_time-replication.result @@ -100,10 +100,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -146,10 +146,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; @@ -251,10 +251,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -297,10 +297,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; @@ -375,7 +375,7 @@ SHOW QUERY_RESPONSE_TIME; 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -391,7 +391,7 @@ time count total 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; @@ -469,7 +469,7 @@ SHOW QUERY_RESPONSE_TIME; 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -488,7 +488,7 @@ time count total 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; @@ -556,7 +556,7 @@ SHOW QUERY_RESPONSE_TIME; 1.000000 34 12.250000 156.000000 33 77.099997 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -565,7 +565,7 @@ time count total 1.000000 34 12.250000 156.000000 33 77.099997 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; @@ -632,7 +632,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 34 12.250000 1000.000000 33 77.099997 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -640,7 +640,7 @@ time count total 0.001000 0 0.000000 1.000000 34 12.250000 1000.000000 33 77.099997 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; @@ -709,7 +709,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 34 12.250000 1000.000000 33 77.099997 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -717,7 +717,7 @@ time count total 0.001000 0 0.000000 1.000000 34 12.250000 1000.000000 33 77.099997 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; diff --git a/mysql-test/suite/percona/percona_query_response_time-stored.result b/mysql-test/suite/percona/percona_query_response_time-stored.result index 7385231241e..fb458d6e7ab 100644 --- a/mysql-test/suite/percona/percona_query_response_time-stored.result +++ b/mysql-test/suite/percona/percona_query_response_time-stored.result @@ -80,10 +80,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -126,10 +126,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -204,10 +204,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -250,10 +250,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -301,7 +301,7 @@ SHOW QUERY_RESPONSE_TIME; 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -317,7 +317,7 @@ time count total 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -368,7 +368,7 @@ SHOW QUERY_RESPONSE_TIME; 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -387,7 +387,7 @@ time count total 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -428,7 +428,7 @@ SHOW QUERY_RESPONSE_TIME; 1.000000 55 8.450000 156.000000 11 25.699999 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -437,7 +437,7 @@ time count total 1.000000 55 8.450000 156.000000 11 25.699999 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -477,7 +477,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 55 8.450000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -485,7 +485,7 @@ time count total 0.001000 0 0.000000 1.000000 55 8.450000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -527,7 +527,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 55 8.450000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -535,7 +535,7 @@ time count total 0.001000 0 0.000000 1.000000 55 8.450000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; diff --git a/mysql-test/suite/percona/percona_query_response_time.result b/mysql-test/suite/percona/percona_query_response_time.result index 4c4d50319c0..1eb90d3cdd4 100644 --- a/mysql-test/suite/percona/percona_query_response_time.result +++ b/mysql-test/suite/percona/percona_query_response_time.result @@ -45,10 +45,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -91,10 +91,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -231,10 +231,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -277,10 +277,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -328,10 +328,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -374,10 +374,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -514,10 +514,10 @@ SHOW QUERY_RESPONSE_TIME; 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -560,10 +560,10 @@ time count total 131072.000000 0 0.000000 262144.000000 0 0.000000 524288.000000 0 0.000000 - 1048576.00000 0 0.000000 - 2097152.00000 0 0.000000 - 4194304.00000 0 0.000000 - 8388608.00000 0 0.000000 +1048576.000000 0 0.000000 +2097152.000000 0 0.000000 +4194304.000000 0 0.000000 +8388608.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -584,7 +584,7 @@ SHOW QUERY_RESPONSE_TIME; 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -600,7 +600,7 @@ time count total 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -710,7 +710,7 @@ SHOW QUERY_RESPONSE_TIME; 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -726,7 +726,7 @@ time count total 1000.000000 0 0.000000 10000.000000 0 0.000000 100000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -750,7 +750,7 @@ SHOW QUERY_RESPONSE_TIME; 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -769,7 +769,7 @@ time count total 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -882,7 +882,7 @@ SHOW QUERY_RESPONSE_TIME; 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -901,7 +901,7 @@ time count total 16807.000000 0 0.000000 117649.000000 0 0.000000 823543.000000 0 0.000000 - 5764801.00000 0 0.000000 +5764801.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -915,7 +915,7 @@ SHOW QUERY_RESPONSE_TIME; 1.000000 0 0.000000 156.000000 0 0.000000 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -924,7 +924,7 @@ time count total 1.000000 0 0.000000 156.000000 0 0.000000 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -1027,7 +1027,7 @@ SHOW QUERY_RESPONSE_TIME; 1.000000 11 4.050000 156.000000 11 25.699999 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -1036,7 +1036,7 @@ time count total 1.000000 11 4.050000 156.000000 11 25.699999 24336.000000 0 0.000000 - 3796416.00000 0 0.000000 +3796416.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -1049,7 +1049,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 0 0.000000 1000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -1057,7 +1057,7 @@ time count total 0.001000 0 0.000000 1.000000 0 0.000000 1000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -1159,7 +1159,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 11 4.050000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -1167,7 +1167,7 @@ time count total 0.001000 0 0.000000 1.000000 11 4.050000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET SESSION query_exec_time=0.1; @@ -1182,7 +1182,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 0 0.000000 1000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -1190,7 +1190,7 @@ time count total 0.001000 0 0.000000 1.000000 0 0.000000 1000.000000 0 0.000000 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; SET SESSION query_exec_time=0.31; @@ -1292,7 +1292,7 @@ SHOW QUERY_RESPONSE_TIME; 0.001000 0 0.000000 1.000000 11 4.050000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; time count total @@ -1300,7 +1300,7 @@ time count total 0.001000 0 0.000000 1.000000 11 4.050000 1000.000000 11 25.699999 - 1000000.00000 0 0.000000 +1000000.000000 0 0.000000 TOO LONG 0 TOO LONG SET SESSION query_exec_time=default; SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; diff --git a/mysql-test/suite/percona/percona_server_variables_debug.result b/mysql-test/suite/percona/percona_server_variables_debug.result index ea1c02e7716..ae02a48c8fa 100644 --- a/mysql-test/suite/percona/percona_server_variables_debug.result +++ b/mysql-test/suite/percona/percona_server_variables_debug.result @@ -109,6 +109,7 @@ INNODB_FILE_FORMAT INNODB_FILE_FORMAT_CHECK INNODB_FILE_FORMAT_MAX INNODB_FILE_PER_TABLE +INNODB_FLUSH_CHECKPOINT_DEBUG INNODB_FLUSH_LOG_AT_TRX_COMMIT INNODB_FLUSH_METHOD INNODB_FLUSH_NEIGHBOR_PAGES @@ -228,6 +229,7 @@ MAX_SP_RECURSION_DEPTH MAX_TMP_TABLES MAX_USER_CONNECTIONS MAX_WRITE_LOCK_COUNT +METADATA_LOCKS_CACHE_SIZE MIN_EXAMINED_ROW_LIMIT MULTI_RANGE_COUNT MYISAM_DATA_POINTER_SIZE diff --git a/mysql-test/suite/percona/percona_server_variables_release.result b/mysql-test/suite/percona/percona_server_variables_release.result index e5965cf7e5e..29ac402c144 100644 --- a/mysql-test/suite/percona/percona_server_variables_release.result +++ b/mysql-test/suite/percona/percona_server_variables_release.result @@ -225,6 +225,7 @@ MAX_SP_RECURSION_DEPTH MAX_TMP_TABLES MAX_USER_CONNECTIONS MAX_WRITE_LOCK_COUNT +METADATA_LOCKS_CACHE_SIZE MIN_EXAMINED_ROW_LIMIT MULTI_RANGE_COUNT MYISAM_DATA_POINTER_SIZE diff --git a/mysql-test/suite/percona/percona_sync_flush.result b/mysql-test/suite/percona/percona_sync_flush.result new file mode 100644 index 00000000000..12335257b32 --- /dev/null +++ b/mysql-test/suite/percona/percona_sync_flush.result @@ -0,0 +1,35 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB; +SET @@global.innodb_flush_checkpoint_debug=1; +INSERT INTO t1(foo) VALUES ('a'), ('b'); +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +INSERT INTO t1(foo) SELECT foo FROM t1; +UPDATE t1 SET foo='c'; +SET @@global.innodb_flush_checkpoint_debug=0; +UPDATE t1 SET foo='d' WHERE foo='c'; +DROP TABLE t1; diff --git a/mysql-test/suite/percona/percona_sync_flush.test b/mysql-test/suite/percona/percona_sync_flush.test new file mode 100644 index 00000000000..35e8d8f92d2 --- /dev/null +++ b/mysql-test/suite/percona/percona_sync_flush.test @@ -0,0 +1,33 @@ +# Test for InnoDB sync state flushing. + +--source include/have_innodb.inc +--source include/have_debug.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB; + +# It is hard to get to InnoDB sync state flushing in MTR with regular workload. Perhaps +# it is possible with many parallel connections, but that would be brittle anyway. +# So, just disable preflushing and checkpointing and issue simple workload. +SET @@global.innodb_flush_checkpoint_debug=1; + +INSERT INTO t1(foo) VALUES ('a'), ('b'); + +let $rep=0; +while ($rep < 14) +{ + INSERT INTO t1(foo) SELECT foo FROM t1; + UPDATE t1 SET foo='c'; + inc $rep; +} + +# By now checkpoint age should be well past sync flush point. Allow +# preflushing/checkpointing again and do some work in order to do the sync flush. +SET @@global.innodb_flush_checkpoint_debug=0; + +UPDATE t1 SET foo='d' WHERE foo='c'; + +DROP TABLE t1; diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.inc b/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.inc index d55e52d5b64..d9804722147 100644 --- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.inc +++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.inc @@ -91,5 +91,27 @@ let $query=select * from t1 -- comment in the end ; --source percona_query_cache_with_comments_eval.inc +let $query=select */* a comment \*/from t1; +--source include/percona_query_cache_with_comments_eval.inc + +let $query=select *# a comment \\ +from t1; +--source include/percona_query_cache_with_comments_eval.inc + +let $query=select *-- a comment \\ +from t1; +--source include/percona_query_cache_with_comments_eval.inc + +let $query=select "\\\\"" /* not a comment */" from t1; +--source include/percona_query_cache_with_comments_eval.inc + +let $query=select "\\\\"" /*! not a comment */" from t1; +--source include/percona_query_cache_with_comments_eval.inc + +# following two queries related to bug #856404. +# There are different queries, but opt_query_cache_strip_comments thinks that they are equal. let $query=select ' \' ' from t1; --source percona_query_cache_with_comments_eval.inc + +let $query=select ' \' /* comment inside quotes with internal backslash quote */' from t1; +--source percona_query_cache_with_comments_eval.inc diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.result b/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.result index 169fdf80fef..d1a6ded08d7 100644 --- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.result +++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments.result @@ -831,7 +831,7 @@ show status like "Qcache_hits"; Variable_name Value Qcache_hits 50 ----------------------------------------------------- -select ' \' ' from t1 +select */* a comment \*/from t1 ----------------------------------------------------- show status like "Qcache_queries_in_cache"; Variable_name Value @@ -842,6 +842,167 @@ Qcache_inserts 1 show status like "Qcache_hits"; Variable_name Value Qcache_hits 50 +select */* a comment \*/from t1; +a +1 +2 +3 +select */* a comment \*/from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 52 +----------------------------------------------------- +select *# a comment \ +from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 52 +select *# a comment \ +from t1; +a +1 +2 +3 +select *# a comment \ +from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 54 +----------------------------------------------------- +select *-- a comment \ +from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 54 +select *-- a comment \ +from t1; +a +1 +2 +3 +select *-- a comment \ +from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 56 +----------------------------------------------------- +select "\\"" /* not a comment */" from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 56 +select "\\"" /* not a comment */" from t1; +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +select "\\"" /* not a comment */" from t1; +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 57 +----------------------------------------------------- +select "\\"" /*! not a comment */" from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 2 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 57 +select "\\"" /*! not a comment */" from t1; +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +select "\\"" /*! not a comment */" from t1; +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 3 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 58 +----------------------------------------------------- +select ' \' ' from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 3 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 3 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 58 select ' \' ' from t1; ' ' @@ -854,13 +1015,44 @@ select ' \' ' from t1; ' show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 2 +Qcache_queries_in_cache 4 show status like "Qcache_inserts"; Variable_name Value -Qcache_inserts 2 +Qcache_inserts 4 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 51 +Qcache_hits 59 +----------------------------------------------------- +select ' \' /* comment inside quotes with internal backslash quote */' from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 4 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 4 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 59 +select ' \' /* comment inside quotes with internal backslash quote */' from t1; +' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ +select ' \' /* comment inside quotes with internal backslash quote */' from t1; +' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 5 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 5 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 60 DROP TABLE t1; SET GLOBAL query_cache_size=default; set global query_cache_strip_comments=OFF; diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments_disable.result b/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments_disable.result index a13a44d9a1c..7e793a942c5 100644 --- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments_disable.result +++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_query_cache_with_comments_disable.result @@ -830,7 +830,7 @@ show status like "Qcache_hits"; Variable_name Value Qcache_hits 25 ----------------------------------------------------- -select ' \' ' from t1 +select */* a comment \*/from t1 ----------------------------------------------------- show status like "Qcache_queries_in_cache"; Variable_name Value @@ -841,6 +841,167 @@ Qcache_inserts 20 show status like "Qcache_hits"; Variable_name Value Qcache_hits 25 +select */* a comment \*/from t1; +a +1 +2 +3 +select */* a comment \*/from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 21 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 21 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 26 +----------------------------------------------------- +select *# a comment \ +from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 21 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 21 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 26 +select *# a comment \ +from t1; +a +1 +2 +3 +select *# a comment \ +from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 22 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 22 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 27 +----------------------------------------------------- +select *-- a comment \ +from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 22 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 22 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 27 +select *-- a comment \ +from t1; +a +1 +2 +3 +select *-- a comment \ +from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 23 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 23 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 28 +----------------------------------------------------- +select "\\"" /* not a comment */" from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 23 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 23 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 28 +select "\\"" /* not a comment */" from t1; +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +select "\\"" /* not a comment */" from t1; +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +\" /* not a comment */ +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 24 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 24 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 29 +----------------------------------------------------- +select "\\"" /*! not a comment */" from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 24 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 24 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 29 +select "\\"" /*! not a comment */" from t1; +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +select "\\"" /*! not a comment */" from t1; +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +\" /*! not a comment */ +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 25 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 25 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 30 +----------------------------------------------------- +select ' \' ' from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 25 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 25 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 30 select ' \' ' from t1; ' ' @@ -853,13 +1014,44 @@ select ' \' ' from t1; ' show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 21 +Qcache_queries_in_cache 26 show status like "Qcache_inserts"; Variable_name Value -Qcache_inserts 21 +Qcache_inserts 26 show status like "Qcache_hits"; Variable_name Value -Qcache_hits 26 +Qcache_hits 31 +----------------------------------------------------- +select ' \' /* comment inside quotes with internal backslash quote */' from t1 +----------------------------------------------------- +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 26 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 26 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 31 +select ' \' /* comment inside quotes with internal backslash quote */' from t1; +' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ +select ' \' /* comment inside quotes with internal backslash quote */' from t1; +' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ + ' /* comment inside quotes with internal backslash quote */ +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 27 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 27 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 32 DROP TABLE t1; SET GLOBAL query_cache_size=default; set global query_cache_strip_comments=OFF; diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result index 678ed685a5b..c243b8ad02f 100644 --- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result +++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.result @@ -3,21 +3,18 @@ flush query cache; flush query cache; reset query cache; flush status; -DROP TABLE IF EXISTS t; -CREATE TABLE t(id INT, number INT); -INSERT INTO t VALUES (0,1); -INSERT INTO t VALUES (1,2); -INSERT INTO t VALUES (2,3); -SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep"; -SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready'; -SELECT number from t where id > 0; -SHOW PROCESSLIST; -Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read -### root ### test Query ### NULL SHOW PROCESSLIST ### ### ### -### root ### test Query ### Waiting on query cache mutex SELECT number from t where id > 0 ### ### ### -SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; -id info state -### SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id executing -### SELECT number from t where id > 0 Waiting on query cache mutex -DROP TABLE t; +SET DEBUG_SYNC='after_query_cache_mutex SIGNAL mutex_locked WAIT_FOR unlock_mutex'; +SELECT "mutex_locked_query" as action; +SET DEBUG_SYNC='now WAIT_FOR mutex_locked'; +SET DEBUG_SYNC='before_query_cache_mutex SIGNAL try_lock_mutex'; +SELECT "try_lock_mutex_query" as action; +SET DEBUG_SYNC='now WAIT_FOR try_lock_mutex'; +SELECT SQL_NO_CACHE state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE info='SELECT "try_lock_mutex_query" as action'; +state +Waiting on query cache mutex +SET DEBUG_SYNC='now SIGNAL unlock_mutex'; +action +mutex_locked_query +action +try_lock_mutex_query SET GLOBAL query_cache_size=0; diff --git a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test index 1e586ca4e7a..b20f088d6ae 100644 --- a/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test +++ b/mysql-test/suite/percona/query_cache_enhance.patch/percona_status_wait_query_cache_mutex.test @@ -3,29 +3,33 @@ --source include/have_debug_sync.inc SET GLOBAL query_cache_size=1355776; --source include/percona_query_cache_with_comments_clear.inc +--let try_lock_mutex_query=SELECT "try_lock_mutex_query" as action --- disable_warnings -DROP TABLE IF EXISTS t; --- enable_warnings -CREATE TABLE t(id INT, number INT); -INSERT INTO t VALUES (0,1); -INSERT INTO t VALUES (1,2); -INSERT INTO t VALUES (2,3); +--connect (mutex_locked_conn, localhost, root,,) +--connect (try_mutex_lock_conn, localhost, root,,) ---connect (conn,localhost,root,,) - ---connection conn -SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep"; -SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready'; -SEND SELECT number from t where id > 0; +--connection mutex_locked_conn +SET DEBUG_SYNC='after_query_cache_mutex SIGNAL mutex_locked WAIT_FOR unlock_mutex'; +send SELECT "mutex_locked_query" as action; --connection default ---replace_column 1 ### 3 ### 6 ### 9 ### 10 ### 11 ### -SHOW PROCESSLIST; +SET DEBUG_SYNC='now WAIT_FOR mutex_locked'; ---replace_column 1 ### -SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; +--connection try_mutex_lock_conn +SET DEBUG_SYNC='before_query_cache_mutex SIGNAL try_lock_mutex'; +send_eval $try_lock_mutex_query; ---disconnect conn -DROP TABLE t; +--connection default +SET DEBUG_SYNC='now WAIT_FOR try_lock_mutex'; +eval SELECT SQL_NO_CACHE state FROM INFORMATION_SCHEMA.PROCESSLIST WHERE info='$try_lock_mutex_query'; +SET DEBUG_SYNC='now SIGNAL unlock_mutex'; + +--connection mutex_locked_conn +reap; +--connection try_mutex_lock_conn +reap; + +--connection default +--disconnect mutex_locked_conn +--disconnect try_mutex_lock_conn SET GLOBAL query_cache_size=0; diff --git a/mysql-test/suite/perfschema/r/all_instances.result b/mysql-test/suite/perfschema/r/all_instances.result index 7eb2bc73d8e..59b1950cb88 100644 --- a/mysql-test/suite/perfschema/r/all_instances.result +++ b/mysql-test/suite/perfschema/r/all_instances.result @@ -1,5 +1,8 @@ use performance_schema; -select name from mutex_instances where name not rlike '/(DEBUG_SYNC::mutex)$' group by name; +select name from mutex_instances +where name not rlike '/(DEBUG_SYNC::mutex)$' + and name != 'wait/synch/mutex/mysys/BITMAP::mutex' + group by name; name wait/synch/mutex/archive/archive_mutex wait/synch/mutex/aria/LOCK_trn_list @@ -16,7 +19,6 @@ wait/synch/mutex/blackhole/blackhole wait/synch/mutex/csv/tina wait/synch/mutex/memory/HP_SHARE::intern_lock wait/synch/mutex/myisam/MYISAM_SHARE::intern_lock -wait/synch/mutex/mysys/BITMAP::mutex wait/synch/mutex/mysys/KEY_CACHE::cache_lock wait/synch/mutex/mysys/LOCK_alarm wait/synch/mutex/mysys/LOCK_uuid_generator @@ -51,7 +53,6 @@ wait/synch/mutex/sql/LOCK_global_index_stats wait/synch/mutex/sql/LOCK_global_system_variables wait/synch/mutex/sql/LOCK_global_table_stats wait/synch/mutex/sql/LOCK_global_user_client_stats -wait/synch/mutex/sql/LOCK_manager wait/synch/mutex/sql/LOCK_open wait/synch/mutex/sql/LOCK_plugin wait/synch/mutex/sql/LOCK_prepared_stmt_count @@ -112,7 +113,6 @@ wait/synch/cond/mysys/COND_alarm wait/synch/cond/mysys/my_thread_var::suspend wait/synch/cond/mysys/THR_COND_threads wait/synch/cond/sql/COND_flush_thread_cache -wait/synch/cond/sql/COND_manager wait/synch/cond/sql/COND_queue_state wait/synch/cond/sql/COND_rpl_status wait/synch/cond/sql/COND_server_started diff --git a/mysql-test/suite/perfschema/r/server_init.result b/mysql-test/suite/perfschema/r/server_init.result index 3e67915adcd..5497267080e 100644 --- a/mysql-test/suite/perfschema/r/server_init.result +++ b/mysql-test/suite/perfschema/r/server_init.result @@ -82,7 +82,7 @@ count(name) select count(name) from mutex_instances where name like "wait/synch/mutex/sql/LOCK_manager"; count(name) -1 +0 select count(name) from mutex_instances where name like "wait/synch/mutex/sql/LOCK_global_system_variables"; count(name) @@ -170,7 +170,7 @@ count(name) select count(name) from cond_instances where name like "wait/synch/cond/sql/COND_manager"; count(name) -1 +0 select count(name) from cond_instances where name like "wait/synch/cond/sql/COND_thread_cache"; count(name) diff --git a/mysql-test/suite/perfschema/t/all_instances.test b/mysql-test/suite/perfschema/t/all_instances.test index d5dc6ffc2b2..53d542b6650 100644 --- a/mysql-test/suite/perfschema/t/all_instances.test +++ b/mysql-test/suite/perfschema/t/all_instances.test @@ -18,7 +18,10 @@ use performance_schema; # "where" filters out instances that can be conditionally compiled out # -select name from mutex_instances where name not rlike '/(DEBUG_SYNC::mutex)$' group by name; +select name from mutex_instances + where name not rlike '/(DEBUG_SYNC::mutex)$' + and name != 'wait/synch/mutex/mysys/BITMAP::mutex' + group by name; # CRYPTO_dynlock_value::lock exists only when building with OpenSSL (not YaSSL). select name from rwlock_instances where name not in ("wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock") diff --git a/mysql-test/suite/plugins/r/unix_socket.result b/mysql-test/suite/plugins/r/unix_socket.result new file mode 100644 index 00000000000..45bf608cc93 --- /dev/null +++ b/mysql-test/suite/plugins/r/unix_socket.result @@ -0,0 +1,30 @@ +install plugin unix_socket soname 'auth_socket.so'; +# +# with named user +# +create user USER identified via unix_socket; +# +# name match = ok +# +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# +# name does not match = failure +# +drop user USER; +# +# and now with anonymous user +# +grant SELECT ON test.* TO '' identified via unix_socket; +# +# name match = ok +# +select user(), current_user(), database(); +user() current_user() database() +USER@localhost @% test +# +# name does not match = failure +# +delete from mysql.user where user=''; +uninstall plugin unix_socket; diff --git a/mysql-test/suite/plugins/t/unix_socket.test b/mysql-test/suite/plugins/t/unix_socket.test new file mode 100644 index 00000000000..fc2e6c5b3c6 --- /dev/null +++ b/mysql-test/suite/plugins/t/unix_socket.test @@ -0,0 +1,56 @@ +--source include/not_embedded.inc + +if (!$AUTH_SOCKET_SO) { + skip No auth_socket plugin; +} + +let $plugindir=`SELECT @@global.plugin_dir`; + +eval install plugin unix_socket soname '$AUTH_SOCKET_SO'; + +--echo # +--echo # with named user +--echo # + +--replace_result $USER USER +eval create user $USER identified via unix_socket; + +--write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt +--replace_result $USER USER +select user(), current_user(), database(); +EOF + +--echo # +--echo # name match = ok +--echo # +--exec $MYSQL_TEST -u $USER --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +--echo # +--echo # name does not match = failure +--echo # +--error 1 +--exec $MYSQL_TEST -u foobar --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +--replace_result $USER USER +eval drop user $USER; + +--echo # +--echo # and now with anonymous user +--echo # +grant SELECT ON test.* TO '' identified via unix_socket; +--echo # +--echo # name match = ok +--echo # +--exec $MYSQL_TEST -u $USER --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +--echo # +--echo # name does not match = failure +--echo # +--error 1 +--exec $MYSQL_TEST -u foobar --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +# restoring mysql.user to the original state. +delete from mysql.user where user=''; +uninstall plugin unix_socket; +--remove_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt + diff --git a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result index 1bee6f2ec1a..bcae1c2c62b 100644 --- a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result +++ b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result @@ -1,12 +1,12 @@ include/master-slave.inc [connection master] +include/stop_slave.inc call mtr.add_suppression("Error in Log_event::read_log_event()"); include/rpl_stop_server.inc [server_number=1] include/rpl_start_server.inc [server_number=1] show binlog events; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log"); -stop slave; reset slave; start slave; include/wait_for_slave_param.inc [Last_IO_Errno] @@ -15,5 +15,5 @@ Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary reset master; stop slave; reset slave; -drop table t; +drop table if exists t; End of the tests diff --git a/mysql-test/suite/rpl/r/rpl_corruption.result b/mysql-test/suite/rpl/r/rpl_corruption.result index 5ecf6b006c9..62f56e70993 100644 --- a/mysql-test/suite/rpl/r/rpl_corruption.result +++ b/mysql-test/suite/rpl/r/rpl_corruption.result @@ -25,14 +25,14 @@ SET GLOBAL debug_dbug="-d,corrupt_read_log_event2"; SET GLOBAL master_verify_checksum=0; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2"; START SLAVE IO_THREAD; -include/wait_for_slave_io_error.inc [errno=1595,1722,1923] +include/wait_for_slave_io_error.inc [errno=1595,1913] SET GLOBAL debug_dbug="-d,corrupt_read_log_event2"; SET GLOBAL debug_dbug= ""; SET GLOBAL master_verify_checksum=1; # 5. Slave. Corruption in network SET GLOBAL debug_dbug="+d,corrupt_queue_event"; START SLAVE IO_THREAD; -include/wait_for_slave_io_error.inc [errno=1595,1722,1923] +include/wait_for_slave_io_error.inc [errno=1595,1913] SET GLOBAL debug_dbug="-d,corrupt_queue_event"; # 6. Slave. Corruption in relay log SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char"; diff --git a/mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result b/mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result index 34024f89617..1bda3bd3ee1 100644 --- a/mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result +++ b/mysql-test/suite/rpl/r/rpl_rotate_purge_deadlock.result @@ -5,6 +5,7 @@ Log_name File_size master-bin.000001 # create table t1 (f text) engine=innodb; SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated'; +SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued'; insert into t1 set f=repeat('a', 4096); *** there must be two logs in the list *** show binary logs; @@ -19,11 +20,14 @@ master-bin.000001 # master-bin.000002 # master-bin.000003 # SET DEBUG_SYNC = 'now SIGNAL rotated'; +SET DEBUG_SYNC = 'now WAIT_FOR continued'; SET DEBUG_SYNC = 'RESET'; SET DEBUG_SYNC = 'RESET'; SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated'; +SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued'; insert into t1 set f=repeat('b', 4096); SET DEBUG_SYNC = 'now SIGNAL rotated'; +SET DEBUG_SYNC = 'now WAIT_FOR continued'; SET DEBUG_SYNC = 'RESET'; SET DEBUG_SYNC = 'RESET'; drop table t1; diff --git a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test index 5e88b163d99..7d05ce251f2 100644 --- a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test +++ b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test @@ -20,9 +20,15 @@ # --source include/not_windows.inc -call mtr.add_suppression("Error in Log_event::read_log_event()"); +--connection slave +# Make sure the slave is stopped while we are messing with master. +# Otherwise we get occasional failures as the slave manages to re-connect +# to the newly started master and we get extra events applied, causing +# conflicts. +--source include/stop_slave.inc --connection master +call mtr.add_suppression("Error in Log_event::read_log_event()"); --let $datadir= `SELECT @@datadir` --let $rpl_server_number= 1 @@ -42,7 +48,6 @@ show binlog events; --connection slave call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log"); -stop slave; reset slave; start slave; @@ -64,6 +69,12 @@ reset master; --connection slave stop slave; reset slave; -drop table t; # table was created from binlog. it does not exist on master. +# The table t may have been created on the slave from binlog. It does not exist +# on the master. +# "May", as it depends on whether the SQL thread had time do do the CREATE +# TABLE before we stopped. +--disable_warnings +drop table if exists t; +--enable_warnings --echo End of the tests diff --git a/mysql-test/suite/rpl/t/rpl_corruption.test b/mysql-test/suite/rpl/t/rpl_corruption.test index 458e3f10e67..c5625b4d002 100644 --- a/mysql-test/suite/rpl/t/rpl_corruption.test +++ b/mysql-test/suite/rpl/t/rpl_corruption.test @@ -115,7 +115,11 @@ SET GLOBAL master_verify_checksum=0; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2"; --connection slave START SLAVE IO_THREAD; -let $slave_io_errno= 1595,1722,1923; +# When the checksum error is detected, the slave sets error code 1913 +# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately +# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io(). +# So we usually get 1595, but it is occasionally possible to get 1913. +let $slave_io_errno= 1595,1913; --source include/wait_for_slave_io_error.inc --connection master SET GLOBAL debug_dbug="-d,corrupt_read_log_event2"; @@ -127,7 +131,7 @@ SET GLOBAL master_verify_checksum=1; --connection slave SET GLOBAL debug_dbug="+d,corrupt_queue_event"; START SLAVE IO_THREAD; -let $slave_io_errno= 1595,1722,1923; +let $slave_io_errno= 1595,1913; --source include/wait_for_slave_io_error.inc SET GLOBAL debug_dbug="-d,corrupt_queue_event"; diff --git a/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test index 429612c405f..a63844b451c 100644 --- a/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test +++ b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test @@ -20,6 +20,7 @@ connection master; source include/show_binary_logs.inc; create table t1 (f text) engine=innodb; SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated'; +SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued'; send insert into t1 set f=repeat('a', 4096); connection master1; @@ -38,6 +39,7 @@ insert into t1 set f=repeat('b', 4096); source include/show_binary_logs.inc; SET DEBUG_SYNC = 'now SIGNAL rotated'; +SET DEBUG_SYNC = 'now WAIT_FOR continued'; SET DEBUG_SYNC = 'RESET'; # the first connection finally completes its INSERT @@ -54,6 +56,7 @@ sync_slave_with_master; connection master; SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated'; +SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued'; send insert into t1 set f=repeat('b', 4096); connection master1; @@ -80,6 +83,7 @@ let $wait_condition= --source include/wait_condition.inc SET DEBUG_SYNC = 'now SIGNAL rotated'; +SET DEBUG_SYNC = 'now WAIT_FOR continued'; SET DEBUG_SYNC = 'RESET'; connection master; diff --git a/mysql-test/suite/sys_vars/r/innodb_flush_checkpoint_debug_basic.result b/mysql-test/suite/sys_vars/r/innodb_flush_checkpoint_debug_basic.result new file mode 100644 index 00000000000..e543cc30975 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_flush_checkpoint_debug_basic.result @@ -0,0 +1,15 @@ +SELECT @@global.innodb_flush_checkpoint_debug; +@@global.innodb_flush_checkpoint_debug +0 +SET @@global.innodb_flush_checkpoint_debug=1; +SELECT @@global.innodb_flush_checkpoint_debug; +@@global.innodb_flush_checkpoint_debug +1 +SET @@global.innodb_flush_checkpoint_debug=0; +SELECT @@global.innodb_flush_checkpoint_debug; +@@global.innodb_flush_checkpoint_debug +0 +SET @@session.innodb_flush_checkpoint_debug=1; +ERROR HY000: Variable 'innodb_flush_checkpoint_debug' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@session.innodb_flush_checkpoint_debug; +ERROR HY000: Variable 'innodb_flush_checkpoint_debug' is a GLOBAL variable diff --git a/mysql-test/suite/sys_vars/t/innodb_flush_checkpoint_debug_basic.test b/mysql-test/suite/sys_vars/t/innodb_flush_checkpoint_debug_basic.test new file mode 100644 index 00000000000..093a765e0e5 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_flush_checkpoint_debug_basic.test @@ -0,0 +1,12 @@ +--source include/have_debug.inc +--source include/have_xtradb.inc + +SELECT @@global.innodb_flush_checkpoint_debug; +SET @@global.innodb_flush_checkpoint_debug=1; +SELECT @@global.innodb_flush_checkpoint_debug; +SET @@global.innodb_flush_checkpoint_debug=0; +SELECT @@global.innodb_flush_checkpoint_debug; +--error ER_GLOBAL_VARIABLE +SET @@session.innodb_flush_checkpoint_debug=1; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_flush_checkpoint_debug; diff --git a/mysql-test/suite/vcol/r/vcol_select_myisam.result b/mysql-test/suite/vcol/r/vcol_select_myisam.result index d4868340ab5..934d047f6bf 100644 --- a/mysql-test/suite/vcol/r/vcol_select_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_select_myisam.result @@ -265,3 +265,33 @@ NULL explain select sum(c) from t1 group by b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort +# +# Bug #806057: join with USING over a virtual column +# +CREATE TABLE t1 (b int); +INSERT INTO t1 VALUES (NULL),( 78), (185), (0), (154); +CREATE TABLE t2 (a int, b int AS (a) VIRTUAL); +INSERT INTO t2 VALUES (187,187), (9,9), (187,187); +Warnings: +Warning 1906 The value specified for computed column 'b' in table 't2' ignored +Warning 1906 The value specified for computed column 'b' in table 't2' ignored +Warning 1906 The value specified for computed column 'b' in table 't2' ignored +EXPLAIN EXTENDED +SELECT * FROM t1 JOIN t2 USING (b); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where (`test`.`t1`.`b` = `test`.`t2`.`b`) +SELECT * FROM t1 JOIN t2 USING (b); +b a +EXPLAIN EXTENDED +SELECT * FROM t1 NATURAL JOIN t2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where (`test`.`t1`.`b` = `test`.`t2`.`b`) +SELECT * FROM t1 NATURAL JOIN t2; +b a +DROP TABLE t1,t2; diff --git a/mysql-test/suite/vcol/r/vcol_view_innodb.result b/mysql-test/suite/vcol/r/vcol_view_innodb.result index fe666e0e400..c9a4897e230 100644 --- a/mysql-test/suite/vcol/r/vcol_view_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_view_innodb.result @@ -107,7 +107,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1. MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 4 +1 PRIMARY ALL NULL NULL NULL NULL 2 2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort drop view v1; create view v1 as select c+1 from t1 order by 1 desc limit 2; @@ -119,7 +119,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1. MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 4 +1 PRIMARY ALL NULL NULL NULL NULL 2 2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort drop view v1; drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_view_myisam.result b/mysql-test/suite/vcol/r/vcol_view_myisam.result index 78c20f79f5e..e3fb2ec61ca 100644 --- a/mysql-test/suite/vcol/r/vcol_view_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_view_myisam.result @@ -107,7 +107,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1. MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 4 +1 PRIMARY ALL NULL NULL NULL NULL 2 2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort drop view v1; create view v1 as select c+1 from t1 order by 1 desc limit 2; @@ -119,7 +119,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1. MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 4 +1 PRIMARY ALL NULL NULL NULL NULL 2 2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort drop view v1; drop table t1; diff --git a/mysql-test/suite/vcol/t/vcol_select_myisam.test b/mysql-test/suite/vcol/t/vcol_select_myisam.test index 855e02ac113..c14faba576d 100644 --- a/mysql-test/suite/vcol/t/vcol_select_myisam.test +++ b/mysql-test/suite/vcol/t/vcol_select_myisam.test @@ -48,3 +48,23 @@ eval SET @@session.storage_engine = 'MyISAM'; #------------------------------------------------------------------------------# # Cleanup --source suite/vcol/inc/vcol_cleanup.inc + +--echo # +--echo # Bug #806057: join with USING over a virtual column +--echo # + +CREATE TABLE t1 (b int); +INSERT INTO t1 VALUES (NULL),( 78), (185), (0), (154); + +CREATE TABLE t2 (a int, b int AS (a) VIRTUAL); +INSERT INTO t2 VALUES (187,187), (9,9), (187,187); + +EXPLAIN EXTENDED +SELECT * FROM t1 JOIN t2 USING (b); +SELECT * FROM t1 JOIN t2 USING (b); + +EXPLAIN EXTENDED +SELECT * FROM t1 NATURAL JOIN t2; +SELECT * FROM t1 NATURAL JOIN t2; + +DROP TABLE t1,t2; diff --git a/mysql-test/t/derived_opt.test b/mysql-test/t/derived_opt.test index 42f3ce296e1..c2f831036e1 100644 --- a/mysql-test/t/derived_opt.test +++ b/mysql-test/t/derived_opt.test @@ -202,5 +202,15 @@ RIGHT JOIN ( drop table t1,t2,t3,t4; +--echo # +--echo # LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal +--echo # Fix: force materialization in case of conflict +--echo # +SET optimizer_switch='derived_merge=on'; +CREATE TABLE t1 ( i INT ); +INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) ); +drop table t1; +set optimizer_switch=@save_optimizer_switch; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index b674350af0a..95412426aa0 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1192,7 +1192,7 @@ INSERT INTO t2 VALUES (7), (4); CREATE TABLE t1 (b int NOT NULL); INSERT INTO t1 VALUES (5), (7); CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; - +SET @save_optimizer_switch=@@optimizer_switch; SET SESSION optimizer_switch='derived_merge=off'; PREPARE st1 FROM @@ -1201,10 +1201,12 @@ EXECUTE st1; EXECUTE st1; DEALLOCATE PREPARE st1; +set SESSION optimizer_switch= @save_optimizer_switch; + DROP VIEW v1; DROP TABLE t1,t2; -SET SESSION optimizer_switch='derived_merge=on'; + --echo # --echo # LP bug #879939: assertion in ha_maria::enable_indexes @@ -1226,7 +1228,7 @@ INSERT INTO t1 VALUES CREATE TABLE t3 (a varchar(35)); INSERT INTO t3 VALUES ('Miami'); - +SET @save_optimizer_switch=@@optimizer_switch; SET optimizer_switch = 'derived_with_keys=on'; SET @@tmp_table_size=1024*4; explain SELECT * FROM (SELECT t1.* FROM t1, t2) AS t JOIN t3 ON t3.a = t.b; @@ -1234,7 +1236,7 @@ SELECT * FROM (SELECT t1.* FROM t1, t2) AS t JOIN t3 ON t3.a = t.b; SET @@tmp_table_size=1024*1024*16; SELECT * FROM (SELECT t1.* FROM t1, t2) AS t JOIN t3 ON t3.a = t.b; SET @@tmp_table_size=default; - +set SESSION optimizer_switch= @save_optimizer_switch; drop table t1,t2,t3; --echo # @@ -1277,6 +1279,40 @@ ORDER BY CONCAT(alias2.col_varchar_nokey); set max_heap_table_size= @tmp_882994; drop table t1,t2,t3; +--echo # +--echo # LP bug #917990: Bad estimate of #rows for derived table with LIMIT +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES + (8), (3), (4), (7), (9), (5), (1), (2); + +SELECT * FROM (SELECT * FROM t1 LIMIT 3) t; +EXPLAIN +SELECT * FROM (SELECT * FROM t1 LIMIT 3) t; + +DROP TABLE t1; + +--echo # +--echo # LP BUG#921878 incorrect check of items during columns union types +--echo # aggregation for merged derived tables +--echo # +SET @save_optimizer_switch=@@optimizer_switch; +SET SESSION optimizer_switch='derived_merge=on'; +CREATE TABLE t1 ( a ENUM( 'x', 'y' ) ); +insert into t1 values ('x'); +CREATE TABLE t2 LIKE t1; +insert into t1 values ('y'); +CREATE TABLE t3 LIKE t1; +INSERT INTO t3 + SELECT * FROM ( SELECT * FROM t1 ) AS A + UNION SELECT * FROM t2; +select * from t3; + +drop table t1,t2,t3; + +set SESSION optimizer_switch= @save_optimizer_switch; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 54535470d4c..7a098c44e5b 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -1153,6 +1153,53 @@ drop table t1; --echo # --echo End of 5.1 tests +--echo # +--echo # Bug #904345: MIN/MAX optimization with constant FALSE condition +--echo # + +CREATE TABLE t1 (a int NOT NULL, KEY(a)); +INSERT INTO t1 VALUES (10), (8), (11), (7), (15), (12), (9); + +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES + (8,2), (6,9), (8,4), (5,3), (9,1); + +EXPLAIN EXTENDED +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT 3,4) AND a<10; +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT 3,4) AND a<10; + +EXPLAIN EXTENDED +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT a,b FROM t2 WHERE b<5) and a<10; +SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT a,b FROM t2 WHERE b<5) and a<10; + +EXPLAIN EXTENDED +SELECT MAX(a) FROM t1 WHERE RAND()*0<>0 AND a<10; +SELECT MAX(a) FROM t1 WHERE RAND()*0<>0 AND a<10; + +DROP TABLE t1,t2; + +--echo # +--echo # Bug #879860: MIN/MAX for subquery returning empty set +--echo # + +CREATE TABLE t1 (a int PRIMARY KEY); +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (a int NOT NULL); +INSERT INTO t2 VALUES (10); + +CREATE TABLE t3 ( a int, b int); +INSERT INTO t3 VALUES (19,1), (20,5); + +EXPLAIN EXTENDED +SELECT (SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b) FROM t3; +SELECT (SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b) FROM t3; + +DROP TABLE t1,t2,t3; + +--echo # +--echo End of 5.2 tests + --echo # --echo # BUG#46680 - Assertion failed in file item_subselect.cc, --echo # line 305 crashing on HAVING subquery diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 4600da9ee17..668d0ca7891 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -3423,5 +3423,164 @@ SET optimizer_switch=@tmp_optimizer_switch; DROP TABLE t1,t2,t3,t4; +--echo # +--echo # Bug#53305 Duplicate weedout + join buffer (join cache --level=7,8) +--echo # + +create table t1 (uid int, fid int, index(uid)); +insert into t1 values + (1,1), (1,2), (1,3), (1,4), + (2,5), (2,6), (2,7), (2,8), + (3,1), (3,2), (3,9); + +create table t2 (uid int primary key, name varchar(128), index(name)); +insert into t2 values + (1, "A"), (2, "B"), (3, "C"), (4, "D"), (5, "E"), + (6, "F"), (7, "G"), (8, "H"), (9, "I"); + +create table t3 (uid int, fid int, index(uid)); +insert into t3 values + (1,1), (1,2), (1,3),(1,4), + (2,5), (2,6), (2,7), (2,8), + (3,1), (3,2), (3,9); + +set @tmp_optimizer_switch=@@optimizer_switch; +set @@optimizer_switch='semijoin=on'; +set optimizer_switch='materialization=off'; +set optimizer_switch='loosescan=off,firstmatch=off'; +set optimizer_switch='mrr_sort_keys=off'; +set join_cache_level=7; + +create table t4 (uid int primary key, name varchar(128), index(name)); +insert into t4 values + (1, "A"), (2, "B"), (3, "C"), (4, "D"), (5, "E"), + (6, "F"), (7, "G"), (8, "H"), (9, "I"); + +explain select name from t2, t1 + where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid) + and t2.uid=t1.fid; + +--sorted_result +select name from t2, t1 + where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid) + and t2.uid=t1.fid; + +set join_cache_level = default; +set optimizer_switch=@tmp_optimizer_switch; + +drop table t1,t2,t3,t4; + +--echo # +--echo # Bug#50358 - semijoin execution of subquery with outerjoin +--echo # emplying join buffer +--echo # + +CREATE TABLE t1 (i int); +CREATE TABLE t2 (i int); +CREATE TABLE t3 (i int); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (6); +INSERT INTO t3 VALUES (1), (2); + +set @tmp_optimizer_switch=@@optimizer_switch; +set @@optimizer_switch='semijoin=on'; +set optimizer_switch='materialization=on'; + +set join_cache_level=0; +EXPLAIN +SELECT * FROM t1 WHERE t1.i IN + (SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); +SELECT * FROM t1 WHERE t1.i IN + (SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); + +set join_cache_level=2; +EXPLAIN +SELECT * FROM t1 WHERE t1.i IN + (SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); +SELECT * FROM t1 WHERE t1.i IN + (SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); + +set join_cache_level = default; +set optimizer_switch=@tmp_optimizer_switch; + +DROP TABLE t1,t2,t3; + +--echo # +--echo # Bug #12546542: missing row with semijoin=off + join cache +--echo # (LP bug #922971) +--echo # + +CREATE TABLE t1 (a varchar(1024)); +INSERT INTO t1 VALUES ('v'), ('we'); +CREATE TABLE t2 ( + a varchar(1024) CHARACTER SET utf8 DEFAULT NULL, b int, c int +); +INSERT INTO t2 VALUES ('we',4,NULL), ('v',1305673728,6); +CREATE TABLE t3 (b int, c int); +INSERT INTO t3 VALUES (4,4); + +set @tmp_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=off'; +set optimizer_switch='materialization=off'; + +set join_cache_level=0; +EXPLAIN +SELECT * FROM t1 + WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b + WHERE t2.c < 10 OR t3.c > 1); + +SELECT * FROM t1 + WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b + WHERE t2.c < 10 OR t3.c > 1); + +set join_cache_level=2; +EXPLAIN +SELECT * FROM t1 + WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b + WHERE t2.c < 10 OR t3.c > 1); +SELECT * FROM t1 + WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b + WHERE t2.c < 10 OR t3.c > 1); + +set join_cache_level = default; +set optimizer_switch=@tmp_optimizer_switch; + +DROP TABLE t1,t2,t3; + +--echo # +--echo # Bug #925985: LEFT JOIN with optimize_join_buffer_size=off + +--echo # join_buffer_size > join_buffer_space_limit +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (5), (3); + +CREATE TABLE t2 (a int, b int); +INSERT INTO t2 VALUES + (3,30), (1,10), (7,70), (2,20), + (3,31), (1,11), (7,71), (2,21), + (3,32), (1,12), (7,72), (2,22); + +CREATE TABLE t3 (b int, c int); +INSERT INTO t3 VALUES (32, 302), (42,400), (30,300); + +set @tmp_optimizer_switch=@@optimizer_switch; +set optimizer_switch='optimize_join_buffer_size=off'; +set join_buffer_space_limit=4096; +set join_buffer_size=4096*2; +set join_cache_level=2; +set optimizer_switch='outer_join_with_cache=on'; + +EXPLAIN +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; +SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a; + +set join_buffer_space_limit=default; +set join_buffer_size=default; +set join_cache_level=default; +set optimizer_switch=@tmp_optimizer_switch; + +DROP TABLE t1,t2,t3; + # this must be the last command in the file set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_outer_innodb.test b/mysql-test/t/join_outer_innodb.test index 0d47c4ea57b..c5cf66c816b 100644 --- a/mysql-test/t/join_outer_innodb.test +++ b/mysql-test/t/join_outer_innodb.test @@ -61,3 +61,18 @@ ORDER BY pk; DROP TABLE t1,t2; --echo # End BUG#58456 + +# +# Bug #848652: crash with RIGHT JOIN and GROUP BY +# + +CREATE TABLE t1(a int, b int, KEY (a), PRIMARY KEY (b)) ENGINE=InnoDB; + +CREATE TABLE t2 (b int, PRIMARY KEY (b)); +INSERT INTO t2 VALUES (4),(9); + +SELECT STRAIGHT_JOIN t1.a FROM t1 RIGHT JOIN t2 ON t1.b = t2.b + WHERE (t1.b NOT BETWEEN 1 AND 7 OR t1.a IS NULL AND t1.b = t2.b) AND t2.b = 4 +GROUP BY 1; + +DROP TABLE t1,t2; diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index 13367cbdcaa..83b4b0b1deb 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -522,3 +522,19 @@ set global key_buffer_size=@save_key_buffer_size; set global key_cache_segments=@save_key_cache_segments; # End of 5.2 tests + +--echo # +--echo # Bug#12361113: crash when load index into cache +--echo # + +--echo # Note that this creates an empty disabled key cache! +SET GLOBAL key_cache_none.key_cache_block_size = 1024; +CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1, 1); +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 in key_cache_none; +--echo # The bug crashed the server at LOAD INDEX below. Now it will succeed +--echo # since the default cache is used due to CACHE INDEX failed for +--echo # key_cache_none. +LOAD INDEX INTO CACHE t1; +DROP TABLE t1; diff --git a/mysql-test/t/myisam_mrr.test b/mysql-test/t/myisam_mrr.test index 1e070ec9a34..28385c61b0f 100644 --- a/mysql-test/t/myisam_mrr.test +++ b/mysql-test/t/myisam_mrr.test @@ -268,5 +268,58 @@ set @@join_cache_level= @tmp_730133_jcl; set @@optimizer_switch= @tmp_730133_os; drop table t1; +--echo # +--echo # Test of MRR handler counters +--echo # +flush status; +show status like 'Handler_mrr%'; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int, filler char(200), key(a)); +insert into t1 +select A.a+10*B.a+100*C.a+1000*D.a, 123,'filler' from t0 A, t0 B, t0 C, t0 D; + +explain select sum(b) from t1 where a < 10; +--echo # This should show one MRR scan and no re-fills: +flush status; +select sum(b) from t1 where a < 10; +show status like 'handler_mrr%'; + +set @mrr_buffer_size_save= @@mrr_buffer_size; +--disable_warnings +set mrr_buffer_size=128; +--enable_warnings + +explain select sum(b) from t1 where a < 1600; +--echo # This should show one MRR scan and one extra rowid sort: +flush status; +select sum(b) from t1 where a < 1600; +show status like 'handler_mrr%'; +set @@mrr_buffer_size= @mrr_buffer_size_save; + +--echo #Now, let's check BKA: +set @join_cache_level_save= @@join_cache_level; +set @join_buffer_size_save= @@join_buffer_size; +set join_cache_level=6; + +explain select sum(t1.b) from t0,t1 where t0.a=t1.a; +flush status; +select sum(t1.b) from t0,t1 where t0.a=t1.a; +show status like 'handler_mrr%'; + +--disable_warnings +set join_buffer_size=10; +--enable_warnings +explain select sum(t1.b) from t0,t1 where t0.a=t1.a; +flush status; +select sum(t1.b) from t0,t1 where t0.a=t1.a; +--replace_result 1 1or2 2 1or2 +show status like 'handler_mrr%'; + +set join_cache_level= @join_cache_level_save; +set join_buffer_size= @join_buffer_size_save; + +drop table t0, t1; + ## This must be last line in the file: set optimizer_switch= @myisam_mrr_tmp; diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index ef88b89e8d8..c0025f9e742 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -147,6 +147,7 @@ SET NAMES DEFAULT; call mtr.add_suppression("@003f.frm' \\(errno: 22\\)"); --echo mysqlcheck --default-character-set="latin1" --databases test # Error returned depends on platform, replace it with "Table doesn't exist" +call mtr.add_suppression("Can't find file: '..test.@003f.frm'"); --replace_result "Can't find file: './test/@003f.frm' (errno: 22)" "Table doesn't exist" "Table 'test.?' doesn't exist" "Table doesn't exist" --exec $MYSQL_CHECK --default-character-set="latin1" --databases test --echo mysqlcheck --default-character-set="utf8" --databases test diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 302d79b6b13..424dd35a819 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2249,8 +2249,12 @@ INSERT INTO b12809202_db.t2 VALUES (1), (2), (3); --echo # commit starting 5.5. --echo --echo #### Dump starts here #### +# We only need to check the --verbose output to verify that "start transaction" +# happens after "logs flushed". We redirect normal output, as otherwise the +# mixing of normal (stdout) and --verbose (stderr) output will happen in random +# order depending on stdio internal buffer size. --replace_regex /-- Server version.*// /-- MySQL dump .*// /-- Dump completed on .*/-- Dump completed/ ---exec $MYSQL_DUMP --verbose --single-transaction --flush-log b12809202_db 2>&1 +--exec $MYSQL_DUMP --verbose --single-transaction --flush-log b12809202_db 2>&1 > $MYSQLTEST_VARDIR/tmp/bug61854.sql --echo --echo #### Dump ends here #### diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 82116558717..a6f50107cbe 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -1562,7 +1562,6 @@ select 1 order by max(1) + min(1); --echo End of 5.1 tests - --echo # --echo # Bug #38745: MySQL 5.1 optimizer uses filesort for ORDER BY --echo # when it should use index @@ -1585,3 +1584,32 @@ SELECT t1.*, t2.* FROM t1 JOIN t2 ON t1.i1 = t2.i2 ORDER BY t1.i1 LIMIT 5; DROP TABLE t1, t2, t3; + +--echo # +--echo # Fix of LP BUG#793589 Wrong result with double ORDER BY +--echo # +CREATE TABLE t1 ( b int) ; +INSERT INTO t1 VALUES (8),(9); + +CREATE TABLE t2 ( a int, b int, PRIMARY KEY (a)) ; +INSERT INTO t2 VALUES (6,7),(7,7),(8,1),(9,7),(10,1),(11,5),(12,2),(13,0),(14,1),(15,8),(16,1),(17,1),(18,9),(19,1),(20,5); + +SELECT t2.b AS field1 FROM t1, t2 WHERE t1.b = t2.a GROUP BY field1 ORDER BY t1.b, field1; +SELECT t2.b, t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b, t2.b; +SELECT t2.b,t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; +SELECT t2.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; + +--echo # field1 removed from ORDER BY +explain extended +SELECT t2.b AS field1 FROM t1, t2 WHERE t1.b = t2.a GROUP BY field1 ORDER BY t1.b, field1; +explain extended +SELECT t2.b, t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b, t2.b; +explain extended +SELECT t2.b,t1.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; +explain extended +SELECT t2.b FROM t1, t2 WHERE t1.b = t2.a GROUP BY t2.b ORDER BY t1.b; + + +drop table t1,t2; + +--echo End of 5.2 tests diff --git a/mysql-test/t/partition_key_cache.test b/mysql-test/t/partition_key_cache.test index 4beb9506b05..067eb7fae59 100644 --- a/mysql-test/t/partition_key_cache.test +++ b/mysql-test/t/partition_key_cache.test @@ -239,6 +239,34 @@ CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache; CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN hot_cache; CACHE INDEX t1 INDEX (`inx_b`) IN hot_cache; DROP TABLE t1,t2; + +--echo # +--echo # Bug#12361113: crash when load index into cache +--echo # +--echo # Note that this creates an empty disabled key cache! +SET GLOBAL key_cache_none.key_cache_block_size = 1024; +CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) +ENGINE = MYISAM +PARTITION BY HASH(a) PARTITIONS 2; +INSERT INTO t1 VALUES (1, 1); +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 IN key_cache_none; +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 PARTITION (p0) IN key_cache_none; +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 PARTITION (p1) IN key_cache_none; +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 PARTITION (p0) KEY (`b`) IN key_cache_none; +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 PARTITION (p1) KEY (`b`) IN key_cache_none; +--echo # The bug crashed the server at LOAD INDEX below. Now it will succeed +--echo # since the default cache is used due to CACHE INDEX failed for +--echo # key_cache_none. +LOAD INDEX INTO CACHE t1; +DROP TABLE t1; + + +--echo # Clean up SET GLOBAL hot_cache.key_buffer_size = 0; SET GLOBAL warm_cache.key_buffer_size = 0; SET @@global.cold_cache.key_buffer_size = 0; diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index da41b8e9428..1c8a4d254a8 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -1106,12 +1106,14 @@ show status like 'Handler_read_key'; flush status; delete from t2 where b > 5; show status like 'Handler_read_rnd_next'; +show status like 'Handler_read_rnd_deleted'; show status like 'Handler_read_key'; show status like 'Handler_read_prev'; show status like 'Handler_read_next'; flush status; delete from t2 where b < 5 or b > 3; show status like 'Handler_read_rnd_next'; +show status like 'Handler_read_rnd_deleted'; show status like 'Handler_read_key'; show status like 'Handler_read_prev'; show status like 'Handler_read_next'; diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 76769e78d90..9395323d32b 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -369,6 +369,16 @@ show status like 'Handler%'; show status like '%tmp%'; drop table t1; +# +# Test of handler status counts +# +CREATE TABLE t1 (i int(11) DEFAULT NULL, KEY i (i) ) ENGINE=MyISAM; +insert into t1 values (1),(2),(3),(4),(5); +flush status; +select * from t1 where i=5 union select * from t1 where i=5; +show status like "handler%"; +drop table t1; + # End of 5.3 tests # Restore global concurrent_insert value. Keep in the end of the test file. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index cb43eb9f646..40ecfead133 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3519,6 +3519,8 @@ SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; ## First a simpler query, illustrating the transformation ## '1 < some (...)' => '1 < max(...)' +EXPLAIN EXTENDED +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1); ## The query which made the server crash. @@ -4431,8 +4433,6 @@ WHERE t1.a = d1.a; DROP TABLE t1; ---echo End of 5.1 tests. - # # Bug #47904 Incorrect results w/ table subquery, derived SQs, and LEFT JOIN on index # @@ -4879,11 +4879,141 @@ INSERT INTO t3 VALUES (0),(0); SELECT a1.f3 AS r FROM t2 AS a1 , t1 WHERE a1.f3 < ALL ( SELECT f3 FROM t3 WHERE f3 = 1 ) ; DROP TABLE t1, t2, t3; +--echo # +--echo # Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +--echo # + +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +## All these are subject to the transformation +## '1 < some (...)' => '1 < max(...)' +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); + +SET SESSION sql_mode=@old_sql_mode; + +DROP TABLE t1, t2; + +create table t2(i int); +insert into t2 values(0); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; + +CREATE TABLE t1 ( + pk int NOT NULL, + col_varchar_key varchar(1) DEFAULT NULL, + PRIMARY KEY (pk), + KEY col_varchar_key (col_varchar_key) +); + +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; + +SET SESSION sql_mode=@old_sql_mode; + +drop table t2, t1; +drop view v1; + +--echo # +--echo # BUG#50257: Missing info in REF column of the EXPLAIN +--echo # lines for subselects +--echo # + +CREATE TABLE t1 (a INT, b INT, INDEX (a)); +INSERT INTO t1 VALUES (3, 10), (2, 20), (7, 10), (5, 20); + +EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a=7) t; +EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); + +DROP TABLE t1; + +--echo # +--echo # BUG#12616253 - WRONG RESULT WITH EXISTS(SUBQUERY) (MISSING ROWS) +--echo # (duplicate of LP bug #888456) +--echo # + +CREATE TABLE t1 (f1 varchar(1)); +INSERT INTO t1 VALUES ('v'),('s'); + +CREATE TABLE t2 (f1_key varchar(1), KEY (f1_key)); +INSERT INTO t2 VALUES ('j'),('v'),('c'),('m'),('d'), +('d'),('y'),('t'),('d'),('s'); + +EXPLAIN +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 + WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 + WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); +SELECT table1.f1, table2.f1_key FROM t1 AS table1, t2 AS table2 + WHERE EXISTS (SELECT DISTINCT f1_key FROM t2 + WHERE f1_key != table2.f1_key AND f1_key >= table1.f1); + +DROP TABLE t1,t2; + +--echo # +--echo # LP bug 919427: EXPLAIN for a query over a single-row table +--echo # with IN subquery in WHERE condition +--echo # + +CREATE TABLE ot ( + col_int_nokey int(11), + col_varchar_nokey varchar(1) +) ; +INSERT INTO ot VALUES (1,'x'); + +CREATE TABLE it1( + col_int_key int(11), + col_varchar_key varchar(1), + KEY idx_cvk_cik (col_varchar_key,col_int_key) +); +INSERT INTO it1 VALUES (NULL,'x'), (NULL,'f'); + +CREATE TABLE it2 ( + col_int_key int(11), + col_varchar_key varchar(1), + col_varchar_key2 varchar(1), + KEY idx_cvk_cvk2_cik (col_varchar_key, col_varchar_key2, col_int_key), + KEY idx_cvk_cik (col_varchar_key, col_int_key) +); +INSERT INTO it2 VALUES (NULL,'x','x'), (NULL,'f','f'); + +EXPLAIN +SELECT col_int_nokey FROM ot + WHERE col_varchar_nokey IN + (SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); +SELECT col_int_nokey FROM ot + WHERE col_varchar_nokey IN + (SELECT col_varchar_key FROM it1 WHERE col_int_key IS NULL); + +EXPLAIN +SELECT col_int_nokey FROM ot + WHERE (col_varchar_nokey, 'x') IN + (SELECT col_varchar_key, col_varchar_key2 FROM it2); +SELECT col_int_nokey FROM ot + WHERE (col_varchar_nokey, 'x') IN + (SELECT col_varchar_key, col_varchar_key2 FROM it2); + +DROP TABLE ot,it1,it2; + --echo End of 5.2 tests --echo # --echo # BUG#779885: Crash in eliminate_item_equal with materialization=on in ---echo # maria-5.3 --echo # CREATE TABLE t1 ( f1 int ); @@ -4936,32 +5066,6 @@ SET optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; ---echo End of 5.3 tests - ---echo # ---echo # Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER ---echo # - -CREATE TABLE t1(a1 int); -INSERT INTO t1 VALUES (1),(2); - -CREATE TABLE t2(a1 int); -INSERT INTO t2 VALUES (3); - -SELECT @@session.sql_mode INTO @old_sql_mode; -SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; - -## All these are subject to the transformation -## '1 < some (...)' => '1 < max(...)' -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); -SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); - -SET SESSION sql_mode=@old_sql_mode; - -DROP TABLE t1, t2; - --echo # --echo # BUG#50257: Missing info in REF column of the EXPLAIN --echo # lines for subselects @@ -4981,6 +5085,55 @@ EXPLAIN SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t1 WHERE a=7); --echo DROP TABLE t1; +--echo # +--echo # Bug#11764086: Null left operand to NOT IN in WHERE clause +--echo # behaves differently than real NULL +--echo # + +CREATE TABLE parent (id int); +INSERT INTO parent VALUES (1), (2); + +CREATE TABLE child (parent_id int, other int); +INSERT INTO child VALUES (1,NULL); + +--echo # Offending query (c.parent_id is NULL for null-complemented rows only) + +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id NOT IN ( + SELECT parent_id + FROM child + WHERE parent_id = 3 + ); + +--echo # Some syntactic variations with IS FALSE and IS NOT TRUE + +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( + SELECT parent_id + FROM child + WHERE parent_id = 3 + ) IS NOT TRUE; + +SELECT p.id, c.parent_id +FROM parent p +LEFT JOIN child c +ON p.id = c.parent_id +WHERE c.parent_id IN ( + SELECT parent_id + FROM child + WHERE parent_id = 3 + ) IS FALSE; + +DROP TABLE parent, child; + +--echo # End of test for bug#11764086. + --echo # --echo # Bug 11765699 - 58690: !TABLE || (!TABLE->READ_SET || --echo # BITMAP_IS_SET(TABLE->READ_SET, FIELD_INDEX @@ -5279,6 +5432,17 @@ SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1; drop table t1,t2,t3; +--echo # +--echo # LP BUG#905353 Wrong non-empty result with a constant table, +--echo # aggregate function in subquery, MyISAM or Aria +--echo # + +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); + +SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); + +drop table t1; --echo # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index f34cf5ba338..6b8a757b9e8 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -1136,6 +1136,262 @@ WHERE (int_nokey, pk) DROP TABLE t1, t2, t3; +--echo # +--echo # BUG#53060: LooseScan semijoin strategy does not return all rows +--echo # + +set @save_optimizer_switch=@@optimizer_switch; +set optimizer_switch='semijoin=on,materialization=off'; +set optimizer_switch='firstmatch=off,loosescan=on'; + +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +CREATE TABLE t2 (i INTEGER, j INTEGER, KEY k(i, j)); +INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1); + +EXPLAIN +SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0); +SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0); + +DROP TABLE t1, t2; + +set optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # BUG#49453: re-execution of prepared statement with view +--echo # and semijoin crashes +--echo # + +CREATE TABLE t1 (city VARCHAR(50), country_id INT); +CREATE TABLE t2 (country_id INT, country VARCHAR(50)); + +INSERT INTO t1 VALUES + ('Batna',2),('Bchar',2),('Skikda',2),('Tafuna',3),('Algeria',2) ; +INSERT INTO t2 VALUES (2,'Algeria'),(2,'AlgeriaDup'),(3,'XAmerican Samoa'); + +CREATE VIEW v1 AS + SELECT country_id as vf_country_id + FROM t2 + WHERE LEFT(country,1) = "A"; + +PREPARE stmt FROM " +SELECT city, country_id +FROM t1 +WHERE country_id IN (SELECT vf_country_id FROM v1); +"; + +--echo +EXECUTE stmt; +EXECUTE stmt; + +DROP TABLE t1,t2; +DROP VIEW v1; + +--echo # +--echo # Bug#54437 Extra rows with LEFT JOIN + semijoin +--echo # + +create table t1 (a int); +create table t2 (a int); +create table t3 (a int); +insert into t1 values(1),(1); +insert into t2 values(1),(1),(1),(1); +insert into t3 values(2),(2); + +set @save_optimizer_switch=@@optimizer_switch; + +set optimizer_switch='materialization=off'; + +set optimizer_switch='semijoin=off'; +explain +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); + +set optimizer_switch='semijoin=on'; +explain +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); +select * from t1 where t1.a in (select t2.a from t2 left join t3 on t2.a=t3.a); + +set optimizer_switch=@save_optimizer_switch; + +drop table t1,t2,t3; + +--echo # +--echo # Bug#55955: crash in MEMORY engine with IN(LEFT JOIN (JOIN)) +--echo # + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +INSERT INTO t1 VALUES(1),(1); +INSERT INTO t2 VALUES(1),(1); +INSERT INTO t3 VALUES(2),(2); + +set @save_optimizer_switch=@@optimizer_switch; + +set optimizer_switch='semijoin=off,materialization=off'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a + FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a + FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); + +set optimizer_switch='semijoin=off,materialization=on'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a + FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a + FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); + +set optimizer_switch='semijoin=on,materialization=off'; +EXPLAIN +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a + FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); +SELECT * FROM t1 +WHERE t1.a IN (SELECT t2.a + FROM t2 LEFT JOIN (t2 AS t2inner, t3) ON t2.a=t3.a); + +set optimizer_switch=@save_optimizer_switch; + +DROP TABLE t1,t2,t3; + +--echo # +--echo # BUG#52329 - Wrong result: subquery materialization, IN, +--echo # non-null field followed by nullable +--echo # + +CREATE TABLE t1 (a1 CHAR(8) NOT NULL, a2 char(8) NOT NULL); + +CREATE TABLE t2a (b1 char(8), b2 char(8)); +CREATE TABLE t2b (b1 CHAR(8), b2 char(8) NOT NULL); +CREATE TABLE t2c (b1 CHAR(8) NOT NULL, b2 char(8)); + +INSERT INTO t1 VALUES ('1 - 12', '2 - 22'); + +INSERT INTO t2a VALUES ('1 - 11', '2 - 21'), + ('1 - 11', '2 - 21'), + ('1 - 12', '2 - 22'), + ('1 - 12', '2 - 22'), + ('1 - 13', '2 - 23'); + +INSERT INTO t2b SELECT * FROM t2a; +INSERT INTO t2c SELECT * FROM t2a; + +set @save_optimizer_switch=@@optimizer_switch; + +set optimizer_switch='semijoin=off,materialization=on'; + +SELECT * FROM t1 +WHERE (a1, a2) IN ( + SELECT b1, b2 FROM t2c WHERE b1 > '0' GROUP BY b1, b2); + +SELECT * FROM t1 +WHERE (a1, a2) IN ( + SELECT b1, b2 FROM t2a WHERE b1 > '0'); + + +SELECT * FROM t1 +WHERE (a1, a2) IN ( + SELECT b1, b2 FROM t2b WHERE b1 > '0'); + + +SELECT * FROM t1 +WHERE (a1, a2) IN ( + SELECT b1, b2 FROM t2c WHERE b1 > '0'); + +set optimizer_switch=@save_optimizer_switch; + +DROP TABLE t1,t2a,t2b,t2c; + +--echo # +--echo # Bug#57623: subquery within before insert trigger causes crash (sj=on) +--echo # + +CREATE TABLE ot1(a INT); +CREATE TABLE ot2(a INT); +CREATE TABLE ot3(a INT); +CREATE TABLE it1(a INT); + +INSERT INTO ot1 VALUES(0),(1),(2),(3),(4),(5),(6),(7); +INSERT INTO ot2 VALUES(0),(2),(4),(6); +INSERT INTO ot3 VALUES(0),(3),(6); +INSERT INTO it1 VALUES(0),(1),(2),(3),(4),(5),(6),(7); + +let $query= +SELECT * +FROM ot1 + LEFT JOIN + (ot2 JOIN ot3 on ot2.a=ot3.a) + ON ot1.a=ot2.a AND ot1.a IN (SELECT a from it1); + +set @save_optimizer_switch=@@optimizer_switch; + +set optimizer_switch='semijoin=on'; + +set optimizer_switch='materialization=off'; +eval explain $query; +eval $query; +eval prepare s from '$query'; +execute s; +execute s; +deallocate prepare s; + +set optimizer_switch='materialization=on'; +eval explain $query; +eval $query; +eval prepare s from '$query'; +execute s; +execute s; +deallocate prepare s; + +set optimizer_switch=@save_optimizer_switch; + +DROP TABLE ot1, ot2, ot3, it1; + +--echo # +--echo # Bug#59919/11766739: Crash in tmp_table_param::init() with semijoin=on +--echo # + +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE t2 (f1 INTEGER, f2 INTEGER) ENGINE=MyISAM; +CREATE TABLE t3 (f1 INTEGER, f2 INTEGER) ENGINE=MyISAM; + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1,1), (2,1); +INSERT INTO t3 VALUES + (1,1), (2,1), (5,4), (7,3), (8,2), (8,1), (7,3), + (9,5), (4,3), (7,2), (7,7), (3,1), (5,8), (9,7); + +set @save_optimizer_switch=@@optimizer_switch; + +set optimizer_switch='semijoin=off,materialization=on'; +EXPLAIN +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 + FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 + FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); + +set optimizer_switch='semijoin=on,materialization=on'; +EXPLAIN +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 + FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); +SELECT * FROM t3 +WHERE f2 IN (SELECT t1.f1 + FROM t1 LEFT OUTER JOIN (t2 AS b1 JOIN t2 AS b2 ON TRUE) ON TRUE); + +set optimizer_switch=@save_optimizer_switch; + +DROP TABLE t1, t2, t3 ; + +--echo # --echo # --echo # BUG#784723: Wrong result with semijoin + nested subqueries in maria-5.3 --echo # @@ -2017,5 +2273,63 @@ SELECT a, COUNT(*) FROM t1 DROP TABLE t1, t2, t3; +--echo # +--echo # BUG#920255: Wrong result (extra rows) with loosescan and IN subquery +--echo # +CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, KEY(b) ); +INSERT INTO t1 VALUES + (1,2),(2,1),(3,3),(4,2),(5,5), + (6,3),(7,1),(8,4),(9,3),(10,2); + +CREATE TABLE t2 ( c INT, d INT, UNIQUE KEY(c) ); +INSERT INTO t2 VALUES + (1,2),(2,1),(3,3),(4,2),(5,5),(6,3),(7,1); + +SELECT a, b, d FROM t1, t2 +WHERE ( b, d ) IN + ( SELECT b, d FROM t1, t2 WHERE b = c ); + +DROP TABLE t1, t2; + +--echo # +--echo # BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ... +--echo # +# t1 should be MyISAM or InnoDB +CREATE TABLE t1 ( a VARCHAR(1) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('e'),('w'),('a'),('h'),('x'),('k'),('g'); +CREATE TABLE t2 ( b INT, c VARCHAR(1) ); +INSERT INTO t2 VALUES (0,'j'),(8,'v'); + +#SET debug_optimizer_prefer_join_prefix= 'alias2,alias4,alias1,alias3'; + +SELECT * FROM t1 alias1, t2 alias2 +WHERE alias2.c IN ( + SELECT alias4.c FROM t1 alias3, t2 alias4 +); + +DROP TABLE t1, t2; + +--echo # +--echo # BUG#923246: Loosescan reports different result than other semijoin methods +--echo # +set @tmp_923246= @@optimizer_switch; +set optimizer_switch='mrr=on,materialization=off'; + +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1 (kp1 int, kp2 int, c int, filler char(100), key(kp1, kp2)); +insert into t1 select A.a+10*(B.a+10*C.a), 0, 0, 'filler' from t0 A, t0 B, t0 C; +insert into t1 select * from t1 where kp1 < 20; + +create table t3 (a int); +insert into t3 select A.a + 10*B.a from t0 A, t0 B; + +select * from t3 where a in (select kp1 from t1 where kp1<20); +explain select * from t3 where a in (select kp1 from t1 where kp1<20); + +drop table t0,t1,t3; +set optimizer_switch= @tmp_923246; + # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/t/subselect_sj2.test b/mysql-test/t/subselect_sj2.test index a77a70bbe4e..ede631f32be 100644 --- a/mysql-test/t/subselect_sj2.test +++ b/mysql-test/t/subselect_sj2.test @@ -1079,5 +1079,19 @@ SELECT * FROM t3 LEFT JOIN (v1,t2) ON t3.a = t2.a DROP VIEW v1; DROP TABLE t1,t2,t3,t4; +--echo # +--echo # BUG#912538: Wrong result (missing rows) with semijoin=on, firstmatch=on, ... +--echo # +CREATE TABLE t1 ( a INT NOT NULL, UNIQUE KEY(a) ); +INSERT INTO t1 VALUES (1),(2),(3),(4); + +# t2 needs to be InnoDB +CREATE TABLE t2 ( b INT, c INT ) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1); + +SELECT * FROM t1, t2 WHERE c IN (SELECT c FROM t1, t2 WHERE a = b); + +DROP TABLE t1,t2; + --echo # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/mysql-test/t/subselect_sj_jcl6.test b/mysql-test/t/subselect_sj_jcl6.test index 4eeaa465b11..6d563cab3d3 100644 --- a/mysql-test/t/subselect_sj_jcl6.test +++ b/mysql-test/t/subselect_sj_jcl6.test @@ -88,6 +88,32 @@ set join_cache_level=default; DROP TABLE t1,t2,t3; +--echo # +--echo # BUG#912513: Wrong result (missing rows) with join_cache_hashed+materialization+semijoin=on +--echo # +set @os_912513= @@optimizer_switch; +set @jcl_912513= @@join_cache_level; +SET optimizer_switch = 'semijoin=on,materialization=on,join_cache_hashed=on'; +SET join_cache_level = 3; + +CREATE TABLE t1 ( a INT, b INT, KEY(a) ); +INSERT INTO t1 VALUES + (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); + +CREATE TABLE t2 ( c INT ); +INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6),(7); + +SELECT alias1.* FROM + t1 AS alias1 INNER JOIN t1 AS alias2 + ON alias2.a = alias1.b +WHERE alias1.b IN ( + SELECT a FROM t1, t2 + ); + +DROP table t1, t2; +set @@optimizer_switch= @os_912513; +set @@join_cache_level= @jcl_912513; + --echo # End set join_cache_level=default; diff --git a/mysql-test/t/subselect_sj_mat.test b/mysql-test/t/subselect_sj_mat.test index 2a5b0f56877..0840029c5e0 100644 --- a/mysql-test/t/subselect_sj_mat.test +++ b/mysql-test/t/subselect_sj_mat.test @@ -1510,6 +1510,42 @@ SELECT * FROM t1 LEFT JOIN t2 ON ( a = b ) DROP TABLE t1,t2; +--echo # +--echo # BUG#922254: Assertion `0' failed at item_cmpfunc.cc:5899: Item* Item_equal::get_first(JOIN_TAB*, Item*) +--echo # +CREATE TABLE t1 ( a VARCHAR(3) ); +CREATE TABLE t2 ( b VARCHAR(3), c VARCHAR(8), KEY(c) ); +INSERT INTO t2 VALUES ('USA','Abilene'),('USA','Akron'); + +EXPLAIN +SELECT * FROM + ( SELECT * FROM t1 ) AS alias1, + t2 AS alias2 +WHERE b = a AND a IN ( + SELECT alias3.c + FROM t2 AS alias3, t2 AS alias4 + WHERE alias4.c = alias3.b +); + +DROP TABLE t1,t2; + +--echo # +--echo # BUG#928048: Query containing IN subquery with OR in the where clause returns a wrong result +--echo # +create table t1 (a int, b int); +insert into t1 values (7,5), (3,3), (5,4), (9,3); + +create table t2 (a int, b int, index i_a(a)); + +insert into t2 values + (4,2), (7,9), (7,4), (3,1), (5,3), (3,1), (9,4), (8,1); + +explain select * from t1 where t1.a in (select a from t2 where t2.a=7 or t2.b<=1); +select * from t1 where t1.a in (select a from t2 where t2.a=7 or t2.b<=1); + +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/mysql-test/t/sum_distinct.test b/mysql-test/t/sum_distinct.test index c58155a8e25..633a72fddc8 100644 --- a/mysql-test/t/sum_distinct.test +++ b/mysql-test/t/sum_distinct.test @@ -93,3 +93,15 @@ SELECT SUM(DISTINCT id) FROM t1; SELECT SUM(DISTINCT id % 11) FROM t1; DROP TABLE t1; + +--echo # +--echo # Bug #777654: empty subselect in FROM clause returning +--echo # SUM(DISTINCT) over non-nullable field +--echo # + +CREATE TABLE t1 (a int NOT NULL) ; + +SELECT SUM(DISTINCT a) FROM t1; +SELECT * FROM (SELECT SUM(DISTINCT a) FROM t1) AS t; + +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 5fd8da745e4..79c733ed791 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4018,6 +4018,59 @@ drop table t1,t2; --echo # ----------------------------------------------------------------- --echo # -- End of 5.1 tests. --echo # ----------------------------------------------------------------- +--echo # +--echo # Bug #794005: crash in st_table::mark_virtual_columns_for_write +--echo # + +CREATE TABLE t1 (a int); +insert into t1 values (1); +CREATE TABLE t2 (a int); +insert into t2 values (1); + +CREATE VIEW v2 AS SELECT * FROM t2; +CREATE VIEW v1 AS SELECT * FROM v2; +CREATE VIEW v3 AS SELECT t2.a,v1.a as b FROM t2,v1 where t2.a=v1.a; +CREATE OR REPLACE ALGORITHM = TEMPTABLE VIEW v2 AS SELECT * FROM t1; + +--error ER_NON_UPDATABLE_TABLE +UPDATE v1 SET a = 10; +--error ER_NON_INSERTABLE_TABLE +REPLACE v1 SET a = 10; +--error ER_NON_INSERTABLE_TABLE +INSERT into v1 values (20); +--error ER_NON_UPDATABLE_TABLE +DELETE from v1; +--error ER_NON_UPDATABLE_TABLE +UPDATE v3 SET b= 10; +--error ER_NON_INSERTABLE_TABLE +REPLACE v3 SET b= 10; +--error ER_NON_INSERTABLE_TABLE +INSERT into v3(b) values (20); +--error ER_VIEW_DELETE_MERGE_VIEW +DELETE from v3 where b=20; +--error ER_VIEW_DELETE_MERGE_VIEW +DELETE from v3 where a=20; +--error ER_NON_UPDATABLE_TABLE +DELETE v1 from v1,t1 where v1.a=t1.a; +UPDATE v3 SET a = 10; +REPLACE v3 SET a = 11; +INSERT INTO v3(a) values (20); + +select * from t1; +select * from t2; + +CREATE OR REPLACE ALGORITHM = MERGE VIEW v2 AS SELECT * FROM t2; +DELETE from v1 where a=11; +DELETE v1 from v1,t1 where v1.a=t1.a; +select * from t1; +select * from t2; + +DROP VIEW v1,v2,v3; +DROP TABLE t1,t2; + +--echo # ----------------------------------------------------------------- +--echo # -- End of 5.2 tests. +--echo # ----------------------------------------------------------------- --echo # --echo # Bug #59696 Optimizer does not use equalities for conditions over view @@ -4493,4 +4546,8 @@ SELECT * FROM t1 RIGHT JOIN v2 ON ( v2.a = t1.a ) WHERE v2.b IN ( SELECT b FROM DROP VIEW v2; DROP TABLE t1, t2, t3; +--echo # ----------------------------------------------------------------- +--echo # -- End of 5.3 tests. +--echo # ----------------------------------------------------------------- + SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 6ee1167621a..b0d754211cd 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -413,133 +413,19 @@ fun:__libc_start_main } -{ - dlclose memory loss from udf_free - Memcheck:Leak - fun:calloc - fun:_dlerror_run - fun:dlclose - fun:_Z8udf_freev -} +# +# dlclose can allocate memory for error message, the memory will be +# freed by dlerror or other dl* function. +# { - dlsym memory loss from udf_free on SuSE 11.1 x64 variant 2 + memory "loss" from dlclose error messages Memcheck:Leak - fun:calloc - obj:/lib*/ld-*.so - fun:dlclose - fun:udf_free -} - -{ - dlclose memory loss from plugin variant 1 - Memcheck:Leak - fun:calloc - fun:_dlerror_run - fun:dlclose - fun:plugin_dl_del(st_mysql_lex_string const*) -} - -{ - dlclose memory loss from plugin variant 2 - Memcheck:Leak - fun:malloc - fun:_dl_close_worker - fun:_dl_close - fun:_dl_catch_error - fun:_dlerror_run - fun:dlclose - fun:_Z15free_plugin_memP12st_plugin_dl - fun:_Z13plugin_dl_delPK19st_mysql_lex_string -} - -{ - dlclose memory loss from plugin variant 3 - Memcheck:Leak - fun:malloc - fun:_dl_scope_free - fun:_dl_close_worker - fun:_dl_close - fun:_dl_catch_error - fun:_dlerror_run - fun:dlclose - fun:_Z15free_plugin_memP12st_plugin_dl - fun:_Z13plugin_dl_delPK19st_mysql_lex_string -} - -{ - dlclose memory loss from plugin variant 4 - Memcheck:Leak - fun:malloc - obj:/lib*/ld-*.so - obj:/lib*/ld-*.so - obj:/lib*/ld-*.so - obj:/lib*/libdl-*.so - fun:dlclose - fun:_ZL15free_plugin_memP12st_plugin_dl - fun:_ZL13plugin_dl_delPK19st_mysql_lex_string -} - -{ - dlclose memory loss from plugin variant 5 - Memcheck:Leak - fun:malloc - obj:/lib*/ld-*.so - obj:/lib*/ld-*.so - obj:/lib*/ld-*.so - obj:/lib*/ld-*.so - obj:/lib*/libdl-*.so + fun:*alloc + ... fun:dlclose } -{ - dlclose memory loss from plugin variant 6, seen on Ubuntu Jaunty i686 - Memcheck:Leak - fun:malloc - fun:_dl_scope_free - fun:_dl_close_worker - fun:_dl_close - fun:dlclose_doit - fun:_dl_catch_error - fun:_dlerror_run - fun:dlclose - fun:_ZL15free_plugin_memP12st_plugin_dl - fun:_ZL13plugin_dl_delPK19st_mysql_lex_string -} - -{ - dlclose memory loss from plugin variant 7, seen on Ubuntu Jaunty i686 - Memcheck:Leak - fun:malloc - fun:_dl_close_worker - fun:_dl_close - fun:dlclose_doit - fun:_dl_catch_error - fun:_dlerror_run - fun:dlclose - fun:_ZL15free_plugin_memP12st_plugin_dl - fun:_ZL13plugin_dl_delPK19st_mysql_lex_string -} - -{ - dlclose memory loss from plugin variant 8 - Memcheck:Leak - fun:calloc - fun:_dlerror_run - fun:dlclose - fun:_Z15free_plugin_memP12st_plugin_dl - fun:_Z13plugin_dl_delPK19st_mysql_lex_string -} - -{ - dlclose memory loss from plugin variant 9 - Memcheck:Leak - fun:calloc - fun:_dlerror_run - fun:dlclose - fun:_ZL15free_plugin_memP12st_plugin_dl - fun:_ZL13plugin_dl_delPK19st_mysql_lex_string -} { dlclose memory loss from plugin variant 10 diff --git a/plugin/auth_dialog/dialog.c b/plugin/auth_dialog/dialog.c index 2026369bc26..0fa5ab93a35 100644 --- a/plugin/auth_dialog/dialog.c +++ b/plugin/auth_dialog/dialog.c @@ -148,6 +148,8 @@ static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) if (res) return CR_ERROR; + first= 0; + /* repeat unless it was the last question */ } while ((cmd & 1) != 1); diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index 45c49975f6e..ee13b37f793 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -8,6 +9,24 @@ struct param { MYSQL_PLUGIN_VIO *vio; }; +/* It least solaris doesn't have strndup */ + +#ifndef HAVE_STRNDUP +char *strndup(const char *from, size_t length) +{ + char *ptr; + size_t max_length= strlen(from); + if (length > max_length) + length= max_length; + if ((ptr= (char*) malloc(length+1)) != 0) + { + memcpy((char*) ptr, (char*) from, length); + ptr[length]=0; + } + return ptr; +} +#endif + static int conv(int n, const struct pam_message **msg, struct pam_response **resp, void *data) { @@ -71,13 +90,21 @@ static int conv(int n, const struct pam_message **msg, #define DO(X) if ((status = (X)) != PAM_SUCCESS) goto end +#ifdef SOLARIS +typedef void** pam_get_item_3_arg; +#else +typedef const void** pam_get_item_3_arg; +#endif + static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { pam_handle_t *pamh = NULL; int status; const char *new_username; struct param param; - struct pam_conv c = { &conv, ¶m }; + /* The following is written in such a way to make also solaris happy */ + struct pam_conv pam_start_arg = { &conv, NULL }; + pam_start_arg.appdata_ptr= (char*) ¶m; /* get the service name, as specified in @@ -90,10 +117,10 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) param.ptr = param.buf + 1; param.vio = vio; - DO( pam_start(service, info->user_name, &c, &pamh) ); + DO( pam_start(service, info->user_name, &pam_start_arg, &pamh) ); DO( pam_authenticate (pamh, 0) ); DO( pam_acct_mgmt(pamh, 0) ); - DO( pam_get_item(pamh, PAM_USER, (const void**)&new_username) ); + DO( pam_get_item(pamh, PAM_USER, (pam_get_item_3_arg) &new_username) ); if (new_username && strcmp(new_username, info->user_name)) strncpy(info->authenticated_as, new_username, @@ -104,7 +131,7 @@ end: return status == PAM_SUCCESS ? CR_OK : CR_ERROR; } -static struct st_mysql_auth pam_info = +static struct st_mysql_auth info = { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "dialog", @@ -114,7 +141,7 @@ static struct st_mysql_auth pam_info = maria_declare_plugin(pam) { MYSQL_AUTHENTICATION_PLUGIN, - &pam_info, + &info, "pam", "Sergei Golubchik", "PAM based authentication", diff --git a/plugin/auth_socket/auth_socket.c b/plugin/auth_socket/auth_socket.c index dbc8513e5dd..41cb1039fd2 100644 --- a/plugin/auth_socket/auth_socket.c +++ b/plugin/auth_socket/auth_socket.c @@ -89,7 +89,7 @@ mysql_declare_plugin(socket_auth) { MYSQL_AUTHENTICATION_PLUGIN, &socket_auth_handler, - "auth_socket", + "unix_socket", "Sergei Golubchik", "Unix Socket based authentication", PLUGIN_LICENSE_GPL, @@ -106,7 +106,7 @@ maria_declare_plugin(socket_auth) { MYSQL_AUTHENTICATION_PLUGIN, &socket_auth_handler, - "auth_socket", + "unix_socket", "Sergei Golubchik", "Unix Socket based authentication", PLUGIN_LICENSE_GPL, diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index f04c33ce90b..36d5da94b11 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4069,6 +4069,8 @@ int ha_partition::rnd_next(uchar *buf) int result= HA_ERR_END_OF_FILE; uint part_id= m_part_spec.start_part; DBUG_ENTER("ha_partition::rnd_next"); + + /* upper level will increment this once again at end of call */ decrement_statistics(&SSV::ha_read_rnd_next_count); if (NO_CURRENT_PART_ID == part_id) diff --git a/sql/item.cc b/sql/item.cc index 02cbe9b7f49..de4716350c2 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5378,7 +5378,8 @@ bool Item_field::set_no_const_sub(uchar *arg) Item *Item_field::replace_equal_field(uchar *arg) { - if (item_equal && item_equal == (Item_equal *) arg) + REPLACE_EQUAL_FIELD_ARG* param= (REPLACE_EQUAL_FIELD_ARG*)arg; + if (item_equal && item_equal == param->item_equal) { Item *const_item= item_equal->get_const(); if (const_item) @@ -5387,7 +5388,8 @@ Item *Item_field::replace_equal_field(uchar *arg) return this; return const_item; } - Item_field *subst= (Item_field *)(item_equal->get_first(this)); + Item_field *subst= + (Item_field *)(item_equal->get_first(param->context_tab, this)); if (subst) subst= (Item_field *) (subst->real_item()); if (subst && !field->eq(subst->field)) @@ -9467,13 +9469,13 @@ void Item_type_holder::get_full_info(Item *item) DBUG_ASSERT((enum_set_typelib && get_real_type(item) == MYSQL_TYPE_NULL) || (!enum_set_typelib && - item->type() == Item::FIELD_ITEM && - (get_real_type(item) == MYSQL_TYPE_ENUM || - get_real_type(item) == MYSQL_TYPE_SET) && - ((Field_enum*)((Item_field *) item)->field)->typelib)); + item->real_item()->type() == Item::FIELD_ITEM && + (get_real_type(item->real_item()) == MYSQL_TYPE_ENUM || + get_real_type(item->real_item()) == MYSQL_TYPE_SET) && + ((Field_enum*)((Item_field *) item->real_item())->field)->typelib)); if (!enum_set_typelib) { - enum_set_typelib= ((Field_enum*)((Item_field *) item)->field)->typelib; + enum_set_typelib= ((Field_enum*)((Item_field *) item->real_item())->field)->typelib; } } } @@ -9558,18 +9560,22 @@ void Item_ref::update_used_tables() } -table_map Item_direct_view_ref::used_tables() const +table_map Item_direct_view_ref::used_tables() const { - return get_depended_from() ? + return get_depended_from() ? OUTER_REF_TABLE_BIT : - (view->merged ? (*ref)->used_tables() : view->table->map); + ((view->merged || !view->table) ? + (*ref)->used_tables() : + view->table->map); } -table_map Item_direct_view_ref::not_null_tables() const +table_map Item_direct_view_ref::not_null_tables() const { - return get_depended_from() ? + return get_depended_from() ? 0 : - (view->merged ? (*ref)->not_null_tables() : view->table->map); + ((view->merged || !view->table) ? + (*ref)->not_null_tables() : + view->table->map); } /* @@ -9583,6 +9589,8 @@ table_map Item_ref_null_helper::used_tables() const } +#ifndef DBUG_OFF + /* Debugger help function */ static char dbug_item_print_buf[256]; @@ -9599,6 +9607,9 @@ const char *dbug_print_item(Item *item) else return "Couldn't fit into buffer"; } + +#endif /*DBUG_OFF*/ + /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/item.h b/sql/item.h index 4732a1a4657..6c0d3138b62 100644 --- a/sql/item.h +++ b/sql/item.h @@ -471,6 +471,16 @@ typedef enum monotonicity_info class sp_rcontext; +class Item_equal; + +struct st_join_table* const NO_PARTICULAR_TAB= (struct st_join_table*)0x1; + +typedef struct replace_equal_field_arg +{ + Item_equal *item_equal; + struct st_join_table *context_tab; +} REPLACE_EQUAL_FIELD_ARG; + class Settable_routine_parameter { public: @@ -1283,6 +1293,7 @@ public: virtual Item *equal_fields_propagator(uchar * arg) { return this; } virtual bool set_no_const_sub(uchar *arg) { return FALSE; } + /* arg points to REPLACE_EQUAL_FIELD_ARG object */ virtual Item *replace_equal_field(uchar * arg) { return this; } /* Check if an expression value has allowed arguments, like DATE/DATETIME diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b3954c55394..4ea5e9534a8 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5804,7 +5804,7 @@ longlong Item_equal::val_int() void Item_equal::fix_length_and_dec() { - Item *item= get_first(NULL); + Item *item= get_first(NO_PARTICULAR_TAB, NULL); eval_item= cmp_item::get_comparator(item->cmp_type(), item, item->collation.collation); } @@ -5904,7 +5904,7 @@ CHARSET_INFO *Item_equal::compare_collation() @retval 0 if no field found. */ -Item* Item_equal::get_first(Item *field_item) +Item* Item_equal::get_first(JOIN_TAB *context, Item *field_item) { Item_equal_fields_iterator it(*this); Item *item; @@ -5932,18 +5932,24 @@ Item* Item_equal::get_first(Item *field_item) in presense of SJM nests. */ - TABLE_LIST *emb_nest= field->table->pos_in_table_list->embedding; + TABLE_LIST *emb_nest; + if (context != NO_PARTICULAR_TAB) + emb_nest= context->emb_sj_nest; + else + emb_nest= field->table->pos_in_table_list->embedding; if (emb_nest && emb_nest->sj_mat_info && emb_nest->sj_mat_info->is_used) { /* - It's a field from an materialized semi-join. We can substitute it only - for a field from the same semi-join. Find the first of such items. + It's a field from an materialized semi-join. We can substitute it for + - a constant item + - a field from the same semi-join + Find the first of such items: */ - while ((item= it++)) { - if (it.get_curr_field()->table->pos_in_table_list->embedding == emb_nest) + if (item->const_item() || + it.get_curr_field()->table->pos_in_table_list->embedding == emb_nest) { /* If we found given field then return NULL to avoid unnecessary diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7b2193b1acd..384c91d5d2e 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1705,7 +1705,7 @@ public: /** Add a non-constant item to the multiple equality */ void add(Item *f) { equal_items.push_back(f); } bool contains(Field *field); - Item* get_first(Item *field); + Item* get_first(struct st_join_table *context, Item *field); /** Get number of field items / references to field items in this object */ uint n_field_items() { return equal_items.elements-test(with_const); } void merge(Item_equal *item); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5f78cdf167b..50625286348 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1271,7 +1271,8 @@ void Item_exists_subselect::fix_length_and_dec() We need only 1 row to determine existence (i.e. any EXISTS that is not an IN always requires LIMIT 1) */ - unit->global_parameters->select_limit= new Item_int((int32) 1); + thd->change_item_tree(&unit->global_parameters->select_limit, + new Item_int((int32) 1)); DBUG_PRINT("info", ("Set limit to 1")); DBUG_VOID_RETURN; } @@ -1597,7 +1598,6 @@ Item_in_subselect::single_value_transformer(JOIN *join) (Item**)optimizer->get_cache(), (char *)"", (char *)in_left_expr_name); - } DBUG_RETURN(false); @@ -1684,10 +1684,6 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) DBUG_EXECUTE("where", print_where(item, "rewrite with MIN/MAX", QT_ORDINARY);); - if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) - { - select_lex->set_non_agg_field_used(false); - } save_allow_sum_func= thd->lex->allow_sum_func; thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; @@ -2244,7 +2240,12 @@ bool Item_in_subselect::create_in_to_exists_cond(JOIN *join_arg) /* The IN=>EXISTS transformation makes non-correlated subqueries correlated. */ - join_arg->select_lex->uncacheable|= UNCACHEABLE_DEPENDENT_INJECTED; + if (!left_expr->const_item() || left_expr->is_expensive()) + { + join_arg->select_lex->uncacheable|= UNCACHEABLE_DEPENDENT_INJECTED; + join_arg->select_lex->master_unit()->uncacheable|= + UNCACHEABLE_DEPENDENT_INJECTED; + } /* The uncacheable property controls a number of actions, e.g. whether to save/restore (via init_save_join_tab/restore_tmp) the original JOIN for @@ -2510,6 +2511,7 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) left_expr && !left_expr->fixed && left_expr->fix_fields(thd_arg, &left_expr)) return TRUE; + else if (Item_subselect::fix_fields(thd_arg, ref)) return TRUE; fixed= TRUE; @@ -3159,6 +3161,8 @@ bool subselect_uniquesubquery_engine::copy_ref_key() for (store_key **copy= tab->ref.key_copy ; *copy ; copy++) { + if ((*copy)->store_key_is_const()) + continue; tab->ref.key_err= (*copy)->copy(); /* diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 6e115854f17..afe4f34bd05 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1129,13 +1129,12 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) return TRUE; decimals=0; - maybe_null=0; + maybe_null= sum_func() != COUNT_FUNC; for (uint i=0 ; i < arg_count ; i++) { if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) return TRUE; set_if_bigger(decimals, args[i]->decimals); - maybe_null |= args[i]->maybe_null; } result_field=0; max_length=float_length(decimals); diff --git a/sql/log.cc b/sql/log.cc index af400c19f4a..9e9716dde67 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5372,6 +5372,7 @@ void MYSQL_BIN_LOG::purge() { purge_logs_before_date(purge_time); } + DEBUG_SYNC(current_thd, "after_purge_logs_before_date"); } #endif } diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index d8dc45d38c7..29e7faa630d 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -482,6 +482,10 @@ void Mrr_ordered_index_reader::resume_read() /** Fill the buffer with (lookup_tuple, range_id) pairs and sort + + @return + 0 OK, the buffer is non-empty and sorted + HA_ERR_END_OF_FILE Source exhausted, the buffer is empty. */ int Mrr_ordered_index_reader::refill_buffer(bool initial) @@ -518,6 +522,13 @@ int Mrr_ordered_index_reader::refill_buffer(bool initial) if (source_exhausted && key_buffer->is_empty()) DBUG_RETURN(HA_ERR_END_OF_FILE); + if (!initial) + { + /* This is a non-initial buffer fill and we've got a non-empty buffer */ + THD *thd= current_thd; + status_var_increment(thd->status_var.ha_mrr_extra_key_sorts); + } + key_buffer->sort((key_buffer->type() == Lifo_buffer::FORWARD)? (qsort2_cmp)Mrr_ordered_index_reader::compare_keys_reverse : (qsort2_cmp)Mrr_ordered_index_reader::compare_keys, @@ -592,6 +603,7 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg, int Mrr_ordered_rndpos_reader::refill_buffer(bool initial) { int res; + bool first_call= initial; DBUG_ENTER("Mrr_ordered_rndpos_reader::refill_buffer"); if (index_reader_exhausted) @@ -609,6 +621,14 @@ int Mrr_ordered_rndpos_reader::refill_buffer(bool initial) initial= FALSE; index_reader_needs_refill= FALSE; } + + if (!first_call && !index_reader_exhausted) + { + /* Ok, this was a successful buffer refill operation */ + THD *thd= current_thd; + status_var_increment(thd->status_var.ha_mrr_extra_rowid_sorts); + } + DBUG_RETURN(res); } @@ -841,8 +861,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, strategy= disk_strategy= &reader_factory.ordered_rndpos_reader; } - if (is_mrr_assoc) - status_var_increment(thd->status_var.ha_multi_range_read_init_count); + status_var_increment(thd->status_var.ha_multi_range_read_init_count); full_buf= buf->buffer; full_buf_end= buf->buffer_end; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2a2361a3d28..df3be29f547 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1884,7 +1884,6 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_delayed_insert); mysql_mutex_destroy(&LOCK_delayed_status); mysql_mutex_destroy(&LOCK_delayed_create); - mysql_mutex_destroy(&LOCK_manager); mysql_mutex_destroy(&LOCK_crypt); mysql_mutex_destroy(&LOCK_user_conn); mysql_mutex_destroy(&LOCK_connection_count); @@ -1915,7 +1914,6 @@ static void clean_up_mutexes() mysql_cond_destroy(&COND_thread_count); mysql_cond_destroy(&COND_thread_cache); mysql_cond_destroy(&COND_flush_thread_cache); - mysql_cond_destroy(&COND_manager); mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); mysql_mutex_destroy(&LOCK_prepare_ordered); @@ -3777,8 +3775,6 @@ static int init_thread_environment() &LOCK_delayed_status, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_delayed_create, &LOCK_delayed_create, MY_MUTEX_INIT_SLOW); - mysql_mutex_init(key_LOCK_manager, - &LOCK_manager, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_active_mi, &LOCK_active_mi, MY_MUTEX_INIT_FAST); @@ -3827,7 +3823,6 @@ static int init_thread_environment() mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL); mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL); mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL); - mysql_cond_init(key_COND_manager, &COND_manager, NULL); #ifdef HAVE_REPLICATION mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_rpl_status, &COND_rpl_status, NULL); @@ -6886,6 +6881,12 @@ SHOW_VAR status_vars[]= { {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS}, {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, {"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS}, +#if 0 + /* Made 3 counters below temporarily invisible until we agree upon their names */ + {"Handler_mrr_extra_key_sorts", (char*) offsetof(STATUS_VAR, ha_mrr_extra_key_sorts), SHOW_LONG_STATUS}, + {"Handler_mrr_extra_rowid_sorts", (char*) offsetof(STATUS_VAR, ha_mrr_extra_rowid_sorts), SHOW_LONG_STATUS}, + {"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_multi_range_read_init_count), SHOW_LONG_STATUS}, +#endif {"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONG_STATUS}, {"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS}, {"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS}, @@ -6893,14 +6894,15 @@ SHOW_VAR status_vars[]= { {"Handler_read_next", (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS}, {"Handler_read_prev", (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS}, {"Handler_read_rnd", (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS}, + {"Handler_read_rnd_deleted", (char*) offsetof(STATUS_VAR, ha_read_rnd_deleted_count), SHOW_LONG_STATUS}, {"Handler_read_rnd_next", (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS}, {"Handler_rollback", (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS}, {"Handler_savepoint", (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS}, {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS}, - {"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS}, - {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS}, {"Handler_tmp_update", (char*) offsetof(STATUS_VAR, ha_tmp_update_count), SHOW_LONG_STATUS}, {"Handler_tmp_write", (char*) offsetof(STATUS_VAR, ha_tmp_write_count), SHOW_LONG_STATUS}, + {"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS}, + {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS}, {"Key", (char*) &show_default_keycache, SHOW_FUNC}, {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 3b1991d1686..6376b1ac33f 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -4080,7 +4080,8 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, { uint i; DBUG_ENTER("setup_semijoin_dups_elimination"); - + + join->complex_firstmatch_tables= table_map(0); POSITION *pos= join->best_positions + join->const_tables; for (i= join->const_tables ; i < join->top_join_tab_count; ) @@ -4099,6 +4100,11 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, { /* We jump from the last table to the first one */ tab->loosescan_match_tab= tab + pos->n_sj_tables - 1; + + /* LooseScan requires records to be produced in order */ + if (tab->select && tab->select->quick) + tab->select->quick->need_sorted_output(); + for (uint j= i; j < i + pos->n_sj_tables; j++) join->join_tab[j].inside_loosescan_range= TRUE; @@ -4108,6 +4114,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, for (uint kp=0; kp < pos->loosescan_picker.loosescan_parts; kp++) keylen += tab->table->key_info[keyno].key_part[kp].store_length; + tab->loosescan_key= keyno; tab->loosescan_key_len= keylen; if (pos->n_sj_tables > 1) tab[pos->n_sj_tables - 1].do_firstmatch= tab; @@ -4163,16 +4170,46 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, } case SJ_OPT_FIRST_MATCH: { - JOIN_TAB *j, *jump_to= tab-1; + JOIN_TAB *j; + JOIN_TAB *jump_to= tab-1; + + bool complex_range= FALSE; + table_map tables_in_range= table_map(0); + for (j= tab; j != tab + pos->n_sj_tables; j++) { - /* - NOTE: this loop probably doesn't do the right thing for the case - where FirstMatch's duplicate-generating range is interleaved with - "unrelated" tables (as specified in WL#3750, section 2.2). - */ + tables_in_range |= j->table->map; if (!j->emb_sj_nest) - jump_to= tab; + { + /* + Got a table that's not within any semi-join nest. This is a case + like this: + + SELECT * FROM ot1, nt1 WHERE ot1.col IN (SELECT expr FROM it1, it2) + + with a join order of + + +----- FirstMatch range ----+ + | | + ot1 it1 nt1 nt2 it2 it3 ... + | ^ + | +-------- 'j' points here + +------------- SJ_OPT_FIRST_MATCH was set for this table as + it's the first one that produces duplicates + + */ + DBUG_ASSERT(j != tab); /* table ntX must have an itX before it */ + + /* + If the table right before us is an inner table (like it1 in the + picture), it should be set to jump back to previous outer-table + */ + if (j[-1].emb_sj_nest) + j[-1].do_firstmatch= jump_to; + + jump_to= j; /* Jump back to us */ + complex_range= TRUE; + } else { j->first_sj_inner_tab= tab; @@ -4182,6 +4219,9 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, j[-1].do_firstmatch= jump_to; i+= pos->n_sj_tables; pos+= pos->n_sj_tables; + + if (complex_range) + join->complex_firstmatch_tables|= tables_in_range; break; } case SJ_OPT_NONE: diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index cda35895a3d..7087a85d13a 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -627,7 +627,12 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, if (!cond) DBUG_RETURN(TRUE); Field *field= field_part->field; - if (!(cond->used_tables() & field->table->map)) + if (cond->used_tables() & OUTER_REF_TABLE_BIT) + { + DBUG_RETURN(FALSE); + } + if (!(cond->used_tables() & field->table->map) && + test(cond->used_tables() & ~PSEUDO_TABLE_BITS)) { /* Condition doesn't restrict the used table */ DBUG_RETURN(!cond->const_item()); diff --git a/sql/slave.cc b/sql/slave.cc index 98b75bc6dad..2b73cad1d7b 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2927,9 +2927,8 @@ pthread_handler_t handle_slave_io(void *arg) if (init_slave_thread(thd, SLAVE_THD_IO)) { mysql_cond_broadcast(&mi->start_cond); - mysql_mutex_unlock(&mi->run_lock); sql_print_error("Failed during slave I/O thread initialization"); - goto err; + goto err_during_init; } mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); @@ -3232,6 +3231,7 @@ err: thd_proc_info(thd, "Waiting for slave mutex on exit"); mysql_mutex_lock(&mi->run_lock); +err_during_init: /* Forget the relay log's format */ delete mi->rli.relay_log.description_event_for_queue; mi->rli.relay_log.description_event_for_queue= 0; @@ -3357,10 +3357,9 @@ pthread_handler_t handle_slave_sql(void *arg) will be stuck if we fail here */ mysql_cond_broadcast(&rli->start_cond); - mysql_mutex_unlock(&rli->run_lock); rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, "Failed during slave thread initialization"); - goto err; + goto err_during_init; } thd->init_for_queries(); thd->temporary_tables = rli->save_temporary_tables; // restore temp tables @@ -3613,6 +3612,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ thd->reset_db(NULL, 0); thd_proc_info(thd, "Waiting for slave mutex on exit"); mysql_mutex_lock(&rli->run_lock); +err_during_init: /* We need data_lock, at least to wake up any waiting master_pos_wait() */ mysql_mutex_lock(&rli->data_lock); DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 92747066121..15c3999be54 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8399,22 +8399,9 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, ulong client_capabilities= uint2korr(net->read_pos); if (client_capabilities & CLIENT_PROTOCOL_41) { - if (pkt_len < 32) + if (pkt_len < 4) return packet_error; client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; - thd->max_client_packet_length= uint4korr(net->read_pos+4); - DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8])); - if (thd_init_client_charset(thd, (uint) net->read_pos[8])) - return packet_error; - thd->update_charset(); - end= (char*) net->read_pos + 32; - } - else - { - if (pkt_len < 5) - return packet_error; - thd->max_client_packet_length= uint3korr(net->read_pos+2); - end= (char*) net->read_pos+5; } /* Disable those bits which are not supported by the client. */ @@ -8446,6 +8433,28 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, } } + if (client_capabilities & CLIENT_PROTOCOL_41) + { + if (pkt_len < 32) + return packet_error; + thd->max_client_packet_length= uint4korr(net->read_pos+4); + DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8])); + if (thd_init_client_charset(thd, (uint) net->read_pos[8])) + return packet_error; + thd->update_charset(); + end= (char*) net->read_pos+32; + } + else + { + if (pkt_len < 5) + return packet_error; + thd->max_client_packet_length= uint3korr(net->read_pos+2); + end= (char*) net->read_pos+5; + } + + if (end >= (char*) net->read_pos+ pkt_len +2) + return packet_error; + if (thd->client_capabilities & CLIENT_IGNORE_SPACE) thd->variables.sql_mode|= MODE_IGNORE_SPACE; if (thd->client_capabilities & CLIENT_INTERACTIVE) diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index f01e279333d..5897d74582a 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -935,6 +935,11 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, DBUG_RETURN(TRUE); } mysql_mutex_unlock(&LOCK_global_system_variables); + if (!key_cache->key_cache_inited) + { + my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str); + DBUG_RETURN(true); + } check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, "assign_to_keycache", TL_READ_NO_INSERT, 0, 0, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1d215f5aa40..3167cb7363d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1923,14 +1923,15 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, t_name= table->table_name; t_alias= table->alias; +retry: DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name)); - for (;;) + for (TABLE_LIST *tl= table_list;;) { /* Table is unique if it is present only once in the global list of tables and once in the list of table locks. */ - if (! (res= find_table_in_global_list(table_list, d_name, t_name))) + if (! (res= find_table_in_global_list(tl, d_name, t_name))) break; /* Skip if same underlying table. */ @@ -1961,10 +1962,23 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, (exclude_from_table_unique_test) or prelocking placeholder. */ next: - table_list= res->next_global; + tl= res->next_global; DBUG_PRINT("info", ("found same copy of table or table which we should skip")); } + if (res && res->belong_to_derived) + { + /* Try to fix */ + TABLE_LIST *derived= res->belong_to_derived; + if (derived->is_merged_derived()) + { + DBUG_PRINT("info", + ("convert merged to materialization to resolve the conflict")); + derived->change_refs_to_fields(); + derived->set_materialized_derived(); + } + goto retry; + } DBUG_RETURN(res); } @@ -7363,11 +7377,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, if (!(eq_cond= new Item_func_eq(item_ident_1, item_ident_2))) goto err; /* Out of memory. */ + if (field_1 && field_1->vcol_info) + field_1->table->mark_virtual_col(field_1); + if (field_2 && field_2->vcol_info) + field_2->table->mark_virtual_col(field_2); + /* Add the new equi-join condition to the ON clause. Notice that fix_fields() is applied to all ON conditions in setup_conds() so we don't do it here. - */ + */ add_join_on((table_ref_1->outer_join & JOIN_TYPE_RIGHT ? table_ref_1 : table_ref_2), eq_cond); @@ -8085,7 +8104,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context, while ((table_list= ti++)) { TABLE *table= table_list->table; - table->pos_in_table_list= table_list; + if (table) + table->pos_in_table_list= table_list; if (first_select_table && table_list->top_table() == first_select_table) { @@ -8098,7 +8118,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context, { table_list->jtbm_table_no= tablenr; } - else + else if (table) { table->pos_in_table_list= table_list; setup_table_map(table, table_list, tablenr); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 0a1185a9924..9c86b2838c4 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1463,10 +1463,10 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", In case the wait time can't be determined there is an upper limit which causes try_lock() to abort with a time out. - The 'TRUE' parameter indicate that the lock is allowed to timeout + The 'TIMEOUT' parameter indicate that the lock is allowed to timeout */ - if (try_lock(thd, Query_cache::WAIT)) + if (try_lock(thd, Query_cache::TIMEOUT)) DBUG_VOID_RETURN; if (query_cache_size == 0) { @@ -1674,6 +1674,17 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length) if (is_disabled() || thd->locked_tables_mode || thd->variables.query_cache_type == 0) goto err; + + /* + The following can only happen for prepared statements that was found + during parsing or later that the query was not cacheable. + */ + if (!thd->lex->safe_to_cache_query) + { + DBUG_PRINT("qcache", ("SELECT is non-cacheable")); + goto err; + } + DBUG_ASSERT(query_cache_size != 0); // otherwise cache would be disabled thd->query_cache_is_applicable= 1; @@ -1959,6 +1970,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", faster. */ thd->query_cache_is_applicable= 0; // Query can't be cached + thd->lex->safe_to_cache_query= 0; // For prepared statements BLOCK_UNLOCK_RD(query_block); DBUG_RETURN(-1); } @@ -1975,6 +1987,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", table_list.db, table_list.alias)); unlock(); thd->query_cache_is_applicable= 0; // Query can't be cached + thd->lex->safe_to_cache_query= 0; // For prepared statements BLOCK_UNLOCK_RD(query_block); DBUG_RETURN(-1); // Privilege error } @@ -1984,6 +1997,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", table_list.db, table_list.alias)); BLOCK_UNLOCK_RD(query_block); thd->query_cache_is_applicable= 0; // Query can't be cached + thd->lex->safe_to_cache_query= 0; // For prepared statements goto err_unlock; // Parse query } #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ @@ -2007,7 +2021,13 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", table->key_length()); } else + { + /* + As this can change from call to call, don't reset set + thd->lex->safe_to_cache_query + */ thd->query_cache_is_applicable= 0; // Query can't be cached + } /* End the statement transaction potentially started by engine. */ trans_rollback_stmt(thd); goto err_unlock; // Parse query @@ -3901,6 +3921,7 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used, DBUG_PRINT("qcache", ("Don't cache statement as it refers to " "tables with column privileges.")); thd->query_cache_is_applicable= 0; // Query can't be cached + thd->lex->safe_to_cache_query= 0; // For prepared statements DBUG_RETURN(0); } #endif @@ -4037,6 +4058,10 @@ my_bool Query_cache::ask_handler_allowance(THD *thd, { DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s", tables_used->db, tables_used->alias)); + /* + As this can change from call to call, don't reset set + thd->lex->safe_to_cache_query + */ thd->query_cache_is_applicable= 0; // Query can't be cached DBUG_RETURN(1); } diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 9d713d012f5..134fd055110 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -443,8 +443,8 @@ protected: uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE, uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE); - bool is_disabled(void) { return m_cache_status != OK; } - bool is_disable_in_progress(void) + inline bool is_disabled(void) { return m_cache_status != OK; } + inline bool is_disable_in_progress(void) { return m_cache_status == DISABLE_REQUEST; } /* initialize cache (mutex) */ diff --git a/sql/sql_class.h b/sql/sql_class.h index ce000adc785..563a9adefce 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -585,12 +585,15 @@ typedef struct system_status_var ulong ha_read_prev_count; ulong ha_read_rnd_count; ulong ha_read_rnd_next_count; + ulong ha_read_rnd_deleted_count; /* This number doesn't include calls to the default implementation and calls made by range access. The intent is to count only calls made by BatchedKeyAccess. */ ulong ha_multi_range_read_init_count; + ulong ha_mrr_extra_key_sorts; + ulong ha_mrr_extra_rowid_sorts; ulong ha_rollback_count; ulong ha_update_count; @@ -4221,10 +4224,17 @@ inline int handler::ha_ft_read(uchar *buf) inline int handler::ha_rnd_next(uchar *buf) { MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, TRUE); - increment_statistics(&SSV::ha_read_rnd_next_count); int error= rnd_next(buf); if (!error) + { update_rows_read(); + increment_statistics(&SSV::ha_read_rnd_next_count); + } + else if (error == HA_ERR_RECORD_DELETED) + increment_statistics(&SSV::ha_read_rnd_deleted_count); + else + increment_statistics(&SSV::ha_read_rnd_next_count); + table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_READ_ROW_DONE(error); return error; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index f48724236d4..ff88bf7c0f8 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -76,7 +76,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE)) DBUG_RETURN(TRUE); - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); DBUG_RETURN(TRUE); @@ -476,7 +476,8 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); - if (!table_list->updatable || check_key_in_view(thd, table_list)) + if (!table_list->single_table_updatable() || + check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); DBUG_RETURN(TRUE); @@ -572,7 +573,7 @@ int mysql_multi_delete_prepare(THD *thd) DBUG_RETURN(TRUE); } - if (!target_tbl->correspondent_table->updatable || + if (!target_tbl->correspondent_table->single_table_updatable() || check_key_in_view(thd, target_tbl->correspondent_table)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 13985becff7..9f06c99c472 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -483,7 +483,7 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) return mysql_derived_prepare(thd, lex, derived); if (!derived->is_multitable()) { - if (!derived->updatable) + if (!derived->single_table_updatable()) return derived->create_field_translation(thd); if (derived->merge_underlying_list) { @@ -750,7 +750,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) if (!derived->is_merged_derived()) { JOIN *join= first_select->join; - unit->set_limit(first_select); + unit->set_limit(unit->global_parameters); unit->optimized= TRUE; if ((res= join->optimize())) goto err; @@ -865,7 +865,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) } else { - unit->set_limit(first_select); + unit->set_limit(unit->global_parameters); if (unit->select_limit_cnt == HA_POS_ERROR) first_select->options&= ~OPTION_FOUND_ROWS; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c7423d9bada..2209a62d7ed 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -118,7 +118,8 @@ static bool check_view_insertability(THD *thd, TABLE_LIST *view); */ bool check_view_single_update(List &fields, List *values, - TABLE_LIST *view, table_map *map) + TABLE_LIST *view, table_map *map, + bool insert) { /* it is join view => we need to find the table for update */ List_iterator_fast it(fields); @@ -156,6 +157,14 @@ bool check_view_single_update(List &fields, List *values, */ tbl->table->insert_values= view->table->insert_values; view->table= tbl->table; + if (!tbl->single_table_updatable()) + { + if (insert) + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); + else + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "UPDATE"); + return TRUE; + } *map= tables; return FALSE; @@ -200,7 +209,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, { TABLE *table= table_list->table; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; @@ -276,7 +285,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (check_view_single_update(fields, fields_and_values_from_different_maps ? (List*) 0 : &values, - table_list, map)) + table_list, map, true)) return -1; table= table_list->table; } @@ -363,7 +372,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, if (insert_table_list->is_view() && insert_table_list->is_merged_derived() && check_view_single_update(update_fields, &update_values, - insert_table_list, map)) + insert_table_list, map, false)) return -1; if (table->timestamp_field) @@ -1255,7 +1264,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, bool insert_into_view= (table_list->view != 0); DBUG_ENTER("mysql_prepare_insert_check_table"); - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); DBUG_RETURN(TRUE); diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 3600bbbb65f..f0362585e39 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -899,6 +899,8 @@ int JOIN_CACHE::alloc_buffer() curr_buff_space_sz+= cache->get_join_buffer_size(); } } + curr_min_buff_space_sz+= min_buff_size; + curr_buff_space_sz+= buff_size; if (curr_min_buff_space_sz > join_buff_space_limit || (curr_buff_space_sz > join_buff_space_limit && @@ -2110,16 +2112,6 @@ enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last) if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS) goto finish; } - if (outer_join_first_inner) - { - /* - All null complemented rows have been already generated for all - outer records from join buffer. Restore the state of the - first_unmatched values to 0 to avoid another null complementing. - */ - for (tab= join_tab->first_inner; tab <= join_tab->last_inner; tab++) - tab->first_unmatched= 0; - } if (skip_last) { @@ -2132,6 +2124,16 @@ enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last) } finish: + if (outer_join_first_inner) + { + /* + All null complemented rows have been already generated for all + outer records from join buffer. Restore the state of the + first_unmatched values to 0 to avoid another null complementing. + */ + for (tab= join_tab->first_inner; tab <= join_tab->last_inner; tab++) + tab->first_unmatched= 0; + } restore_last_record(); reset(TRUE); DBUG_PRINT("exit", ("rc: %d", rc)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 04de1325480..56e05c3dcad 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2847,7 +2847,7 @@ void st_select_lex_unit::set_limit(st_select_lex *sl) DBUG_ASSERT(fix_fields_successful); } - val= fix_fields_successful ? item->val_uint() : HA_POS_ERROR; + val= fix_fields_successful ? item->val_uint() : 0; } else val= ULL(0); @@ -3167,6 +3167,7 @@ void LEX::cleanup_after_one_table_open() if (all_selects_list != &select_lex) { derived_tables= 0; + select_lex.exclude_from_table_unique_test= false; /* cleunup underlying units (units of VIEW) */ for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit(); un; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index aab9ea76499..33d1741b5ec 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -235,7 +235,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, INSERT_ACL | UPDATE_ACL, FALSE)) DBUG_RETURN(-1); if (!table_list->table || // do not suport join view - !table_list->updatable || // and derived tables + !table_list->single_table_updatable() || // and derived tables check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index 221ba56130a..e9ac55730d3 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -43,6 +43,7 @@ static struct handler_cb * volatile cb_list; bool mysql_manager_submit(void (*action)()) { bool result= FALSE; + DBUG_ASSERT(manager_thread_in_use); struct handler_cb * volatile *cb; mysql_mutex_lock(&LOCK_manager); cb= &cb_list; @@ -74,8 +75,9 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) pthread_detach_this_thread(); manager_thread = pthread_self(); + mysql_cond_init(key_COND_manager, &COND_manager,NULL); + mysql_mutex_init(key_LOCK_manager, &LOCK_manager, NULL); manager_thread_in_use = 1; - for (;;) { mysql_mutex_lock(&LOCK_manager); @@ -122,6 +124,8 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) } } manager_thread_in_use = 0; + mysql_mutex_destroy(&LOCK_manager); + mysql_cond_destroy(&COND_manager); DBUG_LEAVE; // Can't use DBUG_RETURN after my_thread_end my_thread_end(); return (NULL); @@ -149,14 +153,14 @@ void stop_handle_manager() { DBUG_ENTER("stop_handle_manager"); abort_manager = true; - mysql_mutex_lock(&LOCK_manager); if (manager_thread_in_use) { + mysql_mutex_lock(&LOCK_manager); DBUG_PRINT("quit", ("initiate shutdown of handle manager thread: 0x%lx", (ulong)manager_thread)); mysql_cond_signal(&COND_manager); + mysql_mutex_unlock(&LOCK_manager); } - mysql_mutex_unlock(&LOCK_manager); DBUG_VOID_RETURN; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c0792b2c342..101b0b52c30 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6676,13 +6676,23 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, if (!threads_to_kill.is_empty()) { List_iterator_fast it(threads_to_kill); - THD *ptr; - while ((ptr= it++)) + THD *next_ptr; + THD *ptr= it++; + do { ptr->awake(kill_signal); + /* + Careful here: The list nodes are allocated on the memroots of the + THDs to be awakened. + But those THDs may be terminated and deleted as soon as we release + LOCK_thd_data, which will make the list nodes invalid. + Since the operation "it++" dereferences the "next" pointer of the + previous list node, we need to do this while holding LOCK_thd_data. + */ + next_ptr= it++; mysql_mutex_unlock(&ptr->LOCK_thd_data); (*rows)++; - } + } while ((ptr= next_ptr)); } DBUG_RETURN(0); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f5a2f409dfc..da9dcc053cf 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1365,7 +1365,7 @@ static int mysql_test_update(Prepared_statement *stmt, if (table_list->handle_derived(thd->lex, DT_PREPARE)) goto error; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); goto error; @@ -1439,7 +1439,7 @@ static bool mysql_test_delete(Prepared_statement *stmt, if (mysql_handle_derived(thd->lex, DT_PREPARE)) goto error; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); goto error; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f22510bb2b7..5e483c2d359 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -131,7 +131,8 @@ static COND *build_equal_items(THD *thd, COND *cond, COND_EQUAL *inherited, List *join_list, COND_EQUAL **cond_equal_ref); -static COND* substitute_for_best_equal_field(COND *cond, +static COND* substitute_for_best_equal_field(JOIN_TAB *context_tab, + COND *cond, COND_EQUAL *cond_equal, void *table_join_idx); static COND *simplify_joins(JOIN *join, List *join_list, @@ -1254,7 +1255,8 @@ JOIN::optimize() */ if (conds) { - conds= substitute_for_best_equal_field(conds, cond_equal, map2table); + conds= substitute_for_best_equal_field(NO_PARTICULAR_TAB, conds, + cond_equal, map2table); conds->update_used_tables(); DBUG_EXECUTE("where", print_where(conds, @@ -1271,7 +1273,8 @@ JOIN::optimize() { if (*tab->on_expr_ref) { - *tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref, + *tab->on_expr_ref= substitute_for_best_equal_field(NO_PARTICULAR_TAB, + *tab->on_expr_ref, tab->cond_equal, map2table); (*tab->on_expr_ref)->update_used_tables(); @@ -1294,7 +1297,7 @@ JOIN::optimize() continue; COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal : cond_equal; - ref_item= substitute_for_best_equal_field(ref_item, equals, map2table); + ref_item= substitute_for_best_equal_field(tab, ref_item, equals, map2table); ref_item->update_used_tables(); if (*ref_item_ptr != ref_item) { @@ -3596,6 +3599,7 @@ make_join_statistics(JOIN *join, List &tables_list, for (i= 0; i < join->table_count ; i++) records*= join->best_positions[i].records_read ? (ha_rows)join->best_positions[i].records_read : 1; + set_if_smaller(records, unit->select_limit_cnt); join->select_lex->increase_derived_records(records); } } @@ -8997,7 +9001,7 @@ void revise_cache_usage(JOIN_TAB *join_tab) first_inner; first_inner= first_inner->first_upper) { - for (tab= end_tab-1; tab >= first_inner; tab--) + for (tab= end_tab; tab >= first_inner; tab--) set_join_cache_denial(tab); end_tab= first_inner; } @@ -9005,7 +9009,7 @@ void revise_cache_usage(JOIN_TAB *join_tab) else if (join_tab->first_sj_inner_tab) { first_inner= join_tab->first_sj_inner_tab; - for (tab= join_tab-1; tab >= first_inner; tab--) + for (tab= join_tab; tab >= first_inner; tab--) { set_join_cache_denial(tab); } @@ -9247,6 +9251,9 @@ uint check_join_cache_usage(JOIN_TAB *tab, if (tab->use_quick == 2) goto no_join_cache; + + if (tab->table->map & join->complex_firstmatch_tables) + goto no_join_cache; /* Don't use join cache if we're inside a join tab range covered by LooseScan @@ -9457,7 +9464,7 @@ void check_join_cache_usage_for_tables(JOIN *join, ulonglong options, { tab->used_join_cache_level= join->max_allowed_join_cache_level; } - + uint idx= join->const_tables; for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); tab; @@ -9542,6 +9549,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) bool statistics= test(!(join->select_options & SELECT_DESCRIBE)); bool sorted= 1; + join->complex_firstmatch_tables= table_map(0); + if (!join->select_lex->sj_nests.is_empty() && setup_semijoin_dups_elimination(join, options, no_jbuf_after)) DBUG_RETURN(TRUE); /* purecov: inspected */ @@ -10422,6 +10431,15 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, } + /* + Cleanup to avoid interference of calls of this function for + ORDER BY and GROUP BY + */ + for (JOIN_TAB *tab= join->join_tab + join->const_tables; + tab < join->join_tab + join->table_count; + tab++) + tab->cached_eq_ref_table= FALSE; + prev_ptr= &first_order; *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1; @@ -11582,7 +11600,7 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, else { TABLE_LIST *emb_nest; - head= item_equal->get_first(NULL); + head= item_equal->get_first(NO_PARTICULAR_TAB, NULL); it++; if ((emb_nest= embedding_sjm(head))) { @@ -11609,7 +11627,7 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, } /* - Check if "item_field=head" equality is already guaranteed to be true + Check if "field_item=head" equality is already guaranteed to be true on upper AND-levels. */ if (upper) @@ -11621,7 +11639,8 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, Item_equal_fields_iterator li(*item_equal); while ((item= li++) != field_item) { - if (item->find_item_equal(upper_levels) == upper) + if (embedding_sjm(item) == field_sjm && + item->find_item_equal(upper_levels) == upper) break; } } @@ -11691,6 +11710,7 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, return cond; } + /** Substitute every field reference in a condition by the best equal field and eliminate all multiple equality predicates. @@ -11705,6 +11725,9 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, After this the function retrieves all other conjuncted predicates substitute every field reference by the field reference to the first equal field or equal constant if there are any. + + @param context_tab Join tab that 'cond' will be attached to, or + NO_PARTICULAR_TAB. See notes above. @param cond condition to process @param cond_equal multiple equalities to take into consideration @param table_join_idx index to tables determining field preference @@ -11715,11 +11738,37 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, new fields in multiple equality item of lower levels. We want the order in them to comply with the order of upper levels. + context_tab may be used to specify which join tab `cond` will be + attached to. There are two possible cases: + + 1. context_tab != NO_PARTICULAR_TAB + We're doing substitution for an Item which will be evaluated in the + context of a particular item. For example, if the optimizer does a + ref access on "tbl1.key= expr" then + = equality substitution will be perfomed on 'expr' + = it is known in advance that 'expr' will be evaluated when + table t1 is accessed. + Note that in this kind of substution we never have to replace Item_equal + objects. For example, for + + t.key= func(col1=col2 AND col2=const) + + we will not build Item_equal or do equality substution (if we decide to, + this function will need to be fixed to handle it) + + 2. context_tab == NO_PARTICULAR_TAB + We're doing substitution in WHERE/ON condition, which is not yet + attached to any particular join_tab. We will use information about the + chosen join order to make "optimal" substitions, i.e. those that allow + to apply filtering as soon as possible. See eliminate_item_equal() and + Item_equal::get_first() for details. + @return The transformed condition */ -static COND* substitute_for_best_equal_field(COND *cond, +static COND* substitute_for_best_equal_field(JOIN_TAB *context_tab, + COND *cond, COND_EQUAL *cond_equal, void *table_join_idx) { @@ -11735,7 +11784,7 @@ static COND* substitute_for_best_equal_field(COND *cond, if (and_level) { cond_equal= &((Item_cond_and *) cond)->cond_equal; - cond_list->disjoin((List *) &cond_equal->current_level); + cond_list->disjoin((List *) &cond_equal->current_level);/* remove Item_equal objects from the AND. */ List_iterator_fast it(cond_equal->current_level); while ((item_equal= it++)) @@ -11748,7 +11797,8 @@ static COND* substitute_for_best_equal_field(COND *cond, Item *item; while ((item= li++)) { - Item *new_item= substitute_for_best_equal_field(item, cond_equal, + Item *new_item= substitute_for_best_equal_field(context_tab, + item, cond_equal, table_join_idx); /* This works OK with PS/SP re-execution as changes are made to @@ -11795,7 +11845,8 @@ static COND* substitute_for_best_equal_field(COND *cond, List_iterator_fast it(cond_equal->current_level); while((item_equal= it++)) { - cond= cond->transform(&Item::replace_equal_field, (uchar *) item_equal); + REPLACE_EQUAL_FIELD_ARG arg= {item_equal, context_tab}; + cond= cond->transform(&Item::replace_equal_field, (uchar *) &arg); } cond_equal= cond_equal->upper_levels; } @@ -15589,7 +15640,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) if (join_tab->loosescan_match_tab && join_tab->loosescan_match_tab->found_match) { - KEY *key= join_tab->table->key_info + join_tab->index; + KEY *key= join_tab->table->key_info + join_tab->loosescan_key; key_copy(join_tab->loosescan_buf, join_tab->table->record[0], key, join_tab->loosescan_key_len); skip_over= TRUE; @@ -15599,7 +15650,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) if (skip_over && !error) { - if(!key_cmp(join_tab->table->key_info[join_tab->index].key_part, + if(!key_cmp(join_tab->table->key_info[join_tab->loosescan_key].key_part, join_tab->loosescan_buf, join_tab->loosescan_key_len)) { /* @@ -18395,7 +18446,6 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, table->sort.io_cache= NULL; select->cleanup(); // filesort did select - tab->select= 0; table->quick_keys.clear_all(); // as far as we cleanup select->quick table->intersect_keys.clear_all(); table->sort.io_cache= tablesort_result_cache; diff --git a/sql/sql_select.h b/sql/sql_select.h index 46e7b7fe95f..2f7d31de404 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -374,6 +374,12 @@ typedef struct st_join_table { /* Buffer to save index tuple to be able to skip duplicates */ uchar *loosescan_buf; + /* + Index used by LooseScan (we store it here separately because ref access + stores it in tab->ref.key, while range scan stores it in tab->index, etc) + */ + uint loosescan_key; + /* Length of key tuple (depends on #keyparts used) to store in the above */ uint loosescan_key_len; @@ -986,6 +992,13 @@ public: /* We also maintain a stack of join optimization states in * join->positions[] */ /******* Join optimization state members end *******/ + + /* + Tables within complex firstmatch ranges (i.e. those where inner tables are + interleaved with outer tables). Join buffering cannot be used for these. + */ + table_map complex_firstmatch_tables; + /* The cost of best complete join plan found so far during optimization, after optimization phase - cost of picked join order (not taking into @@ -1440,6 +1453,7 @@ public: virtual ~store_key() {} /** Not actually needed */ virtual enum Type type() const=0; virtual const char *name() const=0; + virtual bool store_key_is_const() { return false; } /** @brief sets ignore truncation warnings mode and calls the real copy method @@ -1593,6 +1607,7 @@ public: enum Type type() const { return CONST_ITEM_STORE_KEY; } const char *name() const { return "const"; } + bool store_key_is_const() { return true; } protected: enum store_key_result copy_inner() diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 584ebd904a8..9b6d3a8dda5 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -964,6 +964,7 @@ bool st_select_lex::cleanup() } non_agg_fields.empty(); inner_refs_list.empty(); + exclude_from_table_unique_test= FALSE; DBUG_RETURN(error); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 99cac9f40e7..5fa30c91417 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -304,7 +304,7 @@ int mysql_update(THD *thd, thd_proc_info(thd, "init"); table= table_list->table; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); DBUG_RETURN(1); @@ -1246,7 +1246,7 @@ int mysql_multi_update_prepare(THD *thd) /* if table will be updated then check that it is unique */ if (table->map & tables_for_update) { - if (!tl->updatable || check_key_in_view(thd, tl)) + if (!tl->single_table_updatable() || check_key_in_view(thd, tl)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE"); DBUG_RETURN(TRUE); diff --git a/sql/table.cc b/sql/table.cc index 53e5872bfe4..8f4f034bf2a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4053,6 +4053,28 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds, DBUG_RETURN(FALSE); } +/** + Check that table/view is updatable and if it has single + underlying tables/views it is also updatable + + @return Result of the check. +*/ + +bool TABLE_LIST::single_table_updatable() +{ + if (!updatable) + return false; + if (view_tables && view_tables->elements == 1) + { + /* + We need to check deeply only single table views. Multi-table views + will be turned to multi-table updates and then checked by leaf tables + */ + return view_tables->head()->single_table_updatable(); + } + return true; +} + /* Merge ON expressions for a view @@ -4702,6 +4724,36 @@ bool TABLE_LIST::prepare_security(THD *thd) DBUG_RETURN(FALSE); } +#ifndef DBUG_OFF +void TABLE_LIST::set_check_merged() +{ + DBUG_ASSERT(derived); + /* + It is not simple to check all, but at least this should be checked: + this select is not excluded or the exclusion came from above. + */ + DBUG_ASSERT(!derived->first_select()->exclude_from_table_unique_test || + derived->outer_select()-> + exclude_from_table_unique_test); +} +#endif + +void TABLE_LIST::set_check_materialized() +{ + DBUG_ASSERT(derived); + if (!derived->first_select()->exclude_from_table_unique_test) + derived->set_unique_exclude(); + else + { + /* + The subtree should be already excluded + */ + DBUG_ASSERT(!derived->first_select()->first_inner_unit() || + derived->first_select()->first_inner_unit()->first_select()-> + exclude_from_table_unique_test); + } +} + Natural_join_column::Natural_join_column(Field_translator *field_param, TABLE_LIST *tab) @@ -4828,6 +4880,7 @@ Item *Field_iterator_table::create_item(THD *thd) { select->non_agg_fields.push_back(item); item->marker= select->cur_pos_in_select_list; + select->set_non_agg_field_used(true); } return item; } @@ -5532,6 +5585,12 @@ void TABLE::mark_virtual_columns_for_write(bool insert_fl) Field **vfield_ptr, *tmp_vfield; bool bitmap_updated= FALSE; + if (!vfield) + return; + + if (!vfield) + return; + for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) { tmp_vfield= *vfield_ptr; @@ -6293,8 +6352,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) */ if (is_materialized_derived()) { - unit->master_unit()->set_unique_exclude(); + set_check_materialized(); } + /* Create field translation for mergeable derived tables/views. For derived tables field translation can be created only after diff --git a/sql/table.h b/sql/table.h index a327d625387..77a7f8cf6a9 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1983,16 +1983,18 @@ struct TABLE_LIST inline void set_merged_derived() { derived_type= ((derived_type & DTYPE_MASK) | - DTYPE_TABLE | DTYPE_MERGE); + DTYPE_TABLE | DTYPE_MERGE); + set_check_merged(); } inline bool is_materialized_derived() { return (derived_type & DTYPE_MATERIALIZE); } - inline void set_materialized_derived() + void set_materialized_derived() { derived_type= ((derived_type & DTYPE_MASK) | - DTYPE_TABLE | DTYPE_MATERIALIZE); + DTYPE_TABLE | DTYPE_MATERIALIZE); + set_check_materialized(); } inline bool is_multitable() { @@ -2033,9 +2035,17 @@ struct TABLE_LIST int fetch_number_of_rows(); bool change_refs_to_fields(); + bool single_table_updatable(); + private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); + void set_check_materialized(); +#ifndef DBUG_OFF + void set_check_merged(); +#else + inline void set_check_merged() {} +#endif /** See comments for set_metadata_id() */ enum enum_table_ref_type m_table_ref_type; /** See comments for set_metadata_id() */ diff --git a/sql/winservice.c b/sql/winservice.c index 51a5a07a820..e4e0a3bd596 100644 --- a/sql/winservice.c +++ b/sql/winservice.c @@ -116,7 +116,7 @@ int get_mysql_service_properties(const wchar_t *bin_path, wcscat(mysqld_path, L".exe"); if(wcsicmp(file_part, L"mysqld.exe") != 0 && - wcsicmp(file_part, L"mysqld.exe") != 0 && + wcsicmp(file_part, L"mysqld-debug.exe") != 0 && wcsicmp(file_part, L"mysqld-nt.exe") != 0) { /* The service executable is not mysqld. */ @@ -244,4 +244,4 @@ int get_mysql_service_properties(const wchar_t *bin_path, end: LocalFree((HLOCAL)args); return retval; -} \ No newline at end of file +} diff --git a/storage/myisam/mi_preload.c b/storage/myisam/mi_preload.c index 5c974cbea0e..767858a6ea0 100644 --- a/storage/myisam/mi_preload.c +++ b/storage/myisam/mi_preload.c @@ -53,6 +53,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos) DBUG_RETURN(0); + /* Preload into a non initialized key cache should never happen. */ + DBUG_ASSERT(share->key_cache->key_cache_inited); + block_length= keyinfo[0].block_length; if (ignore_leaves) diff --git a/storage/oqgraph/graphcore.cc b/storage/oqgraph/graphcore.cc index 0b856ac253f..ba179989ea3 100644 --- a/storage/oqgraph/graphcore.cc +++ b/storage/oqgraph/graphcore.cc @@ -414,7 +414,7 @@ namespace open_query { if (record_weight && u != v) { typename graph_traits::out_edge_iterator ei, ei_end; - for (tie(ei, ei_end)= out_edges(v, g); ei != ei_end; ++ei) + for (boost::tuples::tie(ei, ei_end)= out_edges(v, g); ei != ei_end; ++ei) { if (target(*ei, g) == u) { @@ -479,14 +479,14 @@ namespace open_query if (in_degree(dest, g) >= out_degree(orig, g)) { graph_traits::out_edge_iterator ei, ei_end; - tie(ei, ei_end)= out_edges(orig, g); + boost::tuples::tie(ei, ei_end)= out_edges(orig, g); if ((ei= find_if(ei, ei_end, target_equals(dest, g))) != ei_end) return *ei; } else { graph_traits::in_edge_iterator ei, ei_end; - tie(ei, ei_end)= in_edges(dest, g); + boost::tuples::tie(ei, ei_end)= in_edges(dest, g); if ((ei= find_if(ei, ei_end, source_equals(orig, g))) != ei_end) return *ei; } @@ -727,7 +727,7 @@ namespace open_query if ((cursor= new (std::nothrow) stack_cursor(share)) && orig) { graph_traits::out_edge_iterator ei, ei_end; - for (tie(ei, ei_end)= out_edges(*orig, share->g); ei != ei_end; ++ei) + for (boost::tuples::tie(ei, ei_end)= out_edges(*orig, share->g); ei != ei_end; ++ei) { Vertex v= target(*ei, share->g); static_cast(cursor)-> @@ -741,7 +741,7 @@ namespace open_query dest) { graph_traits::in_edge_iterator ei, ei_end; - for (tie(ei, ei_end)= in_edges(*dest, share->g); ei != ei_end; ++ei) + for (boost::tuples::tie(ei, ei_end)= in_edges(*dest, share->g); ei != ei_end; ++ei) { Vertex v= source(*ei, share->g); static_cast(cursor)-> @@ -876,7 +876,7 @@ namespace open_query switch (ALGORITHM & op) { case DIJKSTRAS: - dijkstra_shortest_paths(r, *dest, + dijkstra_shortest_paths(r.m_g, *dest, weight_map( share->weightmap ). @@ -1067,7 +1067,7 @@ int edges_cursor::fetch_row(const row &row_info, row &result) edge_iterator it, end; reference ref; size_t count= position; - for (tie(it, end)= edges(share->g); count && it != end; ++it, --count) + for (boost::tuples::tie(it, end)= edges(share->g); count && it != end; ++it, --count) ; if (it != end) ref= reference(position+1, *it); diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c index ca98afc04ad..433b062bcec 100644 --- a/storage/xtradb/btr/btr0btr.c +++ b/storage/xtradb/btr/btr0btr.c @@ -1523,7 +1523,7 @@ btr_free_root( } ut_a(block); - btr_search_drop_page_hash_index(block, NULL); + btr_search_drop_page_hash_index(block); header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP; #ifdef UNIV_BTR_DEBUG @@ -1592,7 +1592,7 @@ btr_page_reorganize_low( #ifndef UNIV_HOTBACKUP if (UNIV_LIKELY(!recovery)) { - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); } block->check_index_page_at_flush = TRUE; @@ -1760,7 +1760,7 @@ btr_page_empty( ut_a(!page_zip || page_zip_validate(page_zip, page)); #endif /* UNIV_ZIP_DEBUG */ - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); btr_blob_dbg_remove(page, index, "btr_page_empty"); /* Recreate the page: note that global data on page (possible @@ -3093,7 +3093,7 @@ btr_lift_page_up( mem_heap_free(heap); } - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); /* Make the father empty */ btr_page_empty(father_block, father_page_zip, index, page_level, mtr); @@ -3317,7 +3317,7 @@ err_exit: goto err_exit; } - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); /* Remove the page from the level list */ btr_level_list_remove(space, zip_size, page, index, mtr); @@ -3358,7 +3358,7 @@ err_exit: goto err_exit; } - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); #ifdef UNIV_BTR_DEBUG if (UNIV_LIKELY_NULL(merge_page_zip)) { @@ -3473,7 +3473,7 @@ btr_discard_only_page_on_level( ut_a(btr_page_get_next(page, mtr) == FIL_NULL); ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); btr_page_get_father(index, block, mtr, &cursor); father = btr_cur_get_block(&cursor); @@ -3578,7 +3578,7 @@ btr_discard_page( page = buf_block_get_frame(block); ut_a(page_is_comp(merge_page) == page_is_comp(page)); - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); if (left_page_no == FIL_NULL && !page_is_leaf(page)) { diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index 717663a123a..43313474071 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -488,8 +488,6 @@ btr_cur_search_to_nth_level( cursor->flag = BTR_CUR_BINARY; cursor->index = index; - cursor->ibuf_cnt = ULINT_UNDEFINED; - #ifndef BTR_CUR_ADAPT guess = NULL; #else @@ -800,21 +798,8 @@ retry_page_get: /* We're doing a search on an ibuf tree and we're one level above the leaf page. */ - ulint is_min_rec; - ut_ad(level == 0); - is_min_rec = rec_get_info_bits(node_ptr, 0) - & REC_INFO_MIN_REC_FLAG; - - if (!is_min_rec) { - cursor->ibuf_cnt - = ibuf_rec_get_counter(node_ptr); - - ut_a(cursor->ibuf_cnt <= 0xFFFF - || cursor->ibuf_cnt == ULINT_UNDEFINED); - } - buf_mode = BUF_GET; rw_latch = RW_NO_LATCH; goto retry_page_get; @@ -2007,7 +1992,7 @@ btr_cur_update_in_place( was_delete_marked = rec_get_deleted_flag( rec, page_is_comp(buf_block_get_frame(block))); - is_hashed = block->is_hashed; + is_hashed = (block->index != NULL); if (is_hashed) { /* TO DO: Can we skip this if none of the fields @@ -3683,16 +3668,11 @@ btr_record_not_null_field_in_rec( } for (i = 0; i < n_unique; i++) { - ulint rec_len; - - rec_get_nth_field_offs(offsets, i, &rec_len); - - if (rec_len != UNIV_SQL_NULL) { - n_not_null[i]++; - } else { - /* Break if we hit the first NULL value */ + if (rec_offs_nth_sql_null(offsets, i)) { break; } + + n_not_null[i]++; } } @@ -3840,8 +3820,7 @@ btr_estimate_number_of_different_key_vals( if (n_not_null) { btr_record_not_null_field_in_rec( - n_cols, offsets_next_rec, - n_not_null); + n_cols, offsets_next_rec, n_not_null); } total_external_size diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c index 081ef9c9457..e6a9ddcf43e 100644 --- a/storage/xtradb/btr/btr0pcur.c +++ b/storage/xtradb/btr/btr0pcur.c @@ -253,6 +253,8 @@ btr_pcur_restore_position_func( cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr); + cursor->latch_mode = latch_mode; + cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->block_when_stored = btr_pcur_get_block(cursor); return(FALSE); diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c index f27afe216ec..bddbcc79dd6 100644 --- a/storage/xtradb/btr/btr0sea.c +++ b/storage/xtradb/btr/btr0sea.c @@ -44,15 +44,11 @@ Created 2/17/1996 Heikki Tuuri #include "ha0ha.h" #include "srv0srv.h" /** Flag: has the search system been enabled? -Protected by btr_search_latch and btr_search_enabled_mutex. */ +Protected by btr_search_latch. */ UNIV_INTERN char btr_search_enabled = TRUE; -UNIV_INTERN ibool btr_search_fully_disabled = FALSE; UNIV_INTERN ulint btr_search_index_num = 1; -/** Mutex protecting btr_search_enabled */ -static mutex_t btr_search_enabled_mutex; - #ifdef UNIV_PFS_MUTEX /* Key to register btr_search_enabled_mutex with performance schema */ UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key; @@ -186,8 +182,6 @@ btr_search_sys_create( //rw_lock_create(btr_search_latch_key, &btr_search_latch, // SYNC_SEARCH_SYS); - mutex_create(btr_search_enabled_mutex_key, - &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF); btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); @@ -238,27 +232,40 @@ void btr_search_disable(void) /*====================*/ { - mutex_enter(&btr_search_enabled_mutex); + dict_table_t* table; + ulint i; + + mutex_enter(&dict_sys->mutex); btr_search_x_lock_all(); - /* Disable access to hash index, also tell ha_insert_for_fold() - stop adding new nodes to hash index, but still allow updating - existing nodes */ btr_search_enabled = FALSE; - /* Clear all block->is_hashed flags and remove all entries - from btr_search_sys->hash_index. */ - buf_pool_drop_hash_index(); + /* Clear the index->search_info->ref_count of every index in + the data dictionary cache. */ + for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table; + table = UT_LIST_GET_NEXT(table_LRU, table)) { - /* hash index has been cleaned up, disallow any operation to - the hash index */ - btr_search_fully_disabled = TRUE; + dict_index_t* index; - /* btr_search_enabled_mutex should guarantee this. */ - ut_ad(!btr_search_enabled); + for (index = dict_table_get_first_index(table); index; + index = dict_table_get_next_index(index)) { + + index->search_info->ref_count = 0; + } + } + + mutex_exit(&dict_sys->mutex); + + /* Set all block->index = NULL. */ + buf_pool_clear_hash_index(); + + /* Clear the adaptive hash index. */ + for (i = 0; i < btr_search_index_num; i++) { + hash_table_clear(btr_search_sys->hash_index[i]); + mem_heap_empty(btr_search_sys->hash_index[i]->heap); + } btr_search_x_unlock_all(); - mutex_exit(&btr_search_enabled_mutex); } /********************************************************************//** @@ -268,14 +275,11 @@ void btr_search_enable(void) /*====================*/ { - mutex_enter(&btr_search_enabled_mutex); btr_search_x_lock_all(); btr_search_enabled = TRUE; - btr_search_fully_disabled = FALSE; btr_search_x_unlock_all(); - mutex_exit(&btr_search_enabled_mutex); } /*****************************************************************//** @@ -499,7 +503,7 @@ btr_search_update_block_hash_info( && (block->n_bytes == info->n_bytes) && (block->left_side == info->left_side)) { - if ((block->is_hashed) + if ((block->index) && (block->curr_n_fields == info->n_fields) && (block->curr_n_bytes == info->n_bytes) && (block->curr_left_side == info->left_side)) { @@ -528,7 +532,7 @@ btr_search_update_block_hash_info( / BTR_SEARCH_PAGE_BUILD_LIMIT) && (info->n_hash_potential >= BTR_SEARCH_BUILD_LIMIT)) { - if ((!block->is_hashed) + if ((!block->index) || (block->n_hash_helps > 2 * page_get_n_recs(block->frame)) || (block->n_fields != block->curr_n_fields) @@ -560,9 +564,9 @@ btr_search_update_hash_ref( buf_block_t* block, /*!< in: buffer block where cursor positioned */ btr_cur_t* cursor) /*!< in: cursor */ { + dict_index_t* index; ulint fold; - rec_t* rec; - index_id_t index_id; + const rec_t* rec; ut_ad(cursor->flag == BTR_CUR_HASH_FAIL); #ifdef UNIV_SYNC_DEBUG @@ -573,13 +577,15 @@ btr_search_update_hash_ref( ut_ad(page_align(btr_cur_get_rec(cursor)) == buf_block_get_frame(block)); - if (!block->is_hashed) { + index = block->index; + + if (!index) { return; } - ut_a(block->index == cursor->index); - ut_a(!dict_index_is_ibuf(cursor->index)); + ut_a(index == cursor->index); + ut_a(!dict_index_is_ibuf(index)); if ((info->n_hash_potential > 0) && (block->curr_n_fields == info->n_fields) @@ -596,12 +602,11 @@ btr_search_update_hash_ref( return; } - index_id = cursor->index->id; fold = rec_fold(rec, - rec_get_offsets(rec, cursor->index, offsets_, + rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), block->curr_n_fields, - block->curr_n_bytes, index_id); + block->curr_n_bytes, index->id); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -870,7 +875,7 @@ btr_search_guess_on_hash( { buf_pool_t* buf_pool; buf_block_t* block; - rec_t* rec; + const rec_t* rec; ulint fold; index_id_t index_id; #ifdef notdefined @@ -956,7 +961,7 @@ btr_search_guess_on_hash( ut_ad(page_rec_is_user_rec(rec)); - btr_cur_position(index, rec, block, cursor); + btr_cur_position(index, (rec_t*) rec, block, cursor); /* Check the validity of the guess within the page */ @@ -1058,11 +1063,10 @@ UNIV_INTERN void btr_search_drop_page_hash_index( /*============================*/ - buf_block_t* block, /*!< in: block containing index page, + buf_block_t* block) /*!< in: block containing index page, s- or x-latched, or an index page for which we know that block->buf_fix_count == 0 */ - dict_index_t* index_in) { hash_table_t* table; ulint n_fields; @@ -1080,24 +1084,14 @@ btr_search_drop_page_hash_index( const dict_index_t* index; ulint* offsets; -#ifdef UNIV_SYNC_DEBUG - if (index_in) { - ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX)); - } -#endif /* UNIV_SYNC_DEBUG */ - retry: - if (index_in) { - index = index_in; - rw_lock_s_lock(btr_search_get_latch(index->id)); - } else if (btr_search_index_num > 1) { + if (btr_search_index_num > 1) { rw_lock_t* btr_search_latch; /* FIXME: This may be optimistic implementation still. */ btr_search_latch = (rw_lock_t*)(block->btr_search_latch); if (UNIV_LIKELY(!btr_search_latch)) { - if (block->is_hashed) { + if (block->index) { goto retry; } return; @@ -1107,7 +1101,7 @@ retry: rw_lock_s_unlock(btr_search_latch); goto retry; } - if (UNIV_LIKELY(!block->is_hashed)) { + if (UNIV_LIKELY(!block->index)) { rw_lock_s_unlock(btr_search_latch); goto retry; } @@ -1116,18 +1110,16 @@ retry: } else { /* btr_search_index_num == 1 */ /* btr_search_latch is only one and able to obtain - before evaluating block->is_hashed. */ + before evaluating block->index. */ rw_lock_s_lock(btr_search_latch_part[0]); - if (UNIV_LIKELY(!block->is_hashed)) { + if (UNIV_LIKELY(!block->index)) { rw_lock_s_unlock(btr_search_latch_part[0]); return; } index = block->index; } - page = block->frame; - - if (UNIV_LIKELY(!block->is_hashed)) { + if (UNIV_LIKELY(!index)) { rw_lock_s_unlock(btr_search_get_latch(index->id)); @@ -1155,6 +1147,7 @@ retry: ut_a(n_fields + n_bytes > 0); + page = block->frame; n_recs = page_get_n_recs(page); /* Calculate and cache fold values into an array for fast deletion @@ -1203,7 +1196,7 @@ next_rec: rw_lock_x_lock(btr_search_get_latch(index->id)); - if (UNIV_UNLIKELY(!block->is_hashed)) { + if (UNIV_UNLIKELY(!block->index)) { /* Someone else has meanwhile dropped the hash index */ goto cleanup; @@ -1231,10 +1224,9 @@ next_rec: ut_a(index->search_info->ref_count > 0); index->search_info->ref_count--; - block->is_hashed = FALSE; block->index = NULL; block->btr_search_latch = NULL; - + cleanup: #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG if (UNIV_UNLIKELY(block->n_pointers)) { @@ -1309,7 +1301,7 @@ retry: if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE || block->index != index - || !block->is_hashed) { + || !block->index) { continue; } @@ -1375,7 +1367,7 @@ next_rec: rw_lock_x_lock(btr_search_get_latch(index->id)); - if (UNIV_UNLIKELY(!block->is_hashed)) { + if (UNIV_UNLIKELY(!block->index)) { goto cleanup; } @@ -1400,7 +1392,6 @@ next_rec: ut_a(index->search_info->ref_count > 0); index->search_info->ref_count--; - block->is_hashed = FALSE; block->index = NULL; block->btr_search_latch = NULL; @@ -1434,8 +1425,8 @@ cleanup: } /********************************************************************//** -Drops a page hash index when a page is freed from a fseg to the file system. -Drops possible hash index if the page happens to be in the buffer pool. */ +Drops a possible page hash index when a page is evicted from the buffer pool +or freed in a file segment. */ UNIV_INTERN void btr_search_drop_page_hash_when_freed( @@ -1448,32 +1439,23 @@ btr_search_drop_page_hash_when_freed( buf_block_t* block; mtr_t mtr; - if (!buf_page_peek_if_search_hashed(space, page_no)) { - - return; - } - mtr_start(&mtr); - /* We assume that if the caller has a latch on the page, then the - caller has already dropped the hash index for the page, and we never - get here. Therefore we can acquire the s-latch to the page without - having to fear a deadlock. */ + /* If the caller has a latch on the page, then the caller must + have a x-latch on the page and it must have already dropped + the hash index for the page. Because of the x-latch that we + are possibly holding, we cannot s-latch the page, but must + (recursively) x-latch it, even though we are only reading. */ - block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL, + block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL, BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__, &mtr); - /* Because the buffer pool mutex was released by - buf_page_peek_if_search_hashed(), it is possible that the - block was removed from the buffer pool by another thread - before buf_page_get_gen() got a chance to acquire the buffer - pool mutex again. Thus, we must check for a NULL return. */ - if (UNIV_LIKELY(block != NULL)) { + if (block && block->index) { buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); - btr_search_drop_page_hash_index(block, NULL); + btr_search_drop_page_hash_index(block); } mtr_commit(&mtr); @@ -1501,7 +1483,6 @@ btr_search_build_page_hash_index( rec_t* next_rec; ulint fold; ulint next_fold; - index_id_t index_id; ulint n_cached; ulint n_recs; ulint* folds; @@ -1526,13 +1507,13 @@ btr_search_build_page_hash_index( rw_lock_s_lock(btr_search_get_latch(index->id)); - if (block->is_hashed && ((block->curr_n_fields != n_fields) + if (block->index && ((block->curr_n_fields != n_fields) || (block->curr_n_bytes != n_bytes) || (block->curr_left_side != left_side))) { rw_lock_s_unlock(btr_search_get_latch(index->id)); - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); } else { rw_lock_s_unlock(btr_search_get_latch(index->id)); } @@ -1565,7 +1546,7 @@ btr_search_build_page_hash_index( n_cached = 0; - index_id = btr_page_get_index_id(page); + ut_a(index->id == btr_page_get_index_id(page)); rec = page_rec_get_next(page_get_infimum_rec(page)); @@ -1580,7 +1561,7 @@ btr_search_build_page_hash_index( } } - fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id); + fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id); if (left_side) { @@ -1607,7 +1588,7 @@ btr_search_build_page_hash_index( offsets = rec_get_offsets(next_rec, index, offsets, n_fields + (n_bytes > 0), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, - n_bytes, index_id); + n_bytes, index->id); if (fold != next_fold) { /* Insert an entry into the hash index */ @@ -1632,13 +1613,13 @@ btr_search_build_page_hash_index( rw_lock_x_lock(btr_search_get_latch(index->id)); - if (UNIV_UNLIKELY(btr_search_fully_disabled)) { + if (UNIV_UNLIKELY(!btr_search_enabled)) { goto exit_func; } - if (block->is_hashed && ((block->curr_n_fields != n_fields) - || (block->curr_n_bytes != n_bytes) - || (block->curr_left_side != left_side))) { + if (block->index && ((block->curr_n_fields != n_fields) + || (block->curr_n_bytes != n_bytes) + || (block->curr_left_side != left_side))) { goto exit_func; } @@ -1647,11 +1628,10 @@ btr_search_build_page_hash_index( rebuild hash index for a page that is already hashed, we have to take care not to increment the counter in that case. */ - if (!block->is_hashed) { + if (!block->index) { index->search_info->ref_count++; } - block->is_hashed = TRUE; block->n_hash_helps = 0; block->curr_n_fields = n_fields; @@ -1700,23 +1680,24 @@ btr_search_move_or_delete_hash_entries( ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - ut_a(!new_block->is_hashed || new_block->index == index); - ut_a(!block->is_hashed || block->index == index); - ut_a(!(new_block->is_hashed || block->is_hashed) - || !dict_index_is_ibuf(index)); rw_lock_s_lock(btr_search_get_latch(index->id)); - if (new_block->is_hashed) { + ut_a(!new_block->index || new_block->index == index); + ut_a(!block->index || block->index == index); + ut_a(!(new_block->index || block->index) + || !dict_index_is_ibuf(index)); + + if (new_block->index) { rw_lock_s_unlock(btr_search_get_latch(index->id)); - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); return; } - if (block->is_hashed) { + if (block->index) { n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; @@ -1753,42 +1734,48 @@ btr_search_update_hash_on_delete( { hash_table_t* table; buf_block_t* block; - rec_t* rec; + const rec_t* rec; ulint fold; - index_id_t index_id; + dict_index_t* index; ulint offsets_[REC_OFFS_NORMAL_SIZE]; mem_heap_t* heap = NULL; rec_offs_init(offsets_); - rec = btr_cur_get_rec(cursor); - block = btr_cur_get_block(cursor); #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - if (!block->is_hashed) { + index = block->index; + + if (!index) { return; } - ut_a(block->index == cursor->index); + ut_a(index == cursor->index); ut_a(block->curr_n_fields + block->curr_n_bytes > 0); - ut_a(!dict_index_is_ibuf(cursor->index)); + ut_a(!dict_index_is_ibuf(index)); table = btr_search_get_hash_index(cursor->index->id); - index_id = cursor->index->id; - fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, + rec = btr_cur_get_rec(cursor); + + fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), - block->curr_n_fields, block->curr_n_bytes, index_id); + block->curr_n_fields, block->curr_n_bytes, index->id); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } + rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); - ha_search_and_delete_if_found(table, fold, rec); + if (block->index) { + ut_a(block->index == index); + + ha_search_and_delete_if_found(table, fold, rec); + } rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } @@ -1806,6 +1793,7 @@ btr_search_update_hash_node_on_insert( { hash_table_t* table; buf_block_t* block; + dict_index_t* index; rec_t* rec; rec = btr_cur_get_rec(cursor); @@ -1816,16 +1804,25 @@ btr_search_update_hash_node_on_insert( ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - if (!block->is_hashed) { + index = block->index; + + if (!index) { return; } - ut_a(block->index == cursor->index); - ut_a(!dict_index_is_ibuf(cursor->index)); + ut_a(cursor->index == index); + ut_a(!dict_index_is_ibuf(index)); rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); + if (!block->index) { + + goto func_exit; + } + + ut_a(block->index == index); + if ((cursor->flag == BTR_CUR_HASH) && (cursor->n_fields == block->curr_n_fields) && (cursor->n_bytes == block->curr_n_bytes) @@ -1836,6 +1833,7 @@ btr_search_update_hash_node_on_insert( ha_search_and_update_if_found(table, cursor->fold, rec, block, page_rec_get_next(rec)); +func_exit: rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } else { rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); @@ -1857,10 +1855,10 @@ btr_search_update_hash_on_insert( { hash_table_t* table; buf_block_t* block; + dict_index_t* index; rec_t* rec; rec_t* ins_rec; rec_t* next_rec; - index_id_t index_id; ulint fold; ulint ins_fold; ulint next_fold = 0; /* remove warning (??? bug ???) */ @@ -1885,15 +1883,15 @@ btr_search_update_hash_on_insert( ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - if (!block->is_hashed) { + index = block->index; + + if (!index) { return; } - ut_a(block->index == cursor->index); - ut_a(!dict_index_is_ibuf(cursor->index)); - - index_id = cursor->index->id; + ut_a(index == cursor->index); + ut_a(!dict_index_is_ibuf(index)); n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; @@ -1902,28 +1900,32 @@ btr_search_update_hash_on_insert( ins_rec = page_rec_get_next(rec); next_rec = page_rec_get_next(ins_rec); - offsets = rec_get_offsets(ins_rec, cursor->index, offsets, + offsets = rec_get_offsets(ins_rec, index, offsets, ULINT_UNDEFINED, &heap); - ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id); + ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id); if (!page_rec_is_supremum(next_rec)) { - offsets = rec_get_offsets(next_rec, cursor->index, offsets, + offsets = rec_get_offsets(next_rec, index, offsets, n_fields + (n_bytes > 0), &heap); next_fold = rec_fold(next_rec, offsets, n_fields, - n_bytes, index_id); + n_bytes, index->id); } if (!page_rec_is_infimum(rec)) { - offsets = rec_get_offsets(rec, cursor->index, offsets, + offsets = rec_get_offsets(rec, index, offsets, n_fields + (n_bytes > 0), &heap); - fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id); + fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id); } else { if (left_side) { - rw_lock_x_lock(btr_search_get_latch(index_id)); + rw_lock_x_lock(btr_search_get_latch(index->id)); locked = TRUE; + if (!btr_search_enabled) { + goto function_exit; + } + ha_insert_for_fold(table, ins_fold, block, ins_rec); } @@ -1934,9 +1936,13 @@ btr_search_update_hash_on_insert( if (!locked) { - rw_lock_x_lock(btr_search_get_latch(index_id)); + rw_lock_x_lock(btr_search_get_latch(index->id)); locked = TRUE; + + if (!btr_search_enabled) { + goto function_exit; + } } if (!left_side) { @@ -1952,9 +1958,13 @@ check_next_rec: if (!left_side) { if (!locked) { - rw_lock_x_lock(btr_search_get_latch(index_id)); + rw_lock_x_lock(btr_search_get_latch(index->id)); locked = TRUE; + + if (!btr_search_enabled) { + goto function_exit; + } } ha_insert_for_fold(table, ins_fold, block, ins_rec); @@ -1967,9 +1977,13 @@ check_next_rec: if (!locked) { - rw_lock_x_lock(btr_search_get_latch(index_id)); + rw_lock_x_lock(btr_search_get_latch(index->id)); locked = TRUE; + + if (!btr_search_enabled) { + goto function_exit; + } } if (!left_side) { @@ -1977,7 +1991,7 @@ check_next_rec: ha_insert_for_fold(table, ins_fold, block, ins_rec); /* fputs("Hash insert for ", stderr); - dict_index_name_print(stderr, cursor->index); + dict_index_name_print(stderr, index); fprintf(stderr, " fold %lu\n", ins_fold); */ } else { @@ -1990,7 +2004,7 @@ function_exit: mem_heap_free(heap); } if (locked) { - rw_lock_x_unlock(btr_search_get_latch(index_id)); + rw_lock_x_unlock(btr_search_get_latch(index->id)); } } @@ -2082,21 +2096,20 @@ btr_search_validate(void) ut_a(!dict_index_is_ibuf(block->index)); - offsets = rec_get_offsets((const rec_t*) node->data, + page_index_id = btr_page_get_index_id(block->frame); + + offsets = rec_get_offsets(node->data, block->index, offsets, block->curr_n_fields + (block->curr_n_bytes > 0), &heap); - page_index_id = btr_page_get_index_id(block->frame); - - if (UNIV_UNLIKELY - (!block->is_hashed || node->fold - != rec_fold((rec_t*)(node->data), - offsets, - block->curr_n_fields, - block->curr_n_bytes, - page_index_id))) { + if (!block->index || node->fold + != rec_fold(node->data, + offsets, + block->curr_n_fields, + block->curr_n_bytes, + page_index_id)) { const page_t* page = block->frame; ok = FALSE; @@ -2112,20 +2125,19 @@ btr_search_validate(void) node->data, (ullint) page_index_id, (ulong) node->fold, - (ulong) rec_fold((rec_t*)(node->data), + (ulong) rec_fold(node->data, offsets, block->curr_n_fields, block->curr_n_bytes, page_index_id)); fputs("InnoDB: Record ", stderr); - rec_print_new(stderr, (rec_t*)node->data, - offsets); + rec_print_new(stderr, node->data, offsets); fprintf(stderr, "\nInnoDB: on that page." - " Page mem address %p, is hashed %lu," + " Page mem address %p, is hashed %p," " n fields %lu, n bytes %lu\n" "InnoDB: side %lu\n", - (void*) page, (ulong) block->is_hashed, + (void*) page, (void*) block->index, (ulong) block->curr_n_fields, (ulong) block->curr_n_bytes, (ulong) block->curr_left_side); diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index 4bc2c26cde2..11b079dd0ef 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -917,6 +917,16 @@ pfs_register_buffer_block( rwlock->pfs_psi = (PSI_server) ? PSI_server->init_rwlock(buf_block_lock_key, rwlock) : NULL; + +# ifdef UNIV_SYNC_DEBUG + rwlock = &block->debug_latch; + ut_a(!rwlock->pfs_psi); + rwlock->pfs_psi = (PSI_server) + ? PSI_server->init_rwlock(buf_block_debug_latch_key, + rwlock) + : NULL; +# endif /* UNIV_SYNC_DEBUG */ + # endif /* UNIV_PFS_RWLOCK */ block++; } @@ -952,8 +962,6 @@ buf_block_init( block->index = NULL; block->btr_search_latch = NULL; - block->is_hashed = FALSE; - #ifdef UNIV_DEBUG block->page.in_page_hash = FALSE; block->page.in_zip_hash = FALSE; @@ -980,17 +988,24 @@ buf_block_init( mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK); rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING); + +# ifdef UNIV_SYNC_DEBUG + rw_lock_create(PFS_NOT_INSTRUMENTED, + &block->debug_latch, SYNC_NO_ORDER_CHECK); +# endif /* UNIV_SYNC_DEBUG */ + #else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */ mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK); rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING); + +# ifdef UNIV_SYNC_DEBUG + rw_lock_create(buf_block_debug_latch_key, + &block->debug_latch, SYNC_NO_ORDER_CHECK); +# endif /* UNIV_SYNC_DEBUG */ #endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */ ut_ad(rw_lock_validate(&(block->lock))); -#ifdef UNIV_SYNC_DEBUG - rw_lock_create(buf_block_debug_latch_key, - &block->debug_latch, SYNC_NO_ORDER_CHECK); -#endif /* UNIV_SYNC_DEBUG */ } /********************************************************************//** @@ -1317,6 +1332,26 @@ buf_pool_free_instance( { buf_chunk_t* chunk; buf_chunk_t* chunks; + buf_page_t* bpage; + + bpage = UT_LIST_GET_LAST(buf_pool->LRU); + while (bpage != NULL) { + buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage); + enum buf_page_state state = buf_page_get_state(bpage); + + ut_ad(buf_page_in_file(bpage)); + ut_ad(bpage->in_LRU_list); + + if (state != BUF_BLOCK_FILE_PAGE) { + /* We must not have any dirty block except + when doing a fast shutdown. */ + ut_ad(state == BUF_BLOCK_ZIP_PAGE + || srv_fast_shutdown == 2); + buf_page_free_descriptor(bpage); + } + + bpage = prev_bpage; + } chunks = buf_pool->chunks; chunk = chunks + buf_pool->n_chunks; @@ -1392,87 +1427,13 @@ buf_pool_free( } /********************************************************************//** -Drops adaptive hash index for a buffer pool instance. */ -static -void -buf_pool_drop_hash_index_instance( -/*==============================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ibool* released_search_latch) /*!< out: flag for signalling - whether the search latch was - released */ -{ - buf_chunk_t* chunks = buf_pool->chunks; - buf_chunk_t* chunk = chunks + buf_pool->n_chunks; - - while (--chunk >= chunks) { - ulint i; - buf_block_t* block = chunk->blocks; - - for (i = chunk->size; i--; block++) { - /* block->is_hashed cannot be modified - when we have an x-latch on btr_search_latch; - see the comment in buf0buf.h */ - - if (!block->is_hashed) { - continue; - } - - /* To follow the latching order, we - have to release btr_search_latch - before acquiring block->latch. */ - btr_search_x_unlock_all(); - /* When we release the search latch, - we must rescan all blocks, because - some may become hashed again. */ - *released_search_latch = TRUE; - - rw_lock_x_lock(&block->lock); - - /* This should be guaranteed by the - callers, which will be holding - btr_search_enabled_mutex. */ - ut_ad(!btr_search_enabled); - - /* Because we did not buffer-fix the - block by calling buf_block_get_gen(), - it is possible that the block has been - allocated for some other use after - btr_search_latch was released above. - We do not care which file page the - block is mapped to. All we want to do - is to drop any hash entries referring - to the page. */ - - /* It is possible that - block->page.state != BUF_FILE_PAGE. - Even that does not matter, because - btr_search_drop_page_hash_index() will - check block->is_hashed before doing - anything. block->is_hashed can only - be set on uncompressed file pages. */ - - btr_search_drop_page_hash_index(block, NULL); - - rw_lock_x_unlock(&block->lock); - - btr_search_x_lock_all(); - - ut_ad(!btr_search_enabled); - } - } -} - -/********************************************************************//** -Drops the adaptive hash index. To prevent a livelock, this function -is only to be called while holding btr_search_latch and while -btr_search_enabled == FALSE. */ +Clears the adaptive hash index on all pages in the buffer pool. */ UNIV_INTERN void -buf_pool_drop_hash_index(void) -/*==========================*/ +buf_pool_clear_hash_index(void) +/*===========================*/ { - ibool released_search_latch; + ulint p; #ifdef UNIV_SYNC_DEBUG ulint j; @@ -1483,21 +1444,34 @@ buf_pool_drop_hash_index(void) #endif /* UNIV_SYNC_DEBUG */ ut_ad(!btr_search_enabled); - do { - ulint i; + for (p = 0; p < srv_buf_pool_instances; p++) { + buf_pool_t* buf_pool = buf_pool_from_array(p); + buf_chunk_t* chunks = buf_pool->chunks; + buf_chunk_t* chunk = chunks + buf_pool->n_chunks; - released_search_latch = FALSE; + while (--chunk >= chunks) { + buf_block_t* block = chunk->blocks; + ulint i = chunk->size; - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; + for (; i--; block++) { + dict_index_t* index = block->index; - buf_pool = buf_pool_from_array(i); + /* We can set block->index = NULL + when we have an x-latch on btr_search_latch; + see the comment in buf0buf.h */ - buf_pool_drop_hash_index_instance( - buf_pool, &released_search_latch); + if (!index) { + /* Not hashed */ + continue; + } + + block->index = NULL; +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + block->n_pointers = 0; +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + } } - - } while (released_search_latch); + } } /********************************************************************//** @@ -1638,12 +1612,12 @@ buf_pool_watch_set( rw_lock_x_lock(&buf_pool->page_hash_latch); bpage = buf_page_hash_get_low(buf_pool, space, offset, fold); - if (bpage) { - block_mutex = buf_page_get_mutex_enter(bpage); - ut_a(block_mutex); - } if (UNIV_LIKELY_NULL(bpage)) { + + block_mutex = buf_page_get_mutex_enter(bpage); + ut_a(block_mutex); + if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) { /* The page was loaded meanwhile. */ rw_lock_x_unlock(&buf_pool->page_hash_latch); @@ -1895,40 +1869,6 @@ buf_reset_check_index_page_at_flush( rw_lock_s_unlock(&buf_pool->page_hash_latch); } -/********************************************************************//** -Returns the current state of is_hashed of a page. FALSE if the page is -not in the pool. NOTE that this operation does not fix the page in the -pool if it is found there. -@return TRUE if page hash index is built in search system */ -UNIV_INTERN -ibool -buf_page_peek_if_search_hashed( -/*===========================*/ - ulint space, /*!< in: space id */ - ulint offset) /*!< in: page number */ -{ - buf_block_t* block; - ibool is_hashed; - buf_pool_t* buf_pool = buf_pool_get(space, offset); - - //buf_pool_mutex_enter(buf_pool); - rw_lock_s_lock(&buf_pool->page_hash_latch); - - block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset); - - if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { - is_hashed = FALSE; - } else { - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page)); - is_hashed = block->is_hashed; - } - - //buf_pool_mutex_exit(buf_pool); - rw_lock_s_unlock(&buf_pool->page_hash_latch); - - return(is_hashed); -} - #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG /********************************************************************//** Sets file_page_was_freed TRUE if the page is found in the buffer pool. @@ -2218,7 +2158,6 @@ buf_block_init_low( block->btr_search_latch = NULL; block->n_hash_helps = 0; - block->is_hashed = FALSE; block->n_fields = 1; block->n_bytes = 0; block->left_side = TRUE; @@ -4473,6 +4412,9 @@ buf_pool_validate_instance( ut_a(rw_lock_is_locked(&block->lock, RW_LOCK_EX)); break; + + case BUF_IO_PIN: + break; } n_lru++; @@ -4502,6 +4444,7 @@ buf_pool_validate_instance( ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE); switch (buf_page_get_io_fix(b)) { case BUF_IO_NONE: + case BUF_IO_PIN: /* All clean blocks should be I/O-unfixed. */ break; case BUF_IO_READ: @@ -4541,6 +4484,7 @@ buf_pool_validate_instance( switch (buf_page_get_io_fix(b)) { case BUF_IO_NONE: case BUF_IO_READ: + case BUF_IO_PIN: break; case BUF_IO_WRITE: switch (buf_page_get_flush_type(b)) { diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c index 73a9ff96289..d776a274d14 100644 --- a/storage/xtradb/buf/buf0flu.c +++ b/storage/xtradb/buf/buf0flu.c @@ -1399,6 +1399,7 @@ buf_flush_try_neighbors( ulint high; ulint count = 0; buf_pool_t* buf_pool = buf_pool_get(space, offset); + ibool is_forward_scan; ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST); @@ -1429,7 +1430,32 @@ buf_flush_try_neighbors( high = fil_space_get_size(space); } - for (i = low; i < high; i++) { + if (srv_flush_neighbor_pages == 2) { + + /* In the case of contiguous flush where the requested page + does not fall at the start of flush area, first scan backward + from the page and later forward from it. */ + is_forward_scan = (offset == low); + } + else { + is_forward_scan = TRUE; + } + +scan: + if (srv_flush_neighbor_pages == 2) { + if (is_forward_scan) { + i = offset; + } + else { + i = offset - 1; + } + } + else { + i = low; + } + + for (; is_forward_scan ? (i < high) : (i >= low); + is_forward_scan ? i++ : i--) { buf_page_t* bpage; @@ -1460,6 +1486,12 @@ buf_flush_try_neighbors( //buf_pool_mutex_exit(buf_pool); rw_lock_s_unlock(&buf_pool->page_hash_latch); + if (srv_flush_neighbor_pages == 2) { + + /* This is contiguous neighbor page flush and + the pages here are not contiguous. */ + break; + } continue; } @@ -1495,6 +1527,22 @@ buf_flush_try_neighbors( } //buf_pool_mutex_exit(buf_pool); rw_lock_s_unlock(&buf_pool->page_hash_latch); + + if (srv_flush_neighbor_pages == 2) { + + /* We are trying to do the contiguous neighbor page + flush, but the last page we checked was unflushable, + making a "hole" in the flush, so stop this attempt. */ + break; + } + } + + if (!is_forward_scan) { + + /* Backward scan done, now do the forward scan */ + ut_a (srv_flush_neighbor_pages == 2); + is_forward_scan = TRUE; + goto scan; } return(count); @@ -1988,6 +2036,22 @@ buf_flush_list( buf_pool = buf_pool_from_array(i); + if (lsn_limit != IB_ULONGLONG_MAX) { + buf_page_t* bpage; + + buf_flush_list_mutex_enter(buf_pool); + bpage = UT_LIST_GET_LAST(buf_pool->flush_list); + if (!bpage + || bpage->oldest_modification >= lsn_limit) { + + buf_flush_list_mutex_exit(buf_pool); + continue; + } else { + + buf_flush_list_mutex_exit(buf_pool); + } + } + if (!buf_flush_start(buf_pool, BUF_FLUSH_LIST)) { /* We have two choices here. If lsn_limit was specified then skipping an instance of buffer diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c index a5a811f7afe..ecad1cf1e64 100644 --- a/storage/xtradb/buf/buf0lru.c +++ b/storage/xtradb/buf/buf0lru.c @@ -68,8 +68,12 @@ allowed to point to either end of the LRU list. */ /** When dropping the search hash index entries before deleting an ibd file, we build a local array of pages belonging to that tablespace -in the buffer pool. Following is the size of that array. */ -#define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024 +in the buffer pool. Following is the size of that array. +We also release buf_pool->mutex after scanning this many pages of the +flush_list when dropping a table. This is to ensure that other threads +are not blocked for extended period of time when using very large +buffer pools. */ +#define BUF_LRU_DROP_SEARCH_SIZE 1024 /** If we switch on the InnoDB monitor because there are too few available frames in the buffer pool, we set this to TRUE */ @@ -222,7 +226,7 @@ buf_LRU_drop_page_hash_batch( ulint i; ut_ad(arr != NULL); - ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE); + ut_ad(count <= BUF_LRU_DROP_SEARCH_SIZE); for (i = 0; i < count; ++i) { btr_search_drop_page_hash_when_freed(space_id, zip_size, @@ -256,7 +260,7 @@ buf_LRU_drop_page_hash_for_tablespace( } page_arr = ut_malloc( - sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE); + sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE); //buf_pool_mutex_enter(buf_pool); mutex_enter(&buf_pool->LRU_list_mutex); @@ -293,7 +297,7 @@ next_page: //mutex_enter(&((buf_block_t*) bpage)->mutex); is_fixed = bpage->buf_fix_count > 0 - || !((buf_block_t*) bpage)->is_hashed; + || !((buf_block_t*) bpage)->index; //mutex_exit(&((buf_block_t*) bpage)->mutex); if (is_fixed) { @@ -304,12 +308,14 @@ next_page: /* Store the page number so that we can drop the hash index in a batch later. */ page_arr[num_entries] = bpage->offset; + mutex_exit(block_mutex); - ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE); + ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE); + ++num_entries; - if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) { + if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) { goto next_page; } @@ -366,39 +372,42 @@ next_page: } /******************************************************************//** -Invalidates all pages belonging to a given tablespace inside a specific +Remove all dirty pages belonging to a given tablespace inside a specific buffer pool instance when we are deleting the data file(s) of that -tablespace. */ +tablespace. The pages still remain a part of LRU and are evicted from +the list as they age towards the tail of the LRU. */ static void -buf_LRU_invalidate_tablespace_buf_pool_instance( -/*============================================*/ +buf_LRU_remove_dirty_pages_for_tablespace( +/*======================================*/ buf_pool_t* buf_pool, /*!< buffer pool instance */ ulint id) /*!< in: space id */ { buf_page_t* bpage; ibool all_freed; + ulint i; scan_again: //buf_pool_mutex_enter(buf_pool); mutex_enter(&buf_pool->LRU_list_mutex); rw_lock_x_lock(&buf_pool->page_hash_latch); + buf_flush_list_mutex_enter(buf_pool); all_freed = TRUE; - bpage = UT_LIST_GET_LAST(buf_pool->LRU); + for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list), i = 0; + bpage != NULL; ++i) { - while (bpage != NULL) { buf_page_t* prev_bpage; mutex_t* block_mutex = NULL; ut_a(buf_page_in_file(bpage)); - prev_bpage = UT_LIST_GET_PREV(LRU, bpage); + prev_bpage = UT_LIST_GET_PREV(flush_list, bpage); /* bpage->space and bpage->io_fix are protected by - buf_pool_mutex and block_mutex. It is safe to check - them while holding buf_pool_mutex only. */ + buf_pool->mutex and block_mutex. It is safe to check + them while holding buf_pool->mutex only. */ if (buf_page_get_space(bpage) != id) { /* Skip this block, as it does not belong to @@ -411,90 +420,97 @@ scan_again: all_freed = FALSE; goto next_page; - } else { - block_mutex = buf_page_get_mutex_enter(bpage); - - if (!block_mutex) { - /* It may be impossible case... - Something wrong, so will be scan_again */ - - all_freed = FALSE; - goto next_page; - } - - if (bpage->buf_fix_count > 0) { - - mutex_exit(block_mutex); - /* We cannot remove this page during - this scan yet; maybe the system is - currently reading it in, or flushing - the modifications to the file */ - - all_freed = FALSE; - - goto next_page; - } } - ut_ad(mutex_own(block_mutex)); + /* We have to release the flush_list_mutex to obey the + latching order. We are however guaranteed that the page + will stay in the flush_list because buf_flush_remove() + needs buf_pool->mutex as well. */ + buf_flush_list_mutex_exit(buf_pool); + block_mutex = buf_page_get_mutex_enter(bpage); -#ifdef UNIV_DEBUG - if (buf_debug_prints) { - fprintf(stderr, - "Dropping space %lu page %lu\n", - (ulong) buf_page_get_space(bpage), - (ulong) buf_page_get_page_no(bpage)); + if (!block_mutex) { + /* It may be impossible case... + Something wrong, so will be scan_again */ + all_freed = FALSE; + goto next_page; } -#endif - if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { - /* This is a compressed-only block - descriptor. Do nothing. */ - } else if (((buf_block_t*) bpage)->is_hashed) { - ulint page_no; - ulint zip_size; - - //buf_pool_mutex_exit(buf_pool); - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); - - zip_size = buf_page_get_zip_size(bpage); - page_no = buf_page_get_page_no(bpage); + if (bpage->buf_fix_count > 0) { mutex_exit(block_mutex); + buf_flush_list_mutex_enter(buf_pool); - /* Note that the following call will acquire - an S-latch on the page */ + /* We cannot remove this page during + this scan yet; maybe the system is + currently reading it in, or flushing + the modifications to the file */ - btr_search_drop_page_hash_when_freed( - id, zip_size, page_no); - goto scan_again; + all_freed = FALSE; + goto next_page; } - if (bpage->oldest_modification != 0) { + ut_ad(bpage->oldest_modification != 0); - buf_flush_remove(bpage); - } + buf_flush_remove(bpage); - /* Remove from the LRU list. */ - - if (buf_LRU_block_remove_hashed_page(bpage, TRUE) - != BUF_BLOCK_ZIP_FREE) { - buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE); - mutex_exit(block_mutex); - } else { - /* The block_mutex should have been released - by buf_LRU_block_remove_hashed_page() when it - returns BUF_BLOCK_ZIP_FREE. */ - ut_ad(block_mutex == &buf_pool->zip_mutex); - ut_ad(!mutex_own(block_mutex)); - } + mutex_exit(block_mutex); + buf_flush_list_mutex_enter(buf_pool); next_page: bpage = prev_bpage; + + if (!bpage) { + break; + } + + /* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the + loop we release buf_pool->mutex to let other threads + do their job. */ + if (i < BUF_LRU_DROP_SEARCH_SIZE) { + continue; + } + + /* We IO-fix the block to make sure that the block + stays in its position in the flush_list. */ + if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + /* Block is already IO-fixed. We don't + want to change the value. Lets leave + this block alone. */ + continue; + } + + buf_flush_list_mutex_exit(buf_pool); + block_mutex = buf_page_get_mutex(bpage); + mutex_enter(block_mutex); + buf_page_set_sticky(bpage); + mutex_exit(block_mutex); + + /* Now it is safe to release the buf_pool->mutex. */ + //buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->LRU_list_mutex); + rw_lock_x_unlock(&buf_pool->page_hash_latch); + + os_thread_yield(); + //buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->LRU_list_mutex); + rw_lock_x_lock(&buf_pool->page_hash_latch); + + + mutex_enter(block_mutex); + buf_page_unset_sticky(bpage); + mutex_exit(block_mutex); + + buf_flush_list_mutex_enter(buf_pool); + ut_ad(bpage->in_flush_list); + + i = 0; } - //buf_pool_mutex_exit(buf_pool); +// buf_pool_mutex_exit(buf_pool); mutex_exit(&buf_pool->LRU_list_mutex); rw_lock_x_unlock(&buf_pool->page_hash_latch); + buf_flush_list_mutex_exit(buf_pool); + + ut_ad(buf_flush_validate(buf_pool)); if (!all_freed) { os_thread_sleep(20000); @@ -525,7 +541,7 @@ buf_LRU_invalidate_tablespace( buf_pool = buf_pool_from_array(i); buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); - buf_LRU_invalidate_tablespace_buf_pool_instance(buf_pool, id); + buf_LRU_remove_dirty_pages_for_tablespace(buf_pool, id); } } @@ -567,7 +583,7 @@ buf_LRU_mark_space_was_deleted( for (k = chunk->size; k--; block++) { if (buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE - || !block->is_hashed + || !block->index || buf_page_get_space(&block->page) != id) { continue; } @@ -575,7 +591,7 @@ buf_LRU_mark_space_was_deleted( btr_search_s_unlock_all(); rw_lock_x_lock(&block->lock); - btr_search_drop_page_hash_index(block, NULL); + btr_search_drop_page_hash_index(block); rw_lock_x_unlock(&block->lock); btr_search_s_lock_all(); @@ -1726,8 +1742,7 @@ not_freed: /* Prevent buf_page_get_gen() from decompressing the block while we release buf_pool->mutex and block_mutex. */ - b->buf_fix_count++; - b->io_fix = BUF_IO_READ; + buf_page_set_sticky(b); mutex_exit(&buf_pool->zip_mutex); } @@ -1744,7 +1759,7 @@ not_freed: UNIV_MEM_VALID(((buf_block_t*) bpage)->frame, UNIV_PAGE_SIZE); - btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL); + btr_search_drop_page_hash_index((buf_block_t*) bpage); UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame, UNIV_PAGE_SIZE); @@ -1772,8 +1787,7 @@ not_freed: if (b) { mutex_enter(&buf_pool->zip_mutex); - b->buf_fix_count--; - buf_page_set_io_fix(b, BUF_IO_NONE); + buf_page_unset_sticky(b); mutex_exit(&buf_pool->zip_mutex); } diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 07f22e4d1d6..98cf88455bd 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -919,6 +919,11 @@ dict_index_find_on_id_low( dict_table_t* table; dict_index_t* index; + /* This can happen if the system tablespace is the wrong page size */ + if (dict_sys == NULL) { + return(NULL); + } + table = UT_LIST_GET_FIRST(dict_sys->table_LRU); while (table) { diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c index 47f969727fb..5303557548b 100644 --- a/storage/xtradb/dict/dict0load.c +++ b/storage/xtradb/dict/dict0load.c @@ -849,7 +849,7 @@ loop: object and check that the .ibd file exists. */ fil_open_single_table_tablespace(FALSE, space_id, - flags, name); + flags, name, NULL); } mem_free(name); @@ -1904,7 +1904,7 @@ err_exit: if (!fil_open_single_table_tablespace( TRUE, table->space, table->flags == DICT_TF_COMPACT ? 0 : - table->flags & ~(~0 << DICT_TF_BITS), name)) { + table->flags & ~(~0 << DICT_TF_BITS), name, NULL)) { /* We failed to find a sensible tablespace file */ diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c index 41b61be0b5b..8cabf13e2c4 100644 --- a/storage/xtradb/fil/fil0fil.c +++ b/storage/xtradb/fil/fil0fil.c @@ -1827,36 +1827,44 @@ fil_write_flushed_lsn_to_data_files( } /*******************************************************************//** -Reads the flushed lsn and arch no fields from a data file at database -startup. */ +Reads the flushed lsn, arch no, and tablespace flag fields from a data +file at database startup. */ UNIV_INTERN void -fil_read_flushed_lsn_and_arch_log_no( -/*=================================*/ +fil_read_first_page( +/*================*/ os_file_t data_file, /*!< in: open data file */ ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ + ulint* flags, /*!< out: tablespace flags */ #ifdef UNIV_LOG_ARCHIVE - ulint* min_arch_log_no, /*!< in/out: */ - ulint* max_arch_log_no, /*!< in/out: */ + ulint* min_arch_log_no, /*!< out: min of archived + log numbers in data files */ + ulint* max_arch_log_no, /*!< out: max of archived + log numbers in data files */ #endif /* UNIV_LOG_ARCHIVE */ - ib_uint64_t* min_flushed_lsn, /*!< in/out: */ - ib_uint64_t* max_flushed_lsn) /*!< in/out: */ + ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed + lsn values in data files */ + ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed + lsn values in data files */ { byte* buf; - byte* buf2; + page_t* page; ib_uint64_t flushed_lsn; - buf2 = ut_malloc(2 * UNIV_PAGE_SIZE); + buf = ut_malloc(2 * UNIV_PAGE_SIZE); /* Align the memory for a possible read from a raw device */ - buf = ut_align(buf2, UNIV_PAGE_SIZE); + page = ut_align(buf, UNIV_PAGE_SIZE); - os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE); + os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE); - flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN); + *flags = mach_read_from_4(page + + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS); - ut_free(buf2); + flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN); + + ut_free(buf); if (!one_read_already) { *min_flushed_lsn = flushed_lsn; @@ -3174,8 +3182,11 @@ fil_open_single_table_tablespace( accessing the first page of the file */ ulint id, /*!< in: space id */ ulint flags, /*!< in: tablespace flags */ - const char* name) /*!< in: table name in the + const char* name, /*!< in: table name in the databasename/tablename format */ + trx_t* trx) /*!< in: transaction. This is only used + for IMPORT TABLESPACE, must be NULL + otherwise */ { os_file_t file; char* filepath; @@ -3393,6 +3404,11 @@ skip_info: /* over write space id of all pages */ rec_offs_init(offsets_); + /* Unlock the data dictionary to not block queries + accessing other tables */ + ut_a(trx); + row_mysql_unlock_data_dictionary(trx); + fprintf(stderr, "InnoDB: Progress in %%:"); for (offset = 0; offset < free_limit_bytes; @@ -3594,6 +3610,9 @@ skip_write: fprintf(stderr, " done.\n"); + /* Reacquire the data dictionary lock */ + row_mysql_lock_data_dictionary(trx); + /* update SYS_INDEXES set root page */ index = dict_table_get_first_index(table); while (index) { diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c index 5e3959a3c7f..6102c5decd8 100644 --- a/storage/xtradb/fsp/fsp0fsp.c +++ b/storage/xtradb/fsp/fsp0fsp.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri #include "dict0mem.h" #include "trx0sys.h" -#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header - within a file page */ - -/* The data structures in files are defined just as byte strings in C */ -typedef byte fsp_header_t; -typedef byte xdes_t; - -/* SPACE HEADER - ============ - -File space header data structure: this data structure is contained in the -first page of a space. The space for this header is reserved in every extent -descriptor page, but used only in the first. */ - -/*-------------------------------------*/ -#define FSP_SPACE_ID 0 /* space id */ -#define FSP_NOT_USED 4 /* this field contained a value up to - which we know that the modifications - in the database have been flushed to - the file space; not used now */ -#define FSP_SIZE 8 /* Current size of the space in - pages */ -#define FSP_FREE_LIMIT 12 /* Minimum page number for which the - free list has not been initialized: - the pages >= this limit are, by - definition, free; note that in a - single-table tablespace where size - < 64 pages, this number is 64, i.e., - we have initialized the space - about the first extent, but have not - physically allocted those pages to the - file */ -#define FSP_SPACE_FLAGS 16 /* table->flags & ~DICT_TF_COMPACT */ -#define FSP_FRAG_N_USED 20 /* number of used pages in the - FSP_FREE_FRAG list */ -#define FSP_FREE 24 /* list of free extents */ -#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE) - /* list of partially free extents not - belonging to any segment */ -#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE) - /* list of full extents not belonging - to any segment */ -#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE) - /* 8 bytes which give the first unused - segment id */ -#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE) - /* list of pages containing segment - headers, where all the segment inode - slots are reserved */ -#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE) - /* list of pages containing segment - headers, where not all the segment - header slots are reserved */ -/*-------------------------------------*/ -/* File space header size */ -#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE) - -#define FSP_FREE_ADD 4 /* this many free extents are added - to the free list from above - FSP_FREE_LIMIT at a time */ - /* FILE SEGMENT INODE ================== diff --git a/storage/xtradb/ha/ha0ha.c b/storage/xtradb/ha/ha0ha.c index b28995553e0..2f5051e541f 100644 --- a/storage/xtradb/ha/ha0ha.c +++ b/storage/xtradb/ha/ha0ha.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -88,41 +88,6 @@ ha_create_func( return(table); } -/*************************************************************//** -Empties a hash table and frees the memory heaps. */ -UNIV_INTERN -void -ha_clear( -/*=====*/ - hash_table_t* table) /*!< in, own: hash table */ -{ - ulint i; - ulint n; - - ut_ad(table); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); -#ifdef UNIV_SYNC_DEBUG - /* cannot identificate which btr_search_latch[i] for now */ - //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE)); -#endif /* UNIV_SYNC_DEBUG */ - -#ifndef UNIV_HOTBACKUP - /* Free the memory heaps. */ - n = table->n_mutexes; - - for (i = 0; i < n; i++) { - mem_heap_free(table->heaps[i]); - } -#endif /* !UNIV_HOTBACKUP */ - - /* Clear the hash table. */ - n = hash_get_n_cells(table); - - for (i = 0; i < n; i++) { - hash_get_nth_cell(table, i)->node = NULL; - } -} - /*************************************************************//** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node @@ -141,7 +106,7 @@ ha_insert_for_fold_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* block, /*!< in: buffer block containing the data */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - void* data) /*!< in: data, must not be NULL */ + const rec_t* data) /*!< in: data, must not be NULL */ { hash_cell_t* cell; ha_node_t* node; @@ -154,7 +119,11 @@ ha_insert_for_fold_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ut_a(block->frame == page_align(data)); #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#ifdef UNIV_SYNC_DEBUG + ut_ad(rw_lock_own(block->btr_search_latch, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ ASSERT_HASH_MUTEX_OWN(table, fold); + ut_ad(btr_search_enabled); hash = hash_calc_hash(fold, table); @@ -174,7 +143,6 @@ ha_insert_for_fold_func( prev_block->n_pointers--; block->n_pointers++; } - ut_ad(!btr_search_fully_disabled); # endif /* !UNIV_HOTBACKUP */ prev_node->block = block; @@ -187,13 +155,6 @@ ha_insert_for_fold_func( prev_node = prev_node->next; } - /* We are in the process of disabling hash index, do not add - new chain node */ - if (!btr_search_enabled) { - ut_ad(!btr_search_fully_disabled); - return(TRUE); - } - /* We have to allocate a new chain node */ node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t)); @@ -251,6 +212,10 @@ ha_delete_hash_node( { ut_ad(table); ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); +#ifdef UNIV_SYNC_DEBUG + // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + ut_ad(btr_search_enabled); #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG # ifndef UNIV_HOTBACKUP if (table->adaptive) { @@ -273,11 +238,11 @@ ha_search_and_update_if_found_func( /*===============================*/ hash_table_t* table, /*!< in/out: hash table */ ulint fold, /*!< in: folded value of the searched data */ - void* data, /*!< in: pointer to the data */ + const rec_t* data, /*!< in: pointer to the data */ #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* new_block,/*!< in: block containing new_data */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - void* new_data)/*!< in: new pointer to the data */ + const rec_t* new_data)/*!< in: new pointer to the data */ { ha_node_t* node; @@ -287,6 +252,13 @@ ha_search_and_update_if_found_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ut_a(new_block->frame == page_align(new_data)); #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#ifdef UNIV_SYNC_DEBUG + // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + if (!btr_search_enabled) { + return; + } node = ha_search_with_data(table, fold, data); @@ -323,6 +295,10 @@ ha_remove_all_nodes_to_page( ut_ad(table); ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); ASSERT_HASH_MUTEX_OWN(table, fold); +#ifdef UNIV_SYNC_DEBUG + // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + ut_ad(btr_search_enabled); node = ha_chain_get_first(table, fold); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 3aa5ff1622d..504595b1448 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -3035,7 +3035,6 @@ skip_overwrite: /* Get the current high water mark format. */ innobase_file_format_max = (char*) trx_sys_file_format_max_get(); - btr_search_fully_disabled = (!btr_search_enabled); DBUG_RETURN(FALSE); error: DBUG_RETURN(TRUE); @@ -5839,8 +5838,7 @@ no_commit: switch (sql_command) { case SQLCOM_LOAD: - if ((trx->duplicates - & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) { + if (trx->duplicates) { goto set_max_autoinc; } @@ -6128,8 +6126,7 @@ ha_innobase::update_row( && table->next_number_field && new_row == table->record[0] && thd_sql_command(user_thd) == SQLCOM_INSERT - && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE)) - == TRX_DUP_IGNORE) { + && trx->duplicates) { ulonglong auto_inc; ulonglong col_max_value; @@ -6515,6 +6512,7 @@ ha_innobase::index_read( (byte*) key_ptr, (ulint) key_len, prebuilt->trx); + DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0); } else { /* We position the cursor to the last or the first entry in the index */ @@ -6616,7 +6614,6 @@ ha_innobase::innobase_get_index( dict_index_t* index = 0; DBUG_ENTER("innobase_get_index"); - ha_statistic_increment(&SSV::ha_read_key_count); if (keynr != MAX_KEY && table->s->keys > 0) { key = table->key_info + keynr; @@ -6630,13 +6627,13 @@ ha_innobase::innobase_get_index( table. Only print message if the index translation table exists */ if (share->idx_trans_tbl.index_mapping) { - sql_print_error("InnoDB could not find " - "index %s key no %u for " - "table %s through its " - "index translation table", - key ? key->name : "NULL", - keynr, - prebuilt->table->name); + sql_print_warning("InnoDB could not find " + "index %s key no %u for " + "table %s through its " + "index translation table", + key ? key->name : "NULL", + keynr, + prebuilt->table->name); } index = dict_table_get_index_on_name(prebuilt->table, @@ -8465,6 +8462,9 @@ ha_innobase::records_in_range( (const uchar*) 0), (ulint) (min_key ? min_key->length : 0), prebuilt->trx); + DBUG_ASSERT(min_key + ? range_start->n_fields > 0 + : range_start->n_fields == 0); row_sel_convert_mysql_key_to_innobase( range_end, (byte*) key_val_buff2, @@ -8473,6 +8473,9 @@ ha_innobase::records_in_range( (const uchar*) 0), (ulint) (max_key ? max_key->length : 0), prebuilt->trx); + DBUG_ASSERT(max_key + ? range_end->n_fields > 0 + : range_end->n_fields == 0); mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag : HA_READ_KEY_EXACT); @@ -9217,7 +9220,10 @@ ha_innobase::check( putc('\n', stderr); #endif - if (!btr_validate_index(index, prebuilt->trx)) { + /* If this is an index being created, break */ + if (*index->name == TEMP_INDEX_PREFIX) { + break; + } else if (!btr_validate_index(index, prebuilt->trx)) { is_ok = FALSE; innobase_format_name( @@ -9770,6 +9776,7 @@ ha_innobase::extra( break; case HA_EXTRA_RESET_STATE: reset_template(); + thd_to_trx(ha_thd())->duplicates = 0; break; case HA_EXTRA_NO_KEYREAD: prebuilt->read_just_key = 0; @@ -9787,19 +9794,18 @@ ha_innobase::extra( parameters below. We must not invoke update_thd() either, because the calling threads may change. CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */ - case HA_EXTRA_IGNORE_DUP_KEY: + case HA_EXTRA_INSERT_WITH_UPDATE: thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE; break; + case HA_EXTRA_NO_IGNORE_DUP_KEY: + thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE; + break; case HA_EXTRA_WRITE_CAN_REPLACE: thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE; break; case HA_EXTRA_WRITE_CANNOT_REPLACE: thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE; break; - case HA_EXTRA_NO_IGNORE_DUP_KEY: - thd_to_trx(ha_thd())->duplicates &= - ~(TRX_DUP_IGNORE | TRX_DUP_REPLACE); - break; default:/* Do nothing */ ; } @@ -12549,10 +12555,42 @@ static MYSQL_SYSVAR_ULINT(checkpoint_age_target, srv_checkpoint_age_target, "Control soft limit of checkpoint age. (0 : not control)", NULL, NULL, 0, 0, ~0UL, 0); -static MYSQL_SYSVAR_ULINT(flush_neighbor_pages, srv_flush_neighbor_pages, - PLUGIN_VAR_RQCMDARG, - "Enable/Disable flushing also neighbor pages. 0:disable 1:enable", - NULL, NULL, 1, 0, 1, 0); +static +void +innodb_flush_neighbor_pages_update( + THD* thd, + struct st_mysql_sys_var* var, + void* var_ptr, + const void* save) +{ + *(long *)var_ptr = (*(long *)save) % 3; +} + +const char *flush_neighbor_pages_names[]= +{ + "none", /* 0 */ + "area", + "cont", /* 2 */ + /* For compatibility with the older patch */ + "0", /* "none" + 3 */ + "1", /* "area" + 3 */ + "2", /* "cont" + 3 */ + NullS +}; + +TYPELIB flush_neighbor_pages_typelib= +{ + array_elements(flush_neighbor_pages_names) - 1, + "flush_neighbor_pages_typelib", + flush_neighbor_pages_names, + NULL +}; + +static MYSQL_SYSVAR_ENUM(flush_neighbor_pages, srv_flush_neighbor_pages, + PLUGIN_VAR_RQCMDARG, "Neighbor page flushing behaviour: none: do not flush, " + "[area]: flush selected pages one-by-one, " + "cont: flush a contiguous block of pages", NULL, + innodb_flush_neighbor_pages_update, 1, &flush_neighbor_pages_typelib); static void @@ -12618,6 +12656,14 @@ static MYSQL_SYSVAR_ENUM(adaptive_flushing_method, srv_adaptive_flushing_method, "Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)", NULL, innodb_adaptive_flushing_method_update, 1, &adaptive_flushing_method_typelib); +#ifdef UNIV_DEBUG +static MYSQL_SYSVAR_ULONG(flush_checkpoint_debug, srv_flush_checkpoint_debug, + PLUGIN_VAR_RQCMDARG, + "Debug flags for InnoDB flushing and checkpointing (0=none," + "1=stop preflush and checkpointing)", + NULL, NULL, 0, 0, 1, 0); +#endif + static MYSQL_SYSVAR_ULONG(import_table_from_xtrabackup, srv_expand_import, PLUGIN_VAR_RQCMDARG, "Enable/Disable converting automatically *.ibd files when import tablespace.", @@ -12764,6 +12810,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(purge_threads), MYSQL_SYSVAR(purge_batch_size), MYSQL_SYSVAR(rollback_segments), +#ifdef UNIV_DEBUG + MYSQL_SYSVAR(flush_checkpoint_debug), +#endif MYSQL_SYSVAR(corrupt_table_action), MYSQL_SYSVAR(lazy_drop_table), MYSQL_SYSVAR(fake_changes), diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index 72ff5f7198b..3b87b860a4a 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -3916,7 +3916,7 @@ i_s_innodb_buffer_pool_pages_index_fill( table->field[2]->store(block->page.offset, TRUE); table->field[3]->store(page_get_n_recs(frame), TRUE); table->field[4]->store(page_get_data_size(frame), TRUE); - table->field[5]->store(block->is_hashed, TRUE); + table->field[5]->store(block->index != NULL, TRUE); table->field[6]->store(block->page.access_time, TRUE); table->field[7]->store(block->page.newest_modification != 0, TRUE); table->field[8]->store(block->page.oldest_modification != 0, TRUE); diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c index 7def360867d..00b7ea7347d 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.c +++ b/storage/xtradb/ibuf/ibuf0ibuf.c @@ -254,11 +254,20 @@ ibuf_count_check( list of the ibuf */ /* @} */ +#define IBUF_REC_FIELD_SPACE 0 /*!< in the pre-4.1 format, + the page number. later, the space_id */ +#define IBUF_REC_FIELD_MARKER 1 /*!< starting with 4.1, a marker + consisting of 1 byte that is 0 */ +#define IBUF_REC_FIELD_PAGE 2 /*!< starting with 4.1, the + page number */ +#define IBUF_REC_FIELD_METADATA 3 /* the metadata field */ +#define IBUF_REC_FIELD_USER 4 /* first user field */ + /* Various constants for checking the type of an ibuf record and extracting data from it. For details, see the description of the record format at the top of this file. */ -/** @name Format of the fourth column of an insert buffer record +/** @name Format of the IBUF_REC_FIELD_METADATA of an insert buffer record The fourth column in the MySQL 5.5 format contains an operation type, counter, and some flags. */ /* @{ */ @@ -1275,13 +1284,13 @@ ibuf_rec_get_page_no_func( ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); - field = rec_get_nth_field_old(rec, 1, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len); if (len == 1) { /* This is of the >= 4.1.x record format */ ut_a(trx_sys_multiple_tablespace_format); - field = rec_get_nth_field_old(rec, 2, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_PAGE, &len); } else { ut_a(trx_doublewrite_must_reset_space_ids); ut_a(!trx_sys_multiple_tablespace_format); @@ -1321,13 +1330,13 @@ ibuf_rec_get_space_func( ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); - field = rec_get_nth_field_old(rec, 1, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len); if (len == 1) { /* This is of the >= 4.1.x record format */ ut_a(trx_sys_multiple_tablespace_format); - field = rec_get_nth_field_old(rec, 0, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len); ut_a(len == 4); return(mach_read_from_4(field)); @@ -1377,9 +1386,9 @@ ibuf_rec_get_info_func( || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); fields = rec_get_n_fields_old(rec); - ut_a(fields > 4); + ut_a(fields > IBUF_REC_FIELD_USER); - types = rec_get_nth_field_old(rec, 3, &len); + types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len); info_len_local = len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE; @@ -1405,7 +1414,8 @@ ibuf_rec_get_info_func( ut_a(op_local < IBUF_OP_COUNT); ut_a((len - info_len_local) == - (fields - 4) * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); + (fields - IBUF_REC_FIELD_USER) + * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); if (op) { *op = op_local; @@ -1449,7 +1459,7 @@ ibuf_rec_get_op_type_func( ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); - (void) rec_get_nth_field_old(rec, 1, &len); + (void) rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len); if (len > 1) { /* This is a < 4.1.x format record */ @@ -1478,12 +1488,12 @@ ibuf_rec_get_counter( const byte* ptr; ulint len; - if (rec_get_n_fields_old(rec) < 4) { + if (rec_get_n_fields_old(rec) <= IBUF_REC_FIELD_METADATA) { return(ULINT_UNDEFINED); } - ptr = rec_get_nth_field_old(rec, 3, &len); + ptr = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len); if (len >= 2) { @@ -1708,7 +1718,7 @@ ibuf_build_entry_from_ibuf_rec_func( || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); - data = rec_get_nth_field_old(ibuf_rec, 1, &len); + data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len); if (len > 1) { /* This a < 4.1.x format record */ @@ -1720,13 +1730,13 @@ ibuf_build_entry_from_ibuf_rec_func( ut_a(trx_sys_multiple_tablespace_format); ut_a(*data == 0); - ut_a(rec_get_n_fields_old(ibuf_rec) > 4); + ut_a(rec_get_n_fields_old(ibuf_rec) > IBUF_REC_FIELD_USER); - n_fields = rec_get_n_fields_old(ibuf_rec) - 4; + n_fields = rec_get_n_fields_old(ibuf_rec) - IBUF_REC_FIELD_USER; tuple = dtuple_create(heap, n_fields); - types = rec_get_nth_field_old(ibuf_rec, 3, &len); + types = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_METADATA, &len); ibuf_rec_get_info(mtr, ibuf_rec, NULL, &comp, &info_len, NULL); @@ -1740,7 +1750,8 @@ ibuf_build_entry_from_ibuf_rec_func( for (i = 0; i < n_fields; i++) { field = dtuple_get_nth_field(tuple, i); - data = rec_get_nth_field_old(ibuf_rec, i + 4, &len); + data = rec_get_nth_field_old( + ibuf_rec, i + IBUF_REC_FIELD_USER, &len); dfield_set_data(field, data, len); @@ -1787,7 +1798,7 @@ ibuf_rec_get_size( field_offset = 2; types_offset = DATA_ORDER_NULL_TYPE_BUF_SIZE; } else { - field_offset = 4; + field_offset = IBUF_REC_FIELD_USER; types_offset = DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE; } @@ -1848,7 +1859,7 @@ ibuf_rec_get_volume_func( ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(ibuf_rec) > 2); - data = rec_get_nth_field_old(ibuf_rec, 1, &len); + data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len); pre_4_1 = (len > 1); if (pre_4_1) { @@ -1871,7 +1882,8 @@ ibuf_rec_get_volume_func( ut_a(trx_sys_multiple_tablespace_format); ut_a(*data == 0); - types = rec_get_nth_field_old(ibuf_rec, 3, &len); + types = rec_get_nth_field_old( + ibuf_rec, IBUF_REC_FIELD_METADATA, &len); ibuf_rec_get_info(mtr, ibuf_rec, &op, &comp, &info_len, NULL); @@ -1901,7 +1913,8 @@ ibuf_rec_get_volume_func( } types += info_len; - n_fields = rec_get_n_fields_old(ibuf_rec) - 4; + n_fields = rec_get_n_fields_old(ibuf_rec) + - IBUF_REC_FIELD_USER; } data_size = ibuf_rec_get_size(ibuf_rec, types, n_fields, pre_4_1, comp); @@ -1956,11 +1969,11 @@ ibuf_entry_build( n_fields = dtuple_get_n_fields(entry); - tuple = dtuple_create(heap, n_fields + 4); + tuple = dtuple_create(heap, n_fields + IBUF_REC_FIELD_USER); /* 1) Space Id */ - field = dtuple_get_nth_field(tuple, 0); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE); buf = mem_heap_alloc(heap, 4); @@ -1970,7 +1983,7 @@ ibuf_entry_build( /* 2) Marker byte */ - field = dtuple_get_nth_field(tuple, 1); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER); buf = mem_heap_alloc(heap, 1); @@ -1982,7 +1995,7 @@ ibuf_entry_build( /* 3) Page number */ - field = dtuple_get_nth_field(tuple, 2); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE); buf = mem_heap_alloc(heap, 4); @@ -2030,10 +2043,7 @@ ibuf_entry_build( ulint fixed_len; const dict_field_t* ifield; - /* We add 4 below because we have the 4 extra fields at the - start of an ibuf record */ - - field = dtuple_get_nth_field(tuple, i + 4); + field = dtuple_get_nth_field(tuple, i + IBUF_REC_FIELD_USER); entry_field = dtuple_get_nth_field(entry, i); dfield_copy(field, entry_field); @@ -2066,13 +2076,13 @@ ibuf_entry_build( /* 4) Type info, part #2 */ - field = dtuple_get_nth_field(tuple, 3); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_METADATA); dfield_set_data(field, type_info, ti - type_info); /* Set all the types in the new tuple binary */ - dtuple_set_types_binary(tuple, n_fields + 4); + dtuple_set_types_binary(tuple, n_fields + IBUF_REC_FIELD_USER); return(tuple); } @@ -2132,11 +2142,11 @@ ibuf_new_search_tuple_build( ut_a(trx_sys_multiple_tablespace_format); - tuple = dtuple_create(heap, 3); + tuple = dtuple_create(heap, IBUF_REC_FIELD_METADATA); /* Store the space id in tuple */ - field = dtuple_get_nth_field(tuple, 0); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_SPACE); buf = mem_heap_alloc(heap, 4); @@ -2146,7 +2156,7 @@ ibuf_new_search_tuple_build( /* Store the new format record marker byte */ - field = dtuple_get_nth_field(tuple, 1); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_MARKER); buf = mem_heap_alloc(heap, 1); @@ -2156,7 +2166,7 @@ ibuf_new_search_tuple_build( /* Store the page number in tuple */ - field = dtuple_get_nth_field(tuple, 2); + field = dtuple_get_nth_field(tuple, IBUF_REC_FIELD_PAGE); buf = mem_heap_alloc(heap, 4); @@ -2164,7 +2174,7 @@ ibuf_new_search_tuple_build( dfield_set_data(field, buf, 4); - dtuple_set_types_binary(tuple, 3); + dtuple_set_types_binary(tuple, IBUF_REC_FIELD_METADATA); return(tuple); } @@ -2833,8 +2843,10 @@ ibuf_get_volume_buffered_hash( ulint fold; ulint bitmask; - len = ibuf_rec_get_size(rec, types, rec_get_n_fields_old(rec) - 4, - FALSE, comp); + len = ibuf_rec_get_size( + rec, types, + rec_get_n_fields_old(rec) - IBUF_REC_FIELD_USER, + FALSE, comp); fold = ut_fold_binary(data, len); hash += (fold / (CHAR_BIT * sizeof *hash)) % size; @@ -2886,8 +2898,8 @@ ibuf_get_volume_buffered_count_func( ut_ad(ibuf_inside(mtr)); n_fields = rec_get_n_fields_old(rec); - ut_ad(n_fields > 4); - n_fields -= 4; + ut_ad(n_fields > IBUF_REC_FIELD_USER); + n_fields -= IBUF_REC_FIELD_USER; rec_get_nth_field_offs_old(rec, 1, &len); /* This function is only invoked when buffering new @@ -2896,7 +2908,7 @@ ibuf_get_volume_buffered_count_func( ut_a(len == 1); ut_ad(trx_sys_multiple_tablespace_format); - types = rec_get_nth_field_old(rec, 3, &len); + types = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len); switch (UNIV_EXPECT(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, IBUF_REC_INFO_SIZE)) { @@ -3208,7 +3220,7 @@ ibuf_update_max_tablespace_id(void) } else { rec = btr_pcur_get_rec(&pcur); - field = rec_get_nth_field_old(rec, 0, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len); ut_a(len == 4); @@ -3230,10 +3242,12 @@ ibuf_update_max_tablespace_id(void) ibuf_get_entry_counter_low_func(rec,space,page_no) #endif /****************************************************************//** -Helper function for ibuf_set_entry_counter. Checks if rec is for (space, -page_no), and if so, reads counter value from it and returns that + 1. -Otherwise, returns 0. -@return new counter value, or 0 */ +Helper function for ibuf_get_entry_counter_func. Checks if rec is for +(space, page_no), and if so, reads counter value from it and returns +that + 1. +@retval ULINT_UNDEFINED if the record does not contain any counter +@retval 0 if the record is not for (space, page_no) +@retval 1 + previous counter value, otherwise */ static ulint ibuf_get_entry_counter_low_func( @@ -3254,7 +3268,7 @@ ibuf_get_entry_counter_low_func( || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); ut_ad(rec_get_n_fields_old(rec) > 2); - field = rec_get_nth_field_old(rec, 1, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len); if (UNIV_UNLIKELY(len != 1)) { /* pre-4.1 format */ @@ -3267,7 +3281,7 @@ ibuf_get_entry_counter_low_func( ut_a(trx_sys_multiple_tablespace_format); /* Check the tablespace identifier. */ - field = rec_get_nth_field_old(rec, 0, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len); ut_a(len == 4); if (mach_read_from_4(field) != space) { @@ -3276,7 +3290,7 @@ ibuf_get_entry_counter_low_func( } /* Check the page offset. */ - field = rec_get_nth_field_old(rec, 2, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_PAGE, &len); ut_a(len == 4); if (mach_read_from_4(field) != page_no) { @@ -3285,7 +3299,7 @@ ibuf_get_entry_counter_low_func( } /* Check if the record contains a counter field. */ - field = rec_get_nth_field_old(rec, 3, &len); + field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_METADATA, &len); switch (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) { default: @@ -3301,147 +3315,61 @@ ibuf_get_entry_counter_low_func( } } +#ifdef UNIV_DEBUG +# define ibuf_get_entry_counter(space,page_no,rec,mtr,exact_leaf) \ + ibuf_get_entry_counter_func(space,page_no,rec,mtr,exact_leaf) +#else /* UNIV_DEBUG */ +# define ibuf_get_entry_counter(space,page_no,rec,mtr,exact_leaf) \ + ibuf_get_entry_counter_func(space,page_no,rec,exact_leaf) +#endif + /****************************************************************//** -Set the counter field in entry to the correct value based on the current +Calculate the counter field for an entry based on the current last record in ibuf for (space, page_no). -@return FALSE if we should abort this insertion to ibuf */ +@return the counter field, or ULINT_UNDEFINED +if we should abort this insertion to ibuf */ static -ibool -ibuf_set_entry_counter( -/*===================*/ - dtuple_t* entry, /*!< in/out: entry to patch */ +ulint +ibuf_get_entry_counter_func( +/*========================*/ ulint space, /*!< in: space id of entry */ ulint page_no, /*!< in: page number of entry */ - btr_pcur_t* pcur, /*!< in: pcur positioned on the record - found by btr_pcur_open(.., entry, - PAGE_CUR_LE, ..., pcur, ...) */ - ibool is_optimistic, /*!< in: is this an optimistic insert */ - mtr_t* mtr) /*!< in: mtr */ + const rec_t* rec, /*!< in: the record preceding the + insertion point */ +#ifdef UNIV_DEBUG + mtr_t* mtr, /*!< in: mini-transaction */ +#endif /* UNIV_DEBUG */ + ibool only_leaf) /*!< in: TRUE if this is the only + leaf page that can contain entries + for (space,page_no), that is, there + was no exact match for (space,page_no) + in the node pointer */ { - dfield_t* field; - byte* data; - ulint counter = 0; - - /* pcur points to either a user rec or to a page's infimum record. */ ut_ad(ibuf_inside(mtr)); - ut_ad(mtr_memo_contains(mtr, btr_pcur_get_block(pcur), - MTR_MEMO_PAGE_X_FIX)); - ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index)); + ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX)); + ut_ad(page_validate(page_align(rec), ibuf->index)); - if (btr_pcur_is_on_user_rec(pcur)) { - - counter = ibuf_get_entry_counter_low( - mtr, btr_pcur_get_rec(pcur), space, page_no); - - if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) { - /* The record lacks a counter field. - Such old records must be merged before - new records can be buffered. */ - - return(FALSE); - } - } else if (btr_pcur_is_before_first_in_tree(pcur, mtr)) { - /* Ibuf tree is either completely empty, or the insert - position is at the very first record of a non-empty tree. In - either case we have no previous records for (space, - page_no). */ - - counter = 0; - } else if (btr_pcur_is_before_first_on_page(pcur)) { - btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur); - - if (cursor->low_match < 3) { - /* If low_match < 3, we know that the father node - pointer did not contain the searched for (space, - page_no), which means that the search ended on the - right page regardless of the counter value, and - since we're at the infimum record, there are no - existing records. */ - - counter = 0; - } else { - rec_t* rec; - const page_t* page; - buf_block_t* block; - page_t* prev_page; - ulint prev_page_no; - - ut_a(cursor->ibuf_cnt != ULINT_UNDEFINED); - - page = btr_pcur_get_page(pcur); - prev_page_no = btr_page_get_prev(page, mtr); - - ut_a(prev_page_no != FIL_NULL); - - block = buf_page_get( - IBUF_SPACE_ID, 0, prev_page_no, - RW_X_LATCH, mtr); - - buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); - - prev_page = buf_block_get_frame(block); - - rec = page_rec_get_prev( - page_get_supremum_rec(prev_page)); - - ut_ad(page_rec_is_user_rec(rec)); - - counter = ibuf_get_entry_counter_low( - mtr, rec, space, page_no); - - if (UNIV_UNLIKELY(counter == ULINT_UNDEFINED)) { - /* The record lacks a counter field. - Such old records must be merged before - new records can be buffered. */ - - return(FALSE); - } - - if (counter < cursor->ibuf_cnt) { - /* Search ended on the wrong page. */ - - if (is_optimistic) { - /* In an optimistic insert, we can - shift the insert position to the left - page, since it only needs an X-latch - on the page itself, which the - original search acquired for us. */ - - btr_cur_position( - ibuf->index, rec, block, - btr_pcur_get_btr_cur(pcur)); - } else { - /* We can't shift the insert - position to the left page in a - pessimistic insert since it would - require an X-latch on the left - page's left page, so we have to - abort. */ - - return(FALSE); - } - } else { - /* The counter field in the father node is - the same as we would insert; we don't know - whether the insert should go to this page or - the left page (the later fields can differ), - so refuse the insert. */ - - return(FALSE); - } - } + if (page_rec_is_supremum(rec)) { + /* This is just for safety. The record should be a + page infimum or a user record. */ + ut_ad(0); + return(ULINT_UNDEFINED); + } else if (!page_rec_is_infimum(rec)) { + return(ibuf_get_entry_counter_low(mtr, rec, space, page_no)); + } else if (only_leaf + || fil_page_get_prev(page_align(rec)) == FIL_NULL) { + /* The parent node pointer did not contain the + searched for (space, page_no), which means that the + search ended on the correct page regardless of the + counter value, and since we're at the infimum record, + there are no existing records. */ + return(0); } else { - /* The cursor is not positioned at or before a user record. */ - return(FALSE); + /* We used to read the previous page here. It would + break the latching order, because the caller has + buffer-fixed an insert buffer bitmap page. */ + return(ULINT_UNDEFINED); } - - /* Patch counter value in already built entry. */ - field = dtuple_get_nth_field(entry, 3); - data = dfield_get_data(field); - - mach_write_to_2(data + IBUF_REC_OFFSET_COUNTER, counter); - - return(TRUE); } /*********************************************************************//** @@ -3650,16 +3578,27 @@ fail_exit: } } - /* Patch correct counter value to the entry to insert. This can - change the insert position, which can result in the need to abort in - some cases. */ - if (!no_counter - && !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur, - mode == BTR_MODIFY_PREV, &mtr)) { -bitmap_fail: - ibuf_mtr_commit(&bitmap_mtr); + if (!no_counter) { + /* Patch correct counter value to the entry to + insert. This can change the insert position, which can + result in the need to abort in some cases. */ + ulint counter = ibuf_get_entry_counter( + space, page_no, btr_pcur_get_rec(&pcur), &mtr, + btr_pcur_get_btr_cur(&pcur)->low_match + < IBUF_REC_FIELD_METADATA); + dfield_t* field; - goto fail_exit; + if (counter == ULINT_UNDEFINED) { +bitmap_fail: + ibuf_mtr_commit(&bitmap_mtr); + goto fail_exit; + } + + field = dtuple_get_nth_field( + ibuf_entry, IBUF_REC_FIELD_METADATA); + mach_write_to_2( + (byte*) dfield_get_data(field) + + IBUF_REC_OFFSET_COUNTER, counter); } /* Set the bitmap bit denoting that the insert buffer contains @@ -4003,7 +3942,7 @@ ibuf_insert_to_index_page( ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); - ut_ad(!buf_block_align(page)->is_hashed); + ut_ad(!buf_block_align(page)->index); if (UNIV_UNLIKELY(dict_table_is_comp(index->table) != (ibool)!!page_is_comp(page))) { diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h index be918439f59..4f33aacc48e 100644 --- a/storage/xtradb/include/btr0cur.h +++ b/storage/xtradb/include/btr0cur.h @@ -743,24 +743,6 @@ struct btr_cur_struct { NULL */ ulint fold; /*!< fold value used in the search if flag is BTR_CUR_HASH */ - /*----- Delete buffering -------*/ - ulint ibuf_cnt; /* in searches done on insert buffer - trees, this contains the "counter" - value (the first two bytes of the - fourth field) extracted from the - page above the leaf page, from the - father node pointer that pointed to - the leaf page. in other words, it - contains the minimum counter value - for records to be inserted on the - chosen leaf page. If for some reason - this can't be read, or if the search - ended on the leftmost leaf page in - the tree (in which case the father - node pointer had the 'minimum - record' flag set), this is - ULINT_UNDEFINED. */ - /*------------------------------*/ /* @} */ btr_path_t* path_arr; /*!< in estimating the number of rows in range, we store in this array diff --git a/storage/xtradb/include/btr0pcur.h b/storage/xtradb/include/btr0pcur.h index f605c476844..140f94466db 100644 --- a/storage/xtradb/include/btr0pcur.h +++ b/storage/xtradb/include/btr0pcur.h @@ -263,14 +263,6 @@ btr_pcur_commit_specify_mtr( /*========================*/ btr_pcur_t* pcur, /*!< in: persistent cursor */ mtr_t* mtr); /*!< in: mtr to commit */ -/**************************************************************//** -Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. -@return TRUE if detached */ -UNIV_INLINE -ibool -btr_pcur_is_detached( -/*=================*/ - btr_pcur_t* pcur); /*!< in: persistent cursor */ /*********************************************************//** Moves the persistent cursor to the next record in the tree. If no records are left, the cursor stays 'after last in tree'. diff --git a/storage/xtradb/include/btr0pcur.ic b/storage/xtradb/include/btr0pcur.ic index d86601e5a32..054ce753c7d 100644 --- a/storage/xtradb/include/btr0pcur.ic +++ b/storage/xtradb/include/btr0pcur.ic @@ -388,38 +388,6 @@ btr_pcur_commit_specify_mtr( pcur->pos_state = BTR_PCUR_WAS_POSITIONED; } -/**************************************************************//** -Sets the pcur latch mode to BTR_NO_LATCHES. */ -UNIV_INLINE -void -btr_pcur_detach( -/*============*/ - btr_pcur_t* pcur) /*!< in: persistent cursor */ -{ - ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED); - - pcur->latch_mode = BTR_NO_LATCHES; - - pcur->pos_state = BTR_PCUR_WAS_POSITIONED; -} - -/**************************************************************//** -Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. -@return TRUE if detached */ -UNIV_INLINE -ibool -btr_pcur_is_detached( -/*=================*/ - btr_pcur_t* pcur) /*!< in: persistent cursor */ -{ - if (pcur->latch_mode == BTR_NO_LATCHES) { - - return(TRUE); - } - - return(FALSE); -} - /**************************************************************//** Sets the old_rec_buf field to NULL. */ UNIV_INLINE diff --git a/storage/xtradb/include/btr0sea.h b/storage/xtradb/include/btr0sea.h index 9e82602934e..d9f2cf9c81b 100644 --- a/storage/xtradb/include/btr0sea.h +++ b/storage/xtradb/include/btr0sea.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -137,11 +137,10 @@ UNIV_INTERN void btr_search_drop_page_hash_index( /*============================*/ - buf_block_t* block, /*!< in: block containing index page, + buf_block_t* block); /*!< in: block containing index page, s- or x-latched, or an index page for which we know that block->buf_fix_count == 0 */ - dict_index_t* index_in); /************************************************************************ Drops a page hash index based on index */ UNIV_INTERN @@ -150,8 +149,8 @@ btr_search_drop_page_hash_index_on_index( /*=====================================*/ dict_index_t* index); /* in: record descriptor */ /********************************************************************//** -Drops a page hash index when a page is freed from a fseg to the file system. -Drops possible hash index if the page happens to be in the buffer pool. */ +Drops a possible page hash index when a page is evicted from the buffer pool +or freed in a file segment. */ UNIV_INTERN void btr_search_drop_page_hash_when_freed( @@ -235,19 +234,6 @@ void btr_search_s_unlock_all(void); /*==========================*/ - -/** Flag: has the search system been enabled? -Protected by btr_search_latch and btr_search_enabled_mutex. */ -extern char btr_search_enabled; - -extern ulint btr_search_index_num; - -/** Flag: whether the search system has completed its disabling process, -It is set to TRUE right after buf_pool_drop_hash_index() in -btr_search_disable(), indicating hash index entries are cleaned up. -Protected by btr_search_latch and btr_search_enabled_mutex. */ -extern ibool btr_search_fully_disabled; - /** The search info struct in an index */ struct btr_search_struct{ ulint ref_count; /*!< Number of blocks in this index tree @@ -316,26 +302,6 @@ struct btr_search_sys_struct{ /** The adaptive hash index */ extern btr_search_sys_t* btr_search_sys; -/** @brief The latch protecting the adaptive search system - -This latch protects the -(1) hash index; -(2) columns of a record to which we have a pointer in the hash index; - -but does NOT protect: - -(3) next record offset field in a record; -(4) next or previous records on the same page. - -Bear in mind (3) and (4) when using the hash index. -*/ -//extern rw_lock_t* btr_search_latch_temp; - -extern rw_lock_t** btr_search_latch_part; - -/** The latch protecting the adaptive search system */ -//#define btr_search_latch (*btr_search_latch_temp) - #ifdef UNIV_SEARCH_PERF_STAT /** Number of successful adaptive hash index lookups */ extern ulint btr_search_n_succ; diff --git a/storage/xtradb/include/btr0types.h b/storage/xtradb/include/btr0types.h index 07c06fb18d7..6f515c3f58c 100644 --- a/storage/xtradb/include/btr0types.h +++ b/storage/xtradb/include/btr0types.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,6 +30,7 @@ Created 2/17/1996 Heikki Tuuri #include "rem0types.h" #include "page0types.h" +#include "sync0rw.h" /** Persistent cursor */ typedef struct btr_pcur_struct btr_pcur_t; @@ -38,6 +39,32 @@ typedef struct btr_cur_struct btr_cur_t; /** B-tree search information for the adaptive hash index */ typedef struct btr_search_struct btr_search_t; +/** @brief The latch protecting the adaptive search system + +This latch protects the +(1) hash index; +(2) columns of a record to which we have a pointer in the hash index; + +but does NOT protect: + +(3) next record offset field in a record; +(4) next or previous records on the same page. + +Bear in mind (3) and (4) when using the hash index. +*/ +//extern rw_lock_t* btr_search_latch_temp; + +extern rw_lock_t** btr_search_latch_part; + +/** The latch protecting the adaptive search system */ +//#define btr_search_latch (*btr_search_latch_temp) + +/** Flag: has the search system been enabled? +Protected by btr_search_latch. */ +extern char btr_search_enabled; + +extern ulint btr_search_index_num; + #ifdef UNIV_BLOB_DEBUG # include "buf0types.h" /** An index->blobs entry for keeping track of off-page column references */ diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h index d85dac5cc91..0ea74fb9eb2 100644 --- a/storage/xtradb/include/buf0buf.h +++ b/storage/xtradb/include/buf0buf.h @@ -244,13 +244,11 @@ buf_pool_free( ulint n_instances); /*!< in: numbere of instances to free */ /********************************************************************//** -Drops the adaptive hash index. To prevent a livelock, this function -is only to be called while holding btr_search_latch and while -btr_search_enabled == FALSE. */ +Clears the adaptive hash index on all pages in the buffer pool. */ UNIV_INTERN void -buf_pool_drop_hash_index(void); -/*==========================*/ +buf_pool_clear_hash_index(void); +/*===========================*/ /********************************************************************//** Relocate a buffer control block. Relocates the block on the LRU list @@ -583,17 +581,6 @@ buf_page_peek_if_too_old( /*=====================*/ const buf_page_t* bpage); /*!< in: block to make younger */ /********************************************************************//** -Returns the current state of is_hashed of a page. FALSE if the page is -not in the pool. NOTE that this operation does not fix the page in the -pool if it is found there. -@return TRUE if page hash index is built in search system */ -UNIV_INTERN -ibool -buf_page_peek_if_search_hashed( -/*===========================*/ - ulint space, /*!< in: space id */ - ulint offset);/*!< in: page number */ -/********************************************************************//** Gets the youngest modification log sequence number for a frame. Returns zero if not file page or no modification occurred yet. @return newest modification to page */ @@ -952,7 +939,27 @@ buf_block_set_io_fix( /*=================*/ buf_block_t* block, /*!< in/out: control block */ enum buf_io_fix io_fix);/*!< in: io_fix state */ - +/*********************************************************************//** +Makes a block sticky. A sticky block implies that even after we release +the buf_pool->mutex and the block->mutex: +* it cannot be removed from the flush_list +* the block descriptor cannot be relocated +* it cannot be removed from the LRU list +Note that: +* the block can still change its position in the LRU list +* the next and previous pointers can change. */ +UNIV_INLINE +void +buf_page_set_sticky( +/*================*/ + buf_page_t* bpage); /*!< in/out: control block */ +/*********************************************************************//** +Removes stickiness of a block. */ +UNIV_INLINE +void +buf_page_unset_sticky( +/*==================*/ + buf_page_t* bpage); /*!< in/out: control block */ /********************************************************************//** Determine if a buffer block can be relocated in memory. The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ @@ -1569,13 +1576,16 @@ struct buf_block_struct{ /* @} */ /** @name Hash search fields - These 6 fields may only be modified when we have + These 5 fields may only be modified when we have an x-latch on btr_search_latch AND - we are holding an s-latch or x-latch on buf_block_struct::lock or - we know that buf_block_struct::buf_fix_count == 0. An exception to this is when we init or create a page - in the buffer pool in buf0buf.c. */ + in the buffer pool in buf0buf.c. + + Another exception is that assigning block->index = NULL + is allowed whenever holding an x-latch on btr_search_latch. */ /* @{ */ @@ -1584,21 +1594,21 @@ struct buf_block_struct{ pointers in the adaptive hash index pointing to this frame */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - volatile unsigned is_hashed:1; /*!< TRUE if hash index has - already been built on this - page; note that it does not - guarantee that the index is - complete, though: there may - have been hash collisions, - record deletions, etc. */ unsigned curr_n_fields:10;/*!< prefix length for hash indexing: number of full fields */ unsigned curr_n_bytes:15;/*!< number of bytes in hash indexing */ unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */ - dict_index_t* index; /*!< Index for which the adaptive - hash index has been created. */ - volatile rw_lock_t* btr_search_latch; + dict_index_t* index; /*!< Index for which the + adaptive hash index has been + created, or NULL if the page + does not exist in the + index. Note that it does not + guarantee that the index is + complete, though: there may + have been hash collisions, + record deletions, etc. */ + volatile rw_lock_t* btr_search_latch; /* @} */ # ifdef UNIV_SYNC_DEBUG /** @name Debug fields */ diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic index 98d575075ba..55d89b66375 100644 --- a/storage/xtradb/include/buf0buf.ic +++ b/storage/xtradb/include/buf0buf.ic @@ -444,6 +444,7 @@ buf_page_get_io_fix( case BUF_IO_NONE: case BUF_IO_READ: case BUF_IO_WRITE: + case BUF_IO_PIN: return(io_fix); } ut_error; @@ -494,6 +495,49 @@ buf_block_set_io_fix( buf_page_set_io_fix(&block->page, io_fix); } +/*********************************************************************//** +Makes a block sticky. A sticky block implies that even after we release +the buf_pool->mutex and the block->mutex: +* it cannot be removed from the flush_list +* the block descriptor cannot be relocated +* it cannot be removed from the LRU list +Note that: +* the block can still change its position in the LRU list +* the next and previous pointers can change. */ +UNIV_INLINE +void +buf_page_set_sticky( +/*================*/ + buf_page_t* bpage) /*!< in/out: control block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); +#endif + ut_ad(mutex_own(buf_page_get_mutex(bpage))); + ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_NONE); + + bpage->io_fix = BUF_IO_PIN; +} + +/*********************************************************************//** +Removes stickiness of a block. */ +UNIV_INLINE +void +buf_page_unset_sticky( +/*==================*/ + buf_page_t* bpage) /*!< in/out: control block */ +{ +#ifdef UNIV_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); +#endif + ut_ad(mutex_own(buf_page_get_mutex(bpage))); + ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_PIN); + + bpage->io_fix = BUF_IO_NONE; +} + /********************************************************************//** Determine if a buffer block can be relocated in memory. The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ diff --git a/storage/xtradb/include/buf0types.h b/storage/xtradb/include/buf0types.h index 156093aad01..d140936a886 100644 --- a/storage/xtradb/include/buf0types.h +++ b/storage/xtradb/include/buf0types.h @@ -57,7 +57,10 @@ enum buf_flush { enum buf_io_fix { BUF_IO_NONE = 0, /**< no pending I/O */ BUF_IO_READ, /**< read pending */ - BUF_IO_WRITE /**< write pending */ + BUF_IO_WRITE, /**< write pending */ + BUF_IO_PIN /**< disallow relocation of + block and its removal of from + the flush_list */ }; /** Parameters of binary buddy system for compressed pages (buf0buddy.h) */ diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 840a9fbb13a..92fdca0db1b 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -34,6 +34,7 @@ Created 10/25/1995 Heikki Tuuri #include "sync0rw.h" #include "ibuf0types.h" #endif /* !UNIV_HOTBACKUP */ +#include "trx0types.h" /** When mysqld is run, the default directory "." is the mysqld datadir, but in the MySQL Embedded Server Library and ibbackup it is not the default @@ -329,18 +330,23 @@ Reads the flushed lsn and arch no fields from a data file at database startup. */ UNIV_INTERN void -fil_read_flushed_lsn_and_arch_log_no( -/*=================================*/ +fil_read_first_page( +/*================*/ os_file_t data_file, /*!< in: open data file */ ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ + ulint* flags, /*!< out: tablespace flags */ #ifdef UNIV_LOG_ARCHIVE - ulint* min_arch_log_no, /*!< in/out: */ - ulint* max_arch_log_no, /*!< in/out: */ + ulint* min_arch_log_no, /*!< out: min of archived + log numbers in data files */ + ulint* max_arch_log_no, /*!< out: max of archived + log numbers in data files */ #endif /* UNIV_LOG_ARCHIVE */ - ib_uint64_t* min_flushed_lsn, /*!< in/out: */ - ib_uint64_t* max_flushed_lsn); /*!< in/out: */ + ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed + lsn values in data files */ + ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed + lsn values in data files */ /*******************************************************************//** Increments the count of pending insert buffer page merges, if space is not being deleted. @@ -474,8 +480,11 @@ fil_open_single_table_tablespace( accessing the first page of the file */ ulint id, /*!< in: space id */ ulint flags, /*!< in: tablespace flags */ - const char* name); /*!< in: table name in the + const char* name, /*!< in: table name in the databasename/tablename format */ + trx_t* trx); /*!< in: transaction. This is only used + for IMPORT TABLESPACE, must be NULL + otherwise */ /********************************************************************//** It is possible, though very improbable, that the lsn's in the tablespace to be imported have risen above the current system lsn, if a lengthy purge, ibuf diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h index 7abd3914eda..d5e235aa870 100644 --- a/storage/xtradb/include/fsp0fsp.h +++ b/storage/xtradb/include/fsp0fsp.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri #include "page0types.h" #include "fsp0types.h" +/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */ + +/** Number of flag bits used to indicate the tablespace page size */ +#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4 +/** Zero relative shift position of the PAGE_SSIZE field */ +#define FSP_FLAGS_POS_PAGE_SSIZE 6 +/** Bit mask of the PAGE_SSIZE field */ +#define FSP_FLAGS_MASK_PAGE_SSIZE \ + ((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \ + << FSP_FLAGS_POS_PAGE_SSIZE) +/** Return the value of the PAGE_SSIZE field */ +#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \ + >> FSP_FLAGS_POS_PAGE_SSIZE) + +/* @} */ + +/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */ + +/** Offset of the space header within a file page */ +#define FSP_HEADER_OFFSET FIL_PAGE_DATA + +/* The data structures in files are defined just as byte strings in C */ +typedef byte fsp_header_t; +typedef byte xdes_t; + +/* SPACE HEADER + ============ + +File space header data structure: this data structure is contained in the +first page of a space. The space for this header is reserved in every extent +descriptor page, but used only in the first. */ + +/*-------------------------------------*/ +#define FSP_SPACE_ID 0 /* space id */ +#define FSP_NOT_USED 4 /* this field contained a value up to + which we know that the modifications + in the database have been flushed to + the file space; not used now */ +#define FSP_SIZE 8 /* Current size of the space in + pages */ +#define FSP_FREE_LIMIT 12 /* Minimum page number for which the + free list has not been initialized: + the pages >= this limit are, by + definition, free; note that in a + single-table tablespace where size + < 64 pages, this number is 64, i.e., + we have initialized the space + about the first extent, but have not + physically allocted those pages to the + file */ +#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to + dict_table_t::flags */ +#define FSP_FRAG_N_USED 20 /* number of used pages in the + FSP_FREE_FRAG list */ +#define FSP_FREE 24 /* list of free extents */ +#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE) + /* list of partially free extents not + belonging to any segment */ +#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE) + /* list of full extents not belonging + to any segment */ +#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE) + /* 8 bytes which give the first unused + segment id */ +#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE) + /* list of pages containing segment + headers, where all the segment inode + slots are reserved */ +#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE) + /* list of pages containing segment + headers, where not all the segment + header slots are reserved */ +/*-------------------------------------*/ +/* File space header size */ +#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE) + +#define FSP_FREE_ADD 4 /* this many free extents are added + to the free list from above + FSP_FREE_LIMIT at a time */ +/* @} */ + +/* @} */ + /**********************************************************************//** Initializes the file space system. */ UNIV_INTERN @@ -352,6 +436,18 @@ fseg_print( mtr_t* mtr); /*!< in: mtr */ #endif /* UNIV_BTR_PRINT */ +/********************************************************************//** +Extract the page size from tablespace flags. +This feature, storing the page_ssize into the tablespace flags, is added +to InnoDB 5.6.4. This is here only to protect against a crash if a newer +database is opened with this code branch. +@return page size of the tablespace in bytes */ +UNIV_INLINE +ulint +fsp_flags_get_page_size( +/*====================*/ + ulint flags); /*!< in: tablespace flags */ + #ifndef UNIV_NONINL #include "fsp0fsp.ic" #endif diff --git a/storage/xtradb/include/fsp0fsp.ic b/storage/xtradb/include/fsp0fsp.ic index 434c370b527..c92111a9d89 100644 --- a/storage/xtradb/include/fsp0fsp.ic +++ b/storage/xtradb/include/fsp0fsp.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -43,3 +43,31 @@ fsp_descr_page( return(UNIV_UNLIKELY((page_no & (zip_size - 1)) == FSP_XDES_OFFSET)); } +/********************************************************************//** +Extract the page size from tablespace flags. +This feature, storing the page_ssize into the tablespace flags, is added +to InnoDB 5.6.4. This is here only to protect against a crash if a newer +database is opened with this code branch. +@return page size of the tablespace in bytes */ +UNIV_INLINE +ulint +fsp_flags_get_page_size( +/*====================*/ + ulint flags) /*!< in: tablespace flags */ +{ + ulint page_size = 0; + ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); + + /* Convert from a 'log2 minus 9' to a page size in bytes. */ + if (UNIV_UNLIKELY(ssize)) { + page_size = (512 << ssize); + + ut_ad(page_size <= UNIV_PAGE_SIZE); + } else { + /* If the page size was not stored, then it is the + original 16k. */ + page_size = UNIV_PAGE_SIZE; + } + + return(page_size); +} diff --git a/storage/xtradb/include/ha0ha.h b/storage/xtradb/include/ha0ha.h index 3299000bf3c..8bba564d153 100644 --- a/storage/xtradb/include/ha0ha.h +++ b/storage/xtradb/include/ha0ha.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,13 +31,14 @@ Created 8/18/1994 Heikki Tuuri #include "hash0hash.h" #include "page0types.h" #include "buf0types.h" +#include "rem0types.h" /*************************************************************//** Looks for an element in a hash table. @return pointer to the data of the first hash table node in chain having the fold number, NULL if not found */ UNIV_INLINE -void* +const rec_t* ha_search_and_get_data( /*===================*/ hash_table_t* table, /*!< in: hash table */ @@ -51,11 +52,11 @@ ha_search_and_update_if_found_func( /*===============================*/ hash_table_t* table, /*!< in/out: hash table */ ulint fold, /*!< in: folded value of the searched data */ - void* data, /*!< in: pointer to the data */ + const rec_t* data, /*!< in: pointer to the data */ #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* new_block,/*!< in: block containing new_data */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - void* new_data);/*!< in: new pointer to the data */ + const rec_t* new_data);/*!< in: new pointer to the data */ #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG /** Looks for an element when we know the pointer to the data and @@ -113,14 +114,6 @@ chosen to be a slightly bigger prime number. # define ha_create(n_c,n_m,level) ha_create_func(n_c,n_m) #endif /* UNIV_SYNC_DEBUG */ -/*************************************************************//** -Empties a hash table and frees the memory heaps. */ -UNIV_INTERN -void -ha_clear( -/*=====*/ - hash_table_t* table); /*!< in, own: hash table */ - /*************************************************************//** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node @@ -138,7 +131,7 @@ ha_insert_for_fold_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* block, /*!< in: buffer block containing the data */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - void* data); /*!< in: data, must not be NULL */ + const rec_t* data); /*!< in: data, must not be NULL */ #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG /** @@ -174,7 +167,7 @@ ha_search_and_delete_if_found( /*==========================*/ hash_table_t* table, /*!< in: hash table */ ulint fold, /*!< in: folded value of the searched data */ - void* data); /*!< in: pointer to the data */ + const rec_t* data); /*!< in: pointer to the data */ #ifndef UNIV_HOTBACKUP /*****************************************************************//** Removes from the chain determined by fold all nodes whose data pointer @@ -217,7 +210,7 @@ struct ha_node_struct { #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* block; /*!< buffer block containing the data, or NULL */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - void* data; /*!< pointer to the data */ + const rec_t* data; /*!< pointer to the data */ ulint fold; /*!< fold value for the data */ }; diff --git a/storage/xtradb/include/ha0ha.ic b/storage/xtradb/include/ha0ha.ic index 734403c4cd9..f224776c134 100644 --- a/storage/xtradb/include/ha0ha.ic +++ b/storage/xtradb/include/ha0ha.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,6 +25,7 @@ Created 8/18/1994 Heikki Tuuri #include "ut0rnd.h" #include "mem0mem.h" +#include "btr0types.h" /***********************************************************//** Deletes a hash node. */ @@ -39,10 +40,10 @@ ha_delete_hash_node( Gets a hash node data. @return pointer to the data */ UNIV_INLINE -void* +const rec_t* ha_node_get_data( /*=============*/ - ha_node_t* node) /*!< in: hash chain node */ + const ha_node_t* node) /*!< in: hash chain node */ { return(node->data); } @@ -57,7 +58,7 @@ ha_node_set_data_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG buf_block_t* block, /*!< in: buffer block containing the data */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - void* data) /*!< in: pointer to the data */ + const rec_t* data) /*!< in: pointer to the data */ { #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG node->block = block; @@ -105,41 +106,12 @@ ha_chain_get_first( hash_get_nth_cell(table, hash_calc_hash(fold, table))->node); } -/*************************************************************//** -Looks for an element in a hash table. -@return pointer to the first hash table node in chain having the fold -number, NULL if not found */ -UNIV_INLINE -ha_node_t* -ha_search( -/*======*/ - hash_table_t* table, /*!< in: hash table */ - ulint fold) /*!< in: folded value of the searched data */ -{ - ha_node_t* node; - - ASSERT_HASH_MUTEX_OWN(table, fold); - - node = ha_chain_get_first(table, fold); - - while (node) { - if (node->fold == fold) { - - return(node); - } - - node = ha_chain_get_next(node); - } - - return(NULL); -} - /*************************************************************//** Looks for an element in a hash table. @return pointer to the data of the first hash table node in chain having the fold number, NULL if not found */ UNIV_INLINE -void* +const rec_t* ha_search_and_get_data( /*===================*/ hash_table_t* table, /*!< in: hash table */ @@ -148,6 +120,10 @@ ha_search_and_get_data( ha_node_t* node; ASSERT_HASH_MUTEX_OWN(table, fold); +#ifdef UNIV_SYNC_DEBUG +// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); +#endif /* UNIV_SYNC_DEBUG */ + ut_ad(btr_search_enabled); node = ha_chain_get_first(table, fold); @@ -172,12 +148,14 @@ ha_search_with_data( /*================*/ hash_table_t* table, /*!< in: hash table */ ulint fold, /*!< in: folded value of the searched data */ - void* data) /*!< in: pointer to the data */ + const rec_t* data) /*!< in: pointer to the data */ { ha_node_t* node; ASSERT_HASH_MUTEX_OWN(table, fold); + ut_ad(btr_search_enabled); + node = ha_chain_get_first(table, fold); while (node) { @@ -202,11 +180,15 @@ ha_search_and_delete_if_found( /*==========================*/ hash_table_t* table, /*!< in: hash table */ ulint fold, /*!< in: folded value of the searched data */ - void* data) /*!< in: pointer to the data */ + const rec_t* data) /*!< in: pointer to the data */ { ha_node_t* node; ASSERT_HASH_MUTEX_OWN(table, fold); +#ifdef UNIV_SYNC_DEBUG +// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + ut_ad(btr_search_enabled); node = ha_search_with_data(table, fold, data); diff --git a/storage/xtradb/include/page0page.h b/storage/xtradb/include/page0page.h index c1c659e2b70..1b9f9c84225 100644 --- a/storage/xtradb/include/page0page.h +++ b/storage/xtradb/include/page0page.h @@ -893,6 +893,7 @@ page_parse_create( ulint comp, /*!< in: nonzero=compact page format */ buf_block_t* block, /*!< in: block or NULL */ mtr_t* mtr); /*!< in: mtr or NULL */ +#ifndef UNIV_HOTBACKUP /************************************************************//** Prints record contents including the data relevant only in the index page context. */ @@ -902,6 +903,7 @@ page_rec_print( /*===========*/ const rec_t* rec, /*!< in: physical record */ const ulint* offsets);/*!< in: record descriptor */ +# ifdef UNIV_BTR_PRINT /***************************************************************//** This is used to print the contents of the directory for debugging purposes. */ @@ -941,6 +943,8 @@ page_print( in directory */ ulint rn); /*!< in: print rn first and last records in directory */ +# endif /* UNIV_BTR_PRINT */ +#endif /* !UNIV_HOTBACKUP */ /***************************************************************//** The following is used to validate a record on a page. This function differs from rec_validate as it can also check the n_owned field and diff --git a/storage/xtradb/include/row0upd.ic b/storage/xtradb/include/row0upd.ic index 11db82f64da..10646241125 100644 --- a/storage/xtradb/include/row0upd.ic +++ b/storage/xtradb/include/row0upd.ic @@ -28,7 +28,6 @@ Created 12/27/1996 Heikki Tuuri # include "trx0trx.h" # include "trx0undo.h" # include "row0row.h" -# include "btr0sea.h" #endif /* !UNIV_HOTBACKUP */ #include "page0zip.h" diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 6f985eacdf3..b660f7ea104 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -243,7 +243,7 @@ extern long long srv_ibuf_max_size; extern ulong srv_ibuf_active_contract; extern ulong srv_ibuf_accel_rate; extern ulint srv_checkpoint_age_target; -extern ulint srv_flush_neighbor_pages; +extern ulong srv_flush_neighbor_pages; extern ulint srv_deprecated_enable_unsafe_group_commit; extern ulong srv_read_ahead; extern ulong srv_adaptive_flushing_method; @@ -288,6 +288,9 @@ extern ibool srv_print_lock_waits; extern ibool srv_print_buf_io; extern ibool srv_print_log_io; extern ibool srv_print_latch_waits; + +extern ulong srv_flush_checkpoint_debug; + #else /* UNIV_DEBUG */ # define srv_print_thread_releases FALSE # define srv_print_lock_waits FALSE diff --git a/storage/xtradb/include/sync0rw.h b/storage/xtradb/include/sync0rw.h index 6420bc5d3bf..971099c91f5 100644 --- a/storage/xtradb/include/sync0rw.h +++ b/storage/xtradb/include/sync0rw.h @@ -543,7 +543,7 @@ mutex. */ UNIV_INTERN void rw_lock_debug_mutex_enter(void); -/*==========================*/ +/*===========================*/ /******************************************************************//** Releases the debug mutex. */ UNIV_INTERN @@ -634,7 +634,8 @@ struct rw_lock_struct { }; #ifdef UNIV_SYNC_DEBUG -/** The structure for storing debug info of an rw-lock */ +/** The structure for storing debug info of an rw-lock. All access to this +structure must be protected by rw_lock_debug_mutex_enter(). */ struct rw_lock_debug_struct { os_thread_id_t thread_id; /*!< The thread id of the thread which diff --git a/storage/xtradb/include/sync0rw.ic b/storage/xtradb/include/sync0rw.ic index a6dfa603c59..3eaa6172631 100644 --- a/storage/xtradb/include/sync0rw.ic +++ b/storage/xtradb/include/sync0rw.ic @@ -406,6 +406,7 @@ rw_lock_s_lock_func( #ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */ + ut_ad(!rw_lock_own(lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ /* TODO: study performance of UNIV_LIKELY branch prediction hints. */ diff --git a/storage/xtradb/include/sync0sync.h b/storage/xtradb/include/sync0sync.h index 6440a670f14..f9434ed54be 100644 --- a/storage/xtradb/include/sync0sync.h +++ b/storage/xtradb/include/sync0sync.h @@ -674,7 +674,6 @@ or row lock! */ #define SYNC_LOG_FLUSH_ORDER 156 #define SYNC_RECV 168 #define SYNC_WORK_QUEUE 162 -#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */ #define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory heap that can be extended to the buffer pool, its logical level is diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h index a03f7aceafa..eded5c303fa 100644 --- a/storage/xtradb/include/trx0trx.h +++ b/storage/xtradb/include/trx0trx.h @@ -494,6 +494,7 @@ struct trx_struct{ this is set to 1 then registered should also be set to 1. This is used in the XA code */ + unsigned called_commit_ordered:1;/* 1 if innobase_commit_ordered has run. */ /*------------------------------*/ ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */ ulint check_foreigns; /* normally TRUE, but if the user diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 0287ea40509..1a48d68d0d7 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX 8 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 20.1 +#define PERCONA_INNODB_VERSION 24.1 #endif /* The following is the InnoDB version as shown in diff --git a/storage/xtradb/log/log0log.c b/storage/xtradb/log/log0log.c index d9676707cfd..af0c801a4ec 100644 --- a/storage/xtradb/log/log0log.c +++ b/storage/xtradb/log/log0log.c @@ -1693,10 +1693,13 @@ log_preflush_pool_modified_pages( recv_apply_hashed_log_recs(TRUE); } + retry: n_pages = buf_flush_list(ULINT_MAX, new_oldest); - if (sync) { - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + if (sync && n_pages != 0) { + //buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); + os_thread_sleep(100000); + goto retry; } if (n_pages == ULINT_UNDEFINED) { @@ -2020,6 +2023,13 @@ log_checkpoint( { ib_uint64_t oldest_lsn; +#ifdef UNIV_DEBUG + if (srv_flush_checkpoint_debug == 1) { + + return TRUE; + } +#endif + if (recv_recovery_is_on()) { recv_apply_hashed_log_recs(TRUE); } @@ -2124,7 +2134,11 @@ log_make_checkpoint_at( physical write will always be made to log files */ { - /* Preflush pages synchronously */ +#ifdef UNIV_DEBUG + if (srv_flush_checkpoint_debug == 1) + return; +#endif +/* Preflush pages synchronously */ while (!log_preflush_pool_modified_pages(lsn, TRUE)); @@ -2216,7 +2230,13 @@ log_checkpoint_margin(void) ibool checkpoint_sync; ibool do_checkpoint; ibool success; -loop: + +#ifdef UNIV_DEBUG + if (srv_flush_checkpoint_debug == 1) + return; +#endif + + loop: sync = FALSE; checkpoint_sync = FALSE; do_checkpoint = FALSE; @@ -2239,13 +2259,15 @@ loop: /* A flush is urgent: we have to do a synchronous preflush */ sync = TRUE; - advance = 2 * (age - log->max_modified_age_sync); + advance = age - log->max_modified_age_sync; } else if (age > log_max_modified_age_async()) { /* A flush is not urgent: we do an asynchronous preflush */ advance = age - log_max_modified_age_async(); + log->check_flush_or_checkpoint = FALSE; } else { advance = 0; + log->check_flush_or_checkpoint = FALSE; } checkpoint_age = log->lsn - log->last_checkpoint_lsn; @@ -2262,9 +2284,9 @@ loop: do_checkpoint = TRUE; - log->check_flush_or_checkpoint = FALSE; + //log->check_flush_or_checkpoint = FALSE; } else { - log->check_flush_or_checkpoint = FALSE; + //log->check_flush_or_checkpoint = FALSE; } mutex_exit(&(log->mutex)); @@ -2272,6 +2294,7 @@ loop: if (advance) { ib_uint64_t new_oldest = oldest_lsn + advance; +retry: success = log_preflush_pool_modified_pages(new_oldest, sync); /* If the flush succeeded, this thread has done its part @@ -2286,7 +2309,7 @@ loop: log->check_flush_or_checkpoint = TRUE; mutex_exit(&(log->mutex)); - goto loop; + goto retry; } } @@ -3164,7 +3187,11 @@ void log_check_margins(void) /*===================*/ { -loop: +#ifdef UNIV_DEBUG + if (srv_flush_checkpoint_debug == 1) + return; +#endif + loop: log_flush_margin(); log_checkpoint_margin(); diff --git a/storage/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c index 17f6c6bbc36..4858929082a 100644 --- a/storage/xtradb/page/page0page.c +++ b/storage/xtradb/page/page0page.c @@ -215,12 +215,6 @@ page_set_max_trx_id( { page_t* page = buf_block_get_frame(block); #ifndef UNIV_HOTBACKUP - const ibool is_hashed = block->is_hashed; - - if (is_hashed) { - rw_lock_x_lock(btr_search_get_latch(block->index->id)); - } - ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); #endif /* !UNIV_HOTBACKUP */ @@ -241,12 +235,6 @@ page_set_max_trx_id( } else { mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id); } - -#ifndef UNIV_HOTBACKUP - if (is_hashed) { - rw_lock_x_unlock(btr_search_get_latch(block->index->id)); - } -#endif /* !UNIV_HOTBACKUP */ } /************************************************************//** @@ -1603,13 +1591,14 @@ page_rec_print( " n_owned: %lu; heap_no: %lu; next rec: %lu\n", (ulong) rec_get_n_owned_old(rec), (ulong) rec_get_heap_no_old(rec), - (ulong) rec_get_next_offs(rec, TRUE)); + (ulong) rec_get_next_offs(rec, FALSE)); } page_rec_check(rec); rec_validate(rec, offsets); } +# ifdef UNIV_BTR_PRINT /***************************************************************//** This is used to print the contents of the directory for debugging purposes. */ @@ -1770,6 +1759,7 @@ page_print( page_dir_print(page, dn); page_print_list(block, index, rn); } +# endif /* UNIV_BTR_PRINT */ #endif /* !UNIV_HOTBACKUP */ /***************************************************************//** diff --git a/storage/xtradb/page/page0zip.c b/storage/xtradb/page/page0zip.c index fc9f30ed94e..d4b0dd8339d 100644 --- a/storage/xtradb/page/page0zip.c +++ b/storage/xtradb/page/page0zip.c @@ -4456,7 +4456,7 @@ page_zip_reorganize( #ifndef UNIV_HOTBACKUP temp_block = buf_block_alloc(buf_pool); - btr_search_drop_page_hash_index(block, index); + btr_search_drop_page_hash_index(block); block->check_index_page_at_flush = TRUE; #else /* !UNIV_HOTBACKUP */ ut_ad(block == back_block1); diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index 9bda27e4b1f..adc75bd5760 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -437,11 +437,9 @@ row_ins_cascade_calc_update_vec( dict_table_t* table = foreign->foreign_table; dict_index_t* index = foreign->foreign_index; upd_t* update; - upd_field_t* ufield; dict_table_t* parent_table; dict_index_t* parent_index; upd_t* parent_update; - upd_field_t* parent_ufield; ulint n_fields_updated; ulint parent_field_no; ulint i; @@ -477,13 +475,15 @@ row_ins_cascade_calc_update_vec( dict_index_get_nth_col_no(parent_index, i)); for (j = 0; j < parent_update->n_fields; j++) { - parent_ufield = parent_update->fields + j; + const upd_field_t* parent_ufield + = &parent_update->fields[j]; if (parent_ufield->field_no == parent_field_no) { ulint min_size; const dict_col_t* col; ulint ufield_len; + upd_field_t* ufield; col = dict_index_get_nth_col(index, i); @@ -985,10 +985,9 @@ row_ins_foreign_check_on_constraint( goto nonstandard_exit_func; } - if ((node->is_delete - && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)) - || (!node->is_delete - && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) { + if (node->is_delete + ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) + : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) { /* Build the appropriate update vector which sets foreign->n_fields first fields in rec to SQL NULL */ @@ -997,6 +996,8 @@ row_ins_foreign_check_on_constraint( update->info_bits = 0; update->n_fields = foreign->n_fields; + UNIV_MEM_INVALID(update->fields, + update->n_fields * sizeof *update->fields); for (i = 0; i < foreign->n_fields; i++) { upd_field_t* ufield = &update->fields[i]; @@ -1665,7 +1666,7 @@ row_ins_scan_sec_index_for_duplicate( ulint n_fields_cmp; btr_pcur_t pcur; ulint err = DB_SUCCESS; - unsigned allow_duplicates; + ulint allow_duplicates; mtr_t mtr; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -1696,7 +1697,7 @@ row_ins_scan_sec_index_for_duplicate( btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); - allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE; + allow_duplicates = thr_get_trx(thr)->duplicates; /* Scan index records and check if there is a duplicate */ @@ -1830,7 +1831,7 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ - if (trx->duplicates & TRX_DUP_IGNORE) { + if (trx->duplicates) { /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1874,7 +1875,7 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); - if (trx->duplicates & TRX_DUP_IGNORE) { + if (trx->duplicates) { /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c index ac424ded6cb..63252ed01b3 100644 --- a/storage/xtradb/row/row0mysql.c +++ b/storage/xtradb/row/row0mysql.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -291,21 +291,21 @@ row_mysql_pad_col( /* space=0x0020 */ pad_end = pad + len; ut_a(!(len % 2)); - do { + while (pad < pad_end) { *pad++ = 0x00; *pad++ = 0x20; - } while (pad < pad_end); + }; break; case 4: /* space=0x00000020 */ pad_end = pad + len; ut_a(!(len % 4)); - do { + while (pad < pad_end) { *pad++ = 0x00; *pad++ = 0x00; *pad++ = 0x00; *pad++ = 0x20; - } while (pad < pad_end); + } break; } } @@ -2736,7 +2736,7 @@ row_import_tablespace_for_mysql( success = fil_open_single_table_tablespace( TRUE, table->space, table->flags == DICT_TF_COMPACT ? 0 : table->flags, - table->name); + table->name, trx); if (success) { table->ibd_file_missing = FALSE; table->tablespace_discarded = FALSE; @@ -4119,6 +4119,7 @@ end: trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); trx->error_state = DB_SUCCESS; + err = DB_ERROR; goto funct_exit; } diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index c7308ccb765..07608389d9a 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -3263,16 +3263,15 @@ row_sel_pop_cached_row_for_mysql( } /********************************************************************//** -Pushes a row for MySQL to the fetch cache. -@return TRUE on success, FALSE if the record contains incomplete BLOBs */ -UNIV_INLINE __attribute__((warn_unused_result)) -ibool -row_sel_push_cache_row_for_mysql( -/*=============================*/ - byte* mysql_rec, /*!< in/out: MySQL record */ +Get the last fetch cache buffer from the queue. +@return pointer to buffer. */ +UNIV_INLINE +byte* +row_sel_fetch_last_buf( +/*===================*/ row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */ { - ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE); + ut_a(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE); ut_a(!prebuilt->templ_contains_blob); if (UNIV_UNLIKELY(prebuilt->fetch_cache[0] == NULL)) { @@ -3301,15 +3300,28 @@ row_sel_push_cache_row_for_mysql( UNIV_MEM_INVALID(prebuilt->fetch_cache[prebuilt->n_fetch_cached], prebuilt->mysql_row_len); - memcpy(prebuilt->fetch_cache[prebuilt->n_fetch_cached], - mysql_rec, prebuilt->mysql_row_len); + return(prebuilt->fetch_cache[prebuilt->n_fetch_cached]); +} - if (++prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE) { - return(FALSE); +/********************************************************************//** +Pushes a row for MySQL to the fetch cache. */ +UNIV_INLINE +void +row_sel_push_cache_row_for_mysql( +/*=============================*/ + byte* mysql_rec, /*!< in/out: MySQL record */ + row_prebuilt_t* prebuilt) /*!< in/out: prebuilt struct */ +{ + /* For non ICP code path the row should already exist in the + next fetch cache slot. */ + + if (prebuilt->idx_cond != NULL) { + byte* dest = row_sel_fetch_last_buf(prebuilt); + + ut_memcpy(dest, mysql_rec, prebuilt->mysql_row_len); } - row_sel_pop_cached_row_for_mysql(mysql_rec, prebuilt); - return(TRUE); + ++prebuilt->n_fetch_cached; } /*********************************************************************//** @@ -3459,6 +3471,7 @@ row_search_idx_cond_check( } ut_error; + return(ICP_ABORTED_BY_USER); /* Keep compiler happy */ } /********************************************************************//** @@ -4735,9 +4748,16 @@ requires_clust_rec: not cache rows because there the cursor is a scrollable cursor. */ + ut_a(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE); + + /* We only convert from InnoDB row format to MySQL row + format when ICP is disabled. */ + if (!prebuilt->idx_cond - && !row_sel_store_mysql_rec(buf, prebuilt, result_rec, - result_rec != rec, offsets)) { + && !row_sel_store_mysql_rec( + row_sel_fetch_last_buf(prebuilt), + prebuilt, result_rec, + result_rec != rec, offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such records do not exist. Such records may only be @@ -4746,8 +4766,12 @@ requires_clust_rec: transaction. Rollback happens at a lower level, not here. */ goto next_rec; - } else if (row_sel_push_cache_row_for_mysql(buf, prebuilt)) { - goto next_rec; + } + + row_sel_push_cache_row_for_mysql(buf, prebuilt); + + if (prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE) { + goto next_rec; } } else { if (UNIV_UNLIKELY diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 0c07d75b39a..3476743a692 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -446,7 +446,7 @@ UNIV_INTERN ulong srv_ibuf_accel_rate = 100; #define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0))) UNIV_INTERN ulint srv_checkpoint_age_target = 0; -UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */ +UNIV_INTERN ulong srv_flush_neighbor_pages = 1; /* 0:disable 1:area 2:contiguous */ UNIV_INTERN ulint srv_deprecated_enable_unsafe_group_commit = 0; UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */ @@ -471,6 +471,9 @@ UNIV_INTERN ibool srv_print_lock_waits = FALSE; UNIV_INTERN ibool srv_print_buf_io = FALSE; UNIV_INTERN ibool srv_print_log_io = FALSE; UNIV_INTERN ibool srv_print_latch_waits = FALSE; + +UNIV_INTERN ulong srv_flush_checkpoint_debug = 0; + #endif /* UNIV_DEBUG */ UNIV_INTERN ulint srv_n_rows_inserted = 0; @@ -1253,7 +1256,7 @@ retry: static void srv_conc_exit_innodb_timer_based(trx_t* trx) { - (void) os_atomic_increment_lint(&srv_conc_n_threads, -1); + (void) os_atomic_increment_lint(&srv_conc_n_threads, -1); trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; return; @@ -1475,7 +1478,7 @@ srv_conc_force_enter_innodb( ut_ad(srv_conc_n_threads >= 0); #ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { - (void) os_atomic_increment_lint(&srv_conc_n_threads, 1); + (void) os_atomic_increment_lint(&srv_conc_n_threads, 1); trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = 1; return; @@ -3625,11 +3628,18 @@ retry_flush_batch: PCT_IO(10), IB_ULONGLONG_MAX); } - srv_main_thread_op_info = "making checkpoint"; +#ifdef UNIV_DEBUG + if (srv_flush_checkpoint_debug != 1) { +#endif - /* Make a new checkpoint about once in 10 seconds */ + srv_main_thread_op_info = "making checkpoint"; - log_checkpoint(TRUE, FALSE, TRUE); + /* Make a new checkpoint about once in 10 seconds */ + + log_checkpoint(TRUE, FALSE, TRUE); +#ifdef UNIV_DEBUG + } +#endif srv_main_thread_op_info = "reserving kernel mutex"; @@ -3708,6 +3718,10 @@ background_loop: } mutex_exit(&kernel_mutex); +#ifdef UNIV_DEBUG + if (srv_flush_checkpoint_debug == 1) + goto skip_flush; +#endif flush_loop: srv_main_thread_op_info = "flushing buffer pool pages"; srv_main_flush_loops++; @@ -3748,6 +3762,9 @@ flush_loop: goto flush_loop; } +#ifdef UNIV_DEBUG +skip_flush: +#endif srv_main_thread_op_info = "reserving kernel mutex"; mutex_enter(&kernel_mutex); diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c index 4083eb75b83..99916610c21 100644 --- a/storage/xtradb/srv/srv0start.c +++ b/storage/xtradb/srv/srv0start.c @@ -735,6 +735,7 @@ open_or_create_data_files( ibool one_created = FALSE; ulint size; ulint size_high; + ulint flags; ulint rounded_size_pages; char name[10000]; @@ -917,12 +918,31 @@ open_or_create_data_files( return(DB_ERROR); } skip_size_check: - fil_read_flushed_lsn_and_arch_log_no( - files[i], one_opened, + fil_read_first_page( + files[i], one_opened, &flags, #ifdef UNIV_LOG_ARCHIVE min_arch_log_no, max_arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ min_flushed_lsn, max_flushed_lsn); + + if (UNIV_PAGE_SIZE + != fsp_flags_get_page_size(flags)) { + + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: data file %s" + " uses page size %lu,\n", + name, + fsp_flags_get_page_size(flags)); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: but the only supported" + " page size in this release is=%lu\n", + (ulong) UNIV_PAGE_SIZE); + + return(DB_ERROR); + } + one_opened = TRUE; } else { /* We created the data file and now write it full of @@ -1060,8 +1080,8 @@ skip_size_check: (ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9); } - fil_read_flushed_lsn_and_arch_log_no( - files[i], one_opened, + fil_read_first_page( + files[i], one_opened, &flags, #ifdef UNIV_LOG_ARCHIVE min_arch_log_no, max_arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c index e561ae319a5..8884812d84d 100644 --- a/storage/xtradb/sync/sync0rw.c +++ b/storage/xtradb/sync/sync0rw.c @@ -623,6 +623,9 @@ rw_lock_x_lock_func( ibool spinning = FALSE; ut_ad(rw_lock_validate(lock)); +#ifdef UNIV_SYNC_DEBUG + ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); +#endif /* UNIV_SYNC_DEBUG */ i = 0; @@ -710,7 +713,7 @@ mutex. */ UNIV_INTERN void rw_lock_debug_mutex_enter(void) -/*==========================*/ +/*===========================*/ { loop: if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) { @@ -937,11 +940,13 @@ rw_lock_list_print_info( putc('\n', file); } + rw_lock_debug_mutex_enter(); info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(file, info); info = UT_LIST_GET_NEXT(list, info); } + rw_lock_debug_mutex_exit(); } #ifndef INNODB_RW_LOCKS_USE_ATOMICS mutex_exit(&(lock->mutex)); @@ -985,11 +990,13 @@ rw_lock_print( putc('\n', stderr); } + rw_lock_debug_mutex_enter(); info = UT_LIST_GET_FIRST(lock->debug_list); while (info != NULL) { rw_lock_debug_print(stderr, info); info = UT_LIST_GET_NEXT(list, info); } + rw_lock_debug_mutex_exit(); } } diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c index b38e2183b0f..d2c4617d65c 100644 --- a/storage/xtradb/sync/sync0sync.c +++ b/storage/xtradb/sync/sync0sync.c @@ -1222,7 +1222,6 @@ sync_thread_add_level( case SYNC_OUTER_ANY_LATCH: case SYNC_FILE_FORMAT_TAG: case SYNC_DOUBLEWRITE: - case SYNC_SEARCH_SYS_CONF: case SYNC_TRX_LOCK_HEAP: case SYNC_KERNEL: case SYNC_IBUF_BITMAP_MUTEX: diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index 94a287cba08..f826c9a6633 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -1,4 +1,4 @@ -SET(HEIDISQL_BASE_NAME "HeidiSQL_6.0_Portable") +SET(HEIDISQL_BASE_NAME "HeidiSQL_7.0_Portable") SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip") SET(HEIDISQL_URL "http://heidisql.googlecode.com/files/${HEIDISQL_ZIP}") SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME})