diff options
author | unknown <timour@askmonty.org> | 2012-03-11 14:39:20 +0200 |
---|---|---|
committer | unknown <timour@askmonty.org> | 2012-03-11 14:39:20 +0200 |
commit | 8aebd44e0ea9c4ae6f573f1ece27b276452122b8 (patch) | |
tree | e2907ea46e4680c18b85dace99b5ea00d5735043 | |
parent | f92cfdb8a9ff7f8287239c39ce4735789a23e3df (diff) | |
download | mariadb-git-8aebd44e0ea9c4ae6f573f1ece27b276452122b8.tar.gz |
Implementation of MDEV-28 LIMIT ROWS EXAMINED
https://mariadb.atlassian.net/browse/MDEV-28
This task implements a new clause LIMIT ROWS EXAMINED <num>
as an extention to the ANSI LIMIT clause. This extension
allows to limit the number of rows and/or keys a query
would access (read and/or write) during query execution.
-rw-r--r-- | mysql-test/r/limit_rows_examined.result | 846 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_stop_slave.result | 6 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_stop_slave.test | 12 | ||||
-rw-r--r-- | mysql-test/t/limit_rows_examined.test | 576 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 3 | ||||
-rw-r--r-- | sql/signal_handler.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.cc | 29 | ||||
-rw-r--r-- | sql/sql_class.h | 44 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 16 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 95 | ||||
-rw-r--r-- | sql/sql_union.cc | 25 | ||||
-rw-r--r-- | sql/sql_view.cc | 11 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 15 |
17 files changed, 1635 insertions, 53 deletions
diff --git a/mysql-test/r/limit_rows_examined.result b/mysql-test/r/limit_rows_examined.result new file mode 100644 index 00000000000..19905746398 --- /dev/null +++ b/mysql-test/r/limit_rows_examined.result @@ -0,0 +1,846 @@ +set @save_join_cache_level = @@join_cache_level; +create table t1 (c1 char(2)); +create table t2 (c2 char(2)); +insert into t1 values ('bb'), ('cc'), ('aa'), ('dd'); +insert into t2 values ('bb'), ('cc'), ('dd'), ('ff'); +create table t1i (c1 char(2) key); +create table t2i (c2 char(2) key); +insert into t1i values ('bb'), ('cc'), ('aa'), ('dd'); +insert into t2i values ('bb'), ('cc'), ('dd'), ('ff'); +========================================================================= +Simple joins +========================================================================= +Simple nested loops join without blocking +set @@join_cache_level=0; +explain +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 2; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 3 rows, which exceeds LIMIT ROWS EXAMINED (2). The query result may be incomplete. +explain +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1i index PRIMARY PRIMARY 2 NULL 4 Using index +1 SIMPLE t2i eq_ref PRIMARY PRIMARY 2 test.t1i.c1 1 Using index +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 4; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 5 rows, which exceeds LIMIT ROWS EXAMINED (4). The query result may be incomplete. +Blocked nested loops join, empty result set because of blocking +set @@join_cache_level=1; +explain +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join) +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +explain +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1i index PRIMARY PRIMARY 2 NULL 4 Using index +1 SIMPLE t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +set @@join_cache_level=6; +explain +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +1 SIMPLE t2 hash_ALL NULL #hash#$hj 3 test.t1.c1 4 Using where; Using join buffer (flat, BNLH join) +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 3; +c1 c2 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 4 rows, which exceeds LIMIT ROWS EXAMINED (3). The query result may be incomplete. +explain +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1i index PRIMARY PRIMARY 2 NULL 4 Using index +1 SIMPLE t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +Mix LIMIT ROWS EXAMINED with LIMIT +set @@join_cache_level=0; +explain +select * from t1, t2 where c1 < c2 LIMIT 1 ROWS EXAMINED 4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1, t2 where c1 < c2 LIMIT 1 ROWS EXAMINED 4; +c1 c2 +bb cc +explain +select * from t1, t2 where c1 < c2 LIMIT 1,1 ROWS EXAMINED 4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1, t2 where c1 < c2 LIMIT 1,1 ROWS EXAMINED 4; +c1 c2 +bb dd +Empty table optimized away during constant optimization +create table t0 (c0 int); +explain +select * from t0 LIMIT ROWS EXAMINED 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 system NULL NULL NULL NULL 0 const row not found +explain +select * from t0 LIMIT ROWS EXAMINED 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 system NULL NULL NULL NULL 0 const row not found +select * from t0 LIMIT ROWS EXAMINED 1; +c0 +drop table t0; +create table t0 (c0 char(2) primary key); +insert into t0 values ('bb'), ('cc'), ('aa'); +explain +select * from t0 where c0 = 'bb' LIMIT ROWS EXAMINED 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 const PRIMARY PRIMARY 2 const 1 Using index +select * from t0 where c0 = 'bb' LIMIT ROWS EXAMINED 0; +c0 +bb +explain +select * from t0, t1 where c0 = 'bb' and c1 > c0 LIMIT ROWS EXAMINED 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 const PRIMARY PRIMARY 2 const 1 Using index +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +select * from t0, t1 where c0 = 'bb' and c1 > c0 LIMIT ROWS EXAMINED 0; +c0 c1 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 2 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +set @@join_cache_level = @save_join_cache_level; +drop table t0; +========================================================================= +LIMIT ROWS EXAMINED with parameter argument +========================================================================= +set @@join_cache_level=0; +set @l = 2; +Prepared statement parameter +prepare st1 from "select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED ?"; +execute st1 using @l; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 3 rows, which exceeds LIMIT ROWS EXAMINED (2). The query result may be incomplete. +deallocate prepare st1; +User variable (not supported for LIMIT in MariaDB 5.3/MySQL 5.1) +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED @l; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@l' at line 1 +Stored procedure parameter (not supported for LIMIT in MariaDB 5.3/MySQL 5.1) +CREATE PROCEDURE test_limit_rows(l int) +BEGIN +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED l; +END| +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'l; +END' at line 3 +set @@join_cache_level = @save_join_cache_level; +========================================================================= +UNIONs (with several LIMIT ROWS EXAMINED clauses) +========================================================================= +(select * from t1, t2 where c1 = c2) +UNION +(select * from t1, t2 where c1 < c2) LIMIT ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6); +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0 +UNION +select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0) +LIMIT 1 ROWS EXAMINED 6; +c1 c2 +bb bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0) +LIMIT 2 ROWS EXAMINED 10; +c1 c2 +bb bb +cc cc +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (10). The query result may be incomplete. +========================================================================= +Subqueries (with several LIMIT ROWS EXAMINED clauses) +========================================================================= +Subqueries, semi-join +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 11); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 2 func 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 11); +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (11). The query result may be incomplete. +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 11; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 2 func 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 11; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (11). The query result may be incomplete. +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 11; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 2 func 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 11; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (11). The query result may be incomplete. +explain +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 6; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index +1 PRIMARY t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 6; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +Subqueries with IN-TO-EXISTS +set @@optimizer_switch='semijoin=off,in_to_exists=on,materialization=off'; +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 4); +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 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 4); +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 5 rows, which exceeds LIMIT ROWS EXAMINED (4). The query result may be incomplete. +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 4; +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 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 4; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 5 rows, which exceeds LIMIT ROWS EXAMINED (4). The query result may be incomplete. +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 4; +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 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 4; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 5 rows, which exceeds LIMIT ROWS EXAMINED (4). The query result may be incomplete. +explain +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 9; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1i index NULL PRIMARY 2 NULL 4 Using where; Using index +2 DEPENDENT SUBQUERY t2i unique_subquery PRIMARY PRIMARY 2 func 1 Using index; Using where +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 9; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 10 rows, which exceeds LIMIT ROWS EXAMINED (9). The query result may be incomplete. +Same as above, without subquery cache +set @@optimizer_switch='subquery_cache=off'; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 2); +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 3 rows, which exceeds LIMIT ROWS EXAMINED (2). The query result may be incomplete. +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 2; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 3 rows, which exceeds LIMIT ROWS EXAMINED (2). The query result may be incomplete. +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 2; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 3 rows, which exceeds LIMIT ROWS EXAMINED (2). The query result may be incomplete. +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 5; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete. +Subqueries with materialization +set @@optimizer_switch='semijoin=off,in_to_exists=off,materialization=on,subquery_cache=on'; +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 13); +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 NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 13); +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 14 rows, which exceeds LIMIT ROWS EXAMINED (13). The query result may be incomplete. +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') LIMIT ROWS EXAMINED 13; +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 NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') LIMIT ROWS EXAMINED 13; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 14 rows, which exceeds LIMIT ROWS EXAMINED (13). The query result may be incomplete. +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 13; +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 NULL NULL NULL NULL 4 Using where +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 13; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 14 rows, which exceeds LIMIT ROWS EXAMINED (13). The query result may be incomplete. +explain +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') LIMIT ROWS EXAMINED 17; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1i index NULL PRIMARY 2 NULL 4 Using where; Using index +2 MATERIALIZED t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') LIMIT ROWS EXAMINED 17; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 18 rows, which exceeds LIMIT ROWS EXAMINED (17). The query result may be incomplete. +set @@optimizer_switch='default'; +========================================================================= +Views and derived tables +========================================================================= +create view v1 as +select * from t1 where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 13); +ERROR 42000: This version of MySQL doesn't yet support 'LIMIT ROWS EXAMINED inside views' +create view v1 as +select * from t1 where c1 IN (select * from t2 where c2 > ' '); +select * from v1; +c1 +bb +cc +dd +select * from v1 LIMIT ROWS EXAMINED 17; +c1 +bb +cc +dd +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 18 rows, which exceeds LIMIT ROWS EXAMINED (17). The query result may be incomplete. +select * from v1 LIMIT ROWS EXAMINED 16; +c1 +bb +cc +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 18 rows, which exceeds LIMIT ROWS EXAMINED (16). The query result may be incomplete. +select * from v1 LIMIT ROWS EXAMINED 11; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (11). The query result may be incomplete. +drop view v1; +explain +select * +from (select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0)) as tmp +LIMIT ROWS EXAMINED 11; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +select * +from (select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0)) as tmp +LIMIT ROWS EXAMINED 11; +c1 +bb +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (11). The query result may be incomplete. +========================================================================= +Aggregation +========================================================================= +create table t3 (c1 char(2), c2 int); +insert into t3 values +('aa', 1), ('aa', 2), +('bb', 3), ('bb', 4), ('bb', 5); +explain +select c1, sum(c2) from t3 group by c1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort +select c1, sum(c2) from t3 group by c1; +c1 sum(c2) +aa 3 +bb 12 +explain +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 0; +c1 sum(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 2 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 1; +ERROR HY000: Sort aborted +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 20; +c1 sum(c2) +aa 3 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 21 rows, which exceeds LIMIT ROWS EXAMINED (20). The query result may be incomplete. +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 21; +c1 sum(c2) +aa 3 +bb 12 +create table t3i (c1 char(2), c2 int); +create index it3i on t3i(c1); +create index it3j on t3i(c2,c1); +insert into t3i values +('aa', 1), ('aa', 2), +('bb', 3), ('bb', 4), ('bb', 5); +explain +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3i index NULL it3j 8 NULL 5 Using index; Using temporary; Using filesort +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 0; +c1 sum(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 2 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 1; +ERROR HY000: Sort aborted +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 20; +c1 sum(c2) +aa 3 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 21 rows, which exceeds LIMIT ROWS EXAMINED (20). The query result may be incomplete. +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 21; +c1 sum(c2) +aa 3 +bb 12 +Aggregation without grouping +explain +select min(c2) from t3 LIMIT ROWS EXAMINED 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 +select min(c2) from t3 LIMIT ROWS EXAMINED 5; +min(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete. +select max(c2) from t3 LIMIT ROWS EXAMINED 6; +max(c2) +5 +select max(c2) from t3 LIMIT ROWS EXAMINED 0; +max(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 1 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +explain +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 Using where +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +max(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete. +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 6; +max(c2) +NULL +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 0; +max(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 1 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +explain +select count(c2) from t3 LIMIT ROWS EXAMINED 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 +select count(c2) from t3 LIMIT ROWS EXAMINED 5; +count(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete. +select count(c2) from t3 LIMIT ROWS EXAMINED 6; +count(c2) +5 +select count(c2) from t3 LIMIT ROWS EXAMINED 0; +count(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 1 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +explain +select count(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 Using where +select count(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +count(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete. +select count(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 6; +count(c2) +0 +explain +select sum(c2) from t3 LIMIT ROWS EXAMINED 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 +select sum(c2) from t3 LIMIT ROWS EXAMINED 5; +sum(c2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 6 rows, which exceeds LIMIT ROWS EXAMINED (5). The query result may be incomplete. +select sum(c2) from t3 LIMIT ROWS EXAMINED 6; +sum(c2) +15 +The query result is found during optimization, LIMIT ROWS EXAMINED has no effect. +explain +select max(c1) from t3i LIMIT ROWS EXAMINED 0; +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 +select max(c1) from t3i LIMIT ROWS EXAMINED 0; +max(c1) +bb +create table t3_empty like t3; +explain +select max(c1) from t3_empty LIMIT ROWS EXAMINED 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3_empty system NULL NULL NULL NULL 0 const row not found +select max(c1) from t3_empty LIMIT ROWS EXAMINED 0; +max(c1) +NULL +drop table t3_empty; +========================================================================= +Sorting +========================================================================= +explain +select c1, c2 from t3 order by c2, c1 LIMIT ROWS EXAMINED 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 ALL NULL NULL NULL NULL 5 Using filesort +select c1, c2 from t3 order by c2, c1 LIMIT ROWS EXAMINED 2; +ERROR HY000: Sort aborted +explain +select c1, c2 from t3i order by c2, c1 LIMIT ROWS EXAMINED 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3i index NULL it3j 8 NULL 5 Using index +select c1, c2 from t3i order by c2, c1 LIMIT ROWS EXAMINED 2; +c1 c2 +aa 1 +aa 2 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 3 rows, which exceeds LIMIT ROWS EXAMINED (2). The query result may be incomplete. +explain +select c1, c2 from t3i order by c2, c1 desc LIMIT ROWS EXAMINED 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3i index NULL it3j 8 NULL 5 Using index; Using filesort +select c1, c2 from t3i order by c2, c1 desc LIMIT ROWS EXAMINED 2; +ERROR HY000: Sort aborted +drop table t3,t3i; +========================================================================= +INSERT/DELETE/UPDATE +========================================================================= +INSERT ... SELECT +CREATE TABLE t4 (a int); +INSERT INTO t4 values (1), (2); +INSERT INTO t4 SELECT a + 2 FROM t4 LIMIT ROWS EXAMINED 0; +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 2 rows, which exceeds LIMIT ROWS EXAMINED (0). The query result may be incomplete. +select * from t4; +a +1 +2 +INSERT INTO t4 SELECT a + 2 FROM t4 LIMIT ROWS EXAMINED 6; +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 8 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete. +select * from t4; +a +1 +2 +3 +drop table t4; +DELETE - LIMIT ROWS EXAMINED not supported +CREATE TABLE t4 (a int); +INSERT INTO t4 values (1), (2); +DELETE FROM t4 WHERE t4.a > 0 LIMIT ROWS EXAMINED 0; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXAMINED 0' at line 1 +DELETE FROM t4 WHERE t4.a > 0 LIMIT 0 ROWS EXAMINED 0; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXAMINED 0' at line 1 +drop table t4; +UPDATE - LIMIT ROWS EXAMINED not supported +CREATE TABLE t4 (a int); +INSERT INTO t4 values (1), (2); +update t4 set a=a+10 LIMIT ROWS EXAMINED 0; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXAMINED 0' at line 1 +update t4 set a=a+10 LIMIT 0 ROWS EXAMINED 0; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXAMINED 0' at line 1 +drop table t4; +drop table t1,t2,t1i,t2i; +========================================================================= +Test cases for bugs +========================================================================= + +MDEV-115 + +SET @@optimizer_switch='in_to_exists=on,outer_join_with_cache=on'; +CREATE TABLE t1 ( a VARCHAR(3) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('USA'); +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (3899),(3914),(3888); +CREATE TABLE t3 ( c VARCHAR(33), d INT ); +INSERT INTO t3 VALUES ('USASpanish',8),('USATagalog',0),('USAVietnamese',0); +EXPLAIN +SELECT DISTINCT a AS field1 FROM t1, t2 +WHERE EXISTS (SELECT c FROM t3 LEFT JOIN t2 ON b = d) +HAVING field1 > 8 LIMIT ROWS EXAMINED 20; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 Using temporary +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Distinct +2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 +2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +SELECT DISTINCT a AS field1 FROM t1, t2 +WHERE EXISTS (SELECT c FROM t3 LEFT JOIN t2 ON b = d) +HAVING field1 > 8 LIMIT ROWS EXAMINED 20; +field1 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 24 rows, which exceeds LIMIT ROWS EXAMINED (20). The query result may be incomplete. +EXPLAIN +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 14; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 Using temporary +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Distinct +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 14; +a +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 15 rows, which exceeds LIMIT ROWS EXAMINED (14). The query result may be incomplete. +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 15; +a +USA +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 16 rows, which exceeds LIMIT ROWS EXAMINED (15). The query result may be incomplete. +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 16; +a +USA +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 17 rows, which exceeds LIMIT ROWS EXAMINED (16). The query result may be incomplete. +drop table t1,t2,t3; +set @@optimizer_switch='default'; + +MDEV-153 + +CREATE TABLE t1 ( a TIME, b DATETIME, KEY(a), KEY(b) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES +('21:22:34.025509', '2002-02-13 17:30:06.013935'), +('10:50:38.059966', '2008-09-27 00:34:58.026613'), +('00:21:38.058143', '2007-05-28 00:00:00'); +CREATE TABLE t2 ( c INT, d TIME, e DATETIME, f VARCHAR(1), KEY(c) ) ENGINE=MyISAM; +INSERT INTO t2 VALUES +(0, '11:03:22.062907', '2007-06-02 11:16:01.053212', 'a'), +(0, '08:14:05.001407', '1900-01-01 00:00:00', 'm'), +(5, '19:03:16.024974', '1900-01-01 00:00:00', 'f'), +(1, '07:23:34.034234', '2000-11-26 05:01:11.054228', 'z'), +(6, '12:29:32.019411', '2006-02-13 00:00:00', 'f'), +(6, '06:07:10.010496', '2007-06-08 04:35:26.020373', 'a'), +(7, '22:55:09.020772', '2005-04-27 00:00:00', 'i'); +EXPLAIN +SELECT a AS field1, alias2.d AS field2, alias2.f AS field3, alias2.e AS field4, b AS field5 +FROM t1, t2 AS alias2, t2 AS alias3 +WHERE alias3.c IN ( SELECT 1 UNION SELECT 6 ) +GROUP BY field1, field2, field3, field4, field5 +LIMIT ROWS EXAMINED 120; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort +1 PRIMARY alias2 ALL NULL NULL NULL NULL 7 Using join buffer (flat, BNL join) +1 PRIMARY alias3 index NULL c 5 NULL 7 Using where; Using index; Using join buffer (incremental, BNL join) +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 +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL +FLUSH STATUS; +SELECT a AS field1, alias2.d AS field2, alias2.f AS field3, alias2.e AS field4, b AS field5 +FROM t1, t2 AS alias2, t2 AS alias3 +WHERE alias3.c IN ( SELECT 1 UNION SELECT 6 ) +GROUP BY field1, field2, field3, field4, field5 +LIMIT ROWS EXAMINED 120; +ERROR HY000: Sort aborted +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 4 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 52 +SHOW STATUS LIKE 'Handler_tmp%'; +Variable_name Value +Handler_tmp_update 0 +Handler_tmp_write 66 +FLUSH STATUS; +SELECT a AS field1, alias2.d AS field2, alias2.f AS field3, alias2.e AS field4, b AS field5 +FROM t1, t2 AS alias2, t2 AS alias3 +WHERE alias3.c IN ( SELECT 1 UNION SELECT 6 ) +GROUP BY field1, field2, field3, field4, field5 +LIMIT ROWS EXAMINED 250; +field1 field2 field3 field4 field5 +00:21:38 06:07:10 a 2007-06-08 04:35:26 2007-05-28 00:00:00 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 251 rows, which exceeds LIMIT ROWS EXAMINED (250). The query result may be incomplete. +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 5 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 2 +Handler_read_rnd_deleted 1 +Handler_read_rnd_next 110 +SHOW STATUS LIKE 'Handler_tmp%'; +Variable_name Value +Handler_tmp_update 0 +Handler_tmp_write 133 +drop table t1, t2; + +MDEV-161 LIMIT_ROWS EXAMINED: query with the limit and NOT EXISTS, without GROUP BY or aggregate, +returns rows, while the same query without the limit returns empty set + +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES (3911,17),(3847,33),(3857,26); +CREATE TABLE t2 ( c VARCHAR(16) ); +INSERT INTO t2 VALUES ('English'),('French'),('German'); +CREATE TABLE t3 ( d INT, e VARCHAR(32) ); +INSERT INTO t3 VALUES (3813,'United States'),(3814,'United States'); +SELECT * FROM t1 AS alias1, t2 AS alias2 +WHERE NOT EXISTS ( +SELECT * FROM t1 LEFT OUTER JOIN t3 +ON (d = a) +WHERE b <= alias1.b OR e != alias2.c +); +a b c +SELECT * FROM t1 AS alias1, t2 AS alias2 +WHERE NOT EXISTS ( +SELECT * FROM t1 LEFT OUTER JOIN t3 +ON (d = a) +WHERE b <= alias1.b OR e != alias2.c +) LIMIT ROWS EXAMINED 20; +a b c +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 25 rows, which exceeds LIMIT ROWS EXAMINED (20). The query result may be incomplete. +drop table t1, t2, t3; + +MDEV-174: LIMIT ROWS EXAMINED: Assertion `0' failed in net_end_statement(THD*) +with subquery in SELECT, constant table, aggregate function + +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( b INT, c INT, KEY(c) ); +INSERT INTO t2 VALUES +(5, 0),(3, 4),(6, 1), +(5, 8),(4, 9),(8, 1); +SELECT (SELECT MAX(c) FROM t1, t2) +FROM t2 +WHERE c = (SELECT MAX(b) FROM t2) +LIMIT ROWS EXAMINED 3; +(SELECT MAX(c) FROM t1, t2) +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 10 rows, which exceeds LIMIT ROWS EXAMINED (3). The query result may be incomplete. +drop table t1, t2; + +MDEV-178: LIMIT ROWS EXAMINED: Assertion `0' failed in net_end_statement(THD*) on the +2nd PS execution, with DISTINCT, FROM subquery or view in SELECT, JOIN in nested subquery + +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (2),(3),(150); +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (2),(17),(3),(6); +CREATE VIEW v AS +SELECT DISTINCT * FROM t1 WHERE a > (SELECT COUNT(*) FROM t1, t2 WHERE a = b); +PREPARE ps FROM 'SELECT * FROM v LIMIT ROWS EXAMINED 21'; +EXECUTE ps; +a +3 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 22 rows, which exceeds LIMIT ROWS EXAMINED (21). The query result may be incomplete. +EXECUTE ps; +a +3 +Warnings: +Warning 1930 Query execution was interrupted. The query examined at least 22 rows, which exceeds LIMIT ROWS EXAMINED (21). The query result may be incomplete. +drop view v; +drop table t1, t2; diff --git a/mysql-test/suite/rpl/r/rpl_stop_slave.result b/mysql-test/suite/rpl/r/rpl_stop_slave.result index 56199b003c5..dfee3e38be7 100644 --- a/mysql-test/suite/rpl/r/rpl_stop_slave.result +++ b/mysql-test/suite/rpl/r/rpl_stop_slave.result @@ -14,7 +14,7 @@ include/stop_slave.inc # Suspend the INSERT statement in current transaction on SQL thread. # It guarantees that SQL thread is applying the transaction when # STOP SLAVE command launchs. -SET GLOBAL debug= 'd,after_mysql_insert'; +SET GLOBAL debug= '+d,after_mysql_insert,*'; include/start_slave.inc # CREATE TEMPORARY TABLE with InnoDB engine @@ -131,7 +131,6 @@ include/diff_tables.inc [master:t1, slave:t1] START SLAVE SQL_THREAD; include/wait_for_slave_sql_to_start.inc # Test end -SET GLOBAL debug= '$debug_save'; include/restart_slave.inc [connection master] DROP TABLE t1, t2; @@ -151,7 +150,7 @@ CREATE TABLE t1 (c1 INT KEY, c2 INT) ENGINE=InnoDB; CREATE TABLE t2 (c1 INT) ENGINE=MyISAM; INSERT INTO t1 VALUES(1, 1); [connection master] -SET GLOBAL debug= 'd,dump_thread_wait_before_send_xid'; +SET GLOBAL debug= '+d,dump_thread_wait_before_send_xid,*'; [connection slave] include/restart_slave.inc BEGIN; @@ -176,5 +175,4 @@ include/wait_for_slave_to_stop.inc include/start_slave.inc [connection master] DROP TABLE t1, t2; -SET GLOBAL debug= $debug_save; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave.test b/mysql-test/suite/rpl/t/rpl_stop_slave.test index 1502c694ea0..51a2d685b46 100644 --- a/mysql-test/suite/rpl/t/rpl_stop_slave.test +++ b/mysql-test/suite/rpl/t/rpl_stop_slave.test @@ -23,7 +23,7 @@ source include/stop_slave.inc; --echo # It guarantees that SQL thread is applying the transaction when --echo # STOP SLAVE command launchs. let $debug_save= `SELECT @@GLOBAL.debug`; -SET GLOBAL debug= 'd,after_mysql_insert'; +SET GLOBAL debug= '+d,after_mysql_insert,*'; source include/start_slave.inc; --echo @@ -53,7 +53,9 @@ let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM source extra/rpl_tests/rpl_stop_slave.test; --echo # Test end -SET GLOBAL debug= '$debug_save'; +--disable_query_log +eval SET GLOBAL debug= '$debug_save'; +--enable_query_log source include/restart_slave_sql.inc; --source include/rpl_connection_master.inc @@ -81,7 +83,7 @@ sync_slave_with_master; --source include/rpl_connection_master.inc let $debug_save= `SELECT @@GLOBAL.debug`; -SET GLOBAL debug= 'd,dump_thread_wait_before_send_xid'; +SET GLOBAL debug= '+d,dump_thread_wait_before_send_xid,*'; --source include/rpl_connection_slave.inc source include/restart_slave_sql.inc; @@ -121,5 +123,7 @@ source include/start_slave.inc; --source include/rpl_connection_master.inc DROP TABLE t1, t2; -SET GLOBAL debug= $debug_save; +--disable_query_log +eval SET GLOBAL debug= '$debug_save'; +--enable_query_log --source include/rpl_end.inc diff --git a/mysql-test/t/limit_rows_examined.test b/mysql-test/t/limit_rows_examined.test new file mode 100644 index 00000000000..a9fb42a3b41 --- /dev/null +++ b/mysql-test/t/limit_rows_examined.test @@ -0,0 +1,576 @@ +# +# Tests for LIMIT ROWS EXAMINED, MDEV-28 +# + +set @save_join_cache_level = @@join_cache_level; + +create table t1 (c1 char(2)); +create table t2 (c2 char(2)); + +insert into t1 values ('bb'), ('cc'), ('aa'), ('dd'); +insert into t2 values ('bb'), ('cc'), ('dd'), ('ff'); + +create table t1i (c1 char(2) key); +create table t2i (c2 char(2) key); + +insert into t1i values ('bb'), ('cc'), ('aa'), ('dd'); +insert into t2i values ('bb'), ('cc'), ('dd'), ('ff'); + +--echo ========================================================================= +--echo Simple joins +--echo ========================================================================= + +--echo Simple nested loops join without blocking +set @@join_cache_level=0; +explain +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 2; +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 2; + +explain +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 4; +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 4; + +--echo Blocked nested loops join, empty result set because of blocking +set @@join_cache_level=1; +explain +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 6; +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 6; + +explain +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; + +set @@join_cache_level=6; +explain +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 3; +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 3; + +explain +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; +select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; + +--echo Mix LIMIT ROWS EXAMINED with LIMIT +set @@join_cache_level=0; +explain +select * from t1, t2 where c1 < c2 LIMIT 1 ROWS EXAMINED 4; +select * from t1, t2 where c1 < c2 LIMIT 1 ROWS EXAMINED 4; + +explain +select * from t1, t2 where c1 < c2 LIMIT 1,1 ROWS EXAMINED 4; +select * from t1, t2 where c1 < c2 LIMIT 1,1 ROWS EXAMINED 4; + +--echo Empty table optimized away during constant optimization +create table t0 (c0 int); +explain +select * from t0 LIMIT ROWS EXAMINED 0; +explain +select * from t0 LIMIT ROWS EXAMINED 1; +select * from t0 LIMIT ROWS EXAMINED 1; +drop table t0; + +create table t0 (c0 char(2) primary key); +insert into t0 values ('bb'), ('cc'), ('aa'); + +explain +select * from t0 where c0 = 'bb' LIMIT ROWS EXAMINED 0; +select * from t0 where c0 = 'bb' LIMIT ROWS EXAMINED 0; + +explain +select * from t0, t1 where c0 = 'bb' and c1 > c0 LIMIT ROWS EXAMINED 0; +select * from t0, t1 where c0 = 'bb' and c1 > c0 LIMIT ROWS EXAMINED 0; + +set @@join_cache_level = @save_join_cache_level; +drop table t0; + +--echo ========================================================================= +--echo LIMIT ROWS EXAMINED with parameter argument +--echo ========================================================================= + +set @@join_cache_level=0; +set @l = 2; + +--echo Prepared statement parameter + +prepare st1 from "select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED ?"; +execute st1 using @l; +deallocate prepare st1; + +--echo User variable (not supported for LIMIT in MariaDB 5.3/MySQL 5.1) +--error 1064 +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED @l; + +--echo Stored procedure parameter (not supported for LIMIT in MariaDB 5.3/MySQL 5.1) + +DELIMITER |; +--error 1064 +CREATE PROCEDURE test_limit_rows(l int) +BEGIN + select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED l; +END| + +DELIMITER ;| + +set @@join_cache_level = @save_join_cache_level; + +--echo ========================================================================= +--echo UNIONs (with several LIMIT ROWS EXAMINED clauses) +--echo ========================================================================= +(select * from t1, t2 where c1 = c2) +UNION +(select * from t1, t2 where c1 < c2) LIMIT ROWS EXAMINED 6; + +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6); + +select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0 +UNION +select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 6; + +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 6; + +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0) +LIMIT 1 ROWS EXAMINED 6; + +(select * from t1, t2 where c1 = c2 LIMIT ROWS EXAMINED 0) +UNION +(select * from t1, t2 where c1 < c2 LIMIT ROWS EXAMINED 0) +LIMIT 2 ROWS EXAMINED 10; + + +--echo ========================================================================= +--echo Subqueries (with several LIMIT ROWS EXAMINED clauses) +--echo ========================================================================= + +--echo Subqueries, semi-join +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 11); +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 11); + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 11; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 11; + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 11; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 11; + +explain +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 6; +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 6; + +--echo Subqueries with IN-TO-EXISTS +set @@optimizer_switch='semijoin=off,in_to_exists=on,materialization=off'; + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 4); +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 4); + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 4; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 4; + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 4; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 4; + +explain +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 9; +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 9; + +--echo Same as above, without subquery cache +set @@optimizer_switch='subquery_cache=off'; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 2); + +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') +LIMIT ROWS EXAMINED 2; + +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 2; + +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') +LIMIT ROWS EXAMINED 5; + +--echo Subqueries with materialization +set @@optimizer_switch='semijoin=off,in_to_exists=off,materialization=on,subquery_cache=on'; + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 13); +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 13); + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') LIMIT ROWS EXAMINED 13; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ') LIMIT ROWS EXAMINED 13; + +explain +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 13; +select * from t1 +where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0) +LIMIT ROWS EXAMINED 13; + +explain +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') LIMIT ROWS EXAMINED 17; +select * from t1i +where c1 IN (select * from t2i where c2 > ' ') LIMIT ROWS EXAMINED 17; + +set @@optimizer_switch='default'; + +--echo ========================================================================= +--echo Views and derived tables +--echo ========================================================================= + +--error 1235 +create view v1 as +select * from t1 where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 13); + +create view v1 as +select * from t1 where c1 IN (select * from t2 where c2 > ' '); + +select * from v1; +select * from v1 LIMIT ROWS EXAMINED 17; +select * from v1 LIMIT ROWS EXAMINED 16; +select * from v1 LIMIT ROWS EXAMINED 11; + +drop view v1; + +explain +select * +from (select * from t1 + where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0)) as tmp +LIMIT ROWS EXAMINED 11; +select * +from (select * from t1 + where c1 IN (select * from t2 where c2 > ' ' LIMIT ROWS EXAMINED 0)) as tmp +LIMIT ROWS EXAMINED 11; + +--echo ========================================================================= +--echo Aggregation +--echo ========================================================================= +create table t3 (c1 char(2), c2 int); + +insert into t3 values +('aa', 1), ('aa', 2), +('bb', 3), ('bb', 4), ('bb', 5); + +explain +select c1, sum(c2) from t3 group by c1; +select c1, sum(c2) from t3 group by c1; + +explain +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 0; +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 0; +--error 1028 +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 1; +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 20; +select c1, sum(c2) from t3 group by c1 LIMIT ROWS EXAMINED 21; + +create table t3i (c1 char(2), c2 int); +create index it3i on t3i(c1); +create index it3j on t3i(c2,c1); + +insert into t3i values +('aa', 1), ('aa', 2), +('bb', 3), ('bb', 4), ('bb', 5); + +explain +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 0; +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 0; +--error 1028 +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 1; +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 20; +select c1, sum(c2) from t3i group by c1 LIMIT ROWS EXAMINED 21; + +--echo Aggregation without grouping + +explain +select min(c2) from t3 LIMIT ROWS EXAMINED 5; +select min(c2) from t3 LIMIT ROWS EXAMINED 5; +select max(c2) from t3 LIMIT ROWS EXAMINED 6; +select max(c2) from t3 LIMIT ROWS EXAMINED 0; + +explain +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 6; +select max(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 0; + +explain +select count(c2) from t3 LIMIT ROWS EXAMINED 5; +select count(c2) from t3 LIMIT ROWS EXAMINED 5; +select count(c2) from t3 LIMIT ROWS EXAMINED 6; +select count(c2) from t3 LIMIT ROWS EXAMINED 0; + +explain +select count(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +select count(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 5; +select count(c2) from t3 where c2 > 10 LIMIT ROWS EXAMINED 6; + +explain +select sum(c2) from t3 LIMIT ROWS EXAMINED 5; +select sum(c2) from t3 LIMIT ROWS EXAMINED 5; +select sum(c2) from t3 LIMIT ROWS EXAMINED 6; + +--echo The query result is found during optimization, LIMIT ROWS EXAMINED has no effect. +explain +select max(c1) from t3i LIMIT ROWS EXAMINED 0; +select max(c1) from t3i LIMIT ROWS EXAMINED 0; + +create table t3_empty like t3; +explain +select max(c1) from t3_empty LIMIT ROWS EXAMINED 0; +select max(c1) from t3_empty LIMIT ROWS EXAMINED 0; +drop table t3_empty; + +--echo ========================================================================= +--echo Sorting +--echo ========================================================================= + +explain +select c1, c2 from t3 order by c2, c1 LIMIT ROWS EXAMINED 2; +--error 1028 +select c1, c2 from t3 order by c2, c1 LIMIT ROWS EXAMINED 2; + +explain +select c1, c2 from t3i order by c2, c1 LIMIT ROWS EXAMINED 2; +select c1, c2 from t3i order by c2, c1 LIMIT ROWS EXAMINED 2; + +explain +select c1, c2 from t3i order by c2, c1 desc LIMIT ROWS EXAMINED 2; +--error 1028 +select c1, c2 from t3i order by c2, c1 desc LIMIT ROWS EXAMINED 2; + +drop table t3,t3i; + +--echo ========================================================================= +--echo INSERT/DELETE/UPDATE +--echo ========================================================================= + +--echo INSERT ... SELECT +CREATE TABLE t4 (a int); +INSERT INTO t4 values (1), (2); +INSERT INTO t4 SELECT a + 2 FROM t4 LIMIT ROWS EXAMINED 0; +select * from t4; +INSERT INTO t4 SELECT a + 2 FROM t4 LIMIT ROWS EXAMINED 6; +select * from t4; +drop table t4; + +--echo DELETE - LIMIT ROWS EXAMINED not supported +CREATE TABLE t4 (a int); +INSERT INTO t4 values (1), (2); +--error 1064 +DELETE FROM t4 WHERE t4.a > 0 LIMIT ROWS EXAMINED 0; +--error 1064 +DELETE FROM t4 WHERE t4.a > 0 LIMIT 0 ROWS EXAMINED 0; +drop table t4; + +--echo UPDATE - LIMIT ROWS EXAMINED not supported +CREATE TABLE t4 (a int); +INSERT INTO t4 values (1), (2); +--error 1064 +update t4 set a=a+10 LIMIT ROWS EXAMINED 0; +--error 1064 +update t4 set a=a+10 LIMIT 0 ROWS EXAMINED 0; +drop table t4; + +drop table t1,t2,t1i,t2i; + + +--echo ========================================================================= +--echo Test cases for bugs +--echo ========================================================================= + +--echo +--echo MDEV-115 +--echo + +SET @@optimizer_switch='in_to_exists=on,outer_join_with_cache=on'; + +CREATE TABLE t1 ( a VARCHAR(3) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('USA'); + +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (3899),(3914),(3888); + +CREATE TABLE t3 ( c VARCHAR(33), d INT ); +INSERT INTO t3 VALUES ('USASpanish',8),('USATagalog',0),('USAVietnamese',0); + +EXPLAIN +SELECT DISTINCT a AS field1 FROM t1, t2 +WHERE EXISTS (SELECT c FROM t3 LEFT JOIN t2 ON b = d) +HAVING field1 > 8 LIMIT ROWS EXAMINED 20; + +SELECT DISTINCT a AS field1 FROM t1, t2 +WHERE EXISTS (SELECT c FROM t3 LEFT JOIN t2 ON b = d) +HAVING field1 > 8 LIMIT ROWS EXAMINED 20; + +EXPLAIN +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 14; +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 14; + +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 15; +SELECT DISTINCT a FROM t1, t2 HAVING a > ' ' LIMIT ROWS EXAMINED 16; + +drop table t1,t2,t3; + +set @@optimizer_switch='default'; + +--echo +--echo MDEV-153 +--echo + +CREATE TABLE t1 ( a TIME, b DATETIME, KEY(a), KEY(b) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES + ('21:22:34.025509', '2002-02-13 17:30:06.013935'), + ('10:50:38.059966', '2008-09-27 00:34:58.026613'), + ('00:21:38.058143', '2007-05-28 00:00:00'); + +CREATE TABLE t2 ( c INT, d TIME, e DATETIME, f VARCHAR(1), KEY(c) ) ENGINE=MyISAM; +INSERT INTO t2 VALUES + (0, '11:03:22.062907', '2007-06-02 11:16:01.053212', 'a'), + (0, '08:14:05.001407', '1900-01-01 00:00:00', 'm'), + (5, '19:03:16.024974', '1900-01-01 00:00:00', 'f'), + (1, '07:23:34.034234', '2000-11-26 05:01:11.054228', 'z'), + (6, '12:29:32.019411', '2006-02-13 00:00:00', 'f'), + (6, '06:07:10.010496', '2007-06-08 04:35:26.020373', 'a'), + (7, '22:55:09.020772', '2005-04-27 00:00:00', 'i'); + +EXPLAIN +SELECT a AS field1, alias2.d AS field2, alias2.f AS field3, alias2.e AS field4, b AS field5 +FROM t1, t2 AS alias2, t2 AS alias3 +WHERE alias3.c IN ( SELECT 1 UNION SELECT 6 ) +GROUP BY field1, field2, field3, field4, field5 +LIMIT ROWS EXAMINED 120; + +FLUSH STATUS; +--error 1028 +SELECT a AS field1, alias2.d AS field2, alias2.f AS field3, alias2.e AS field4, b AS field5 +FROM t1, t2 AS alias2, t2 AS alias3 +WHERE alias3.c IN ( SELECT 1 UNION SELECT 6 ) +GROUP BY field1, field2, field3, field4, field5 +LIMIT ROWS EXAMINED 120; +SHOW STATUS LIKE 'Handler_read%'; +SHOW STATUS LIKE 'Handler_tmp%'; + +FLUSH STATUS; +SELECT a AS field1, alias2.d AS field2, alias2.f AS field3, alias2.e AS field4, b AS field5 +FROM t1, t2 AS alias2, t2 AS alias3 +WHERE alias3.c IN ( SELECT 1 UNION SELECT 6 ) +GROUP BY field1, field2, field3, field4, field5 +LIMIT ROWS EXAMINED 250; +SHOW STATUS LIKE 'Handler_read%'; +SHOW STATUS LIKE 'Handler_tmp%'; + +drop table t1, t2; + +--echo +--echo MDEV-161 LIMIT_ROWS EXAMINED: query with the limit and NOT EXISTS, without GROUP BY or aggregate, +--echo returns rows, while the same query without the limit returns empty set +--echo + +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES (3911,17),(3847,33),(3857,26); + +CREATE TABLE t2 ( c VARCHAR(16) ); +INSERT INTO t2 VALUES ('English'),('French'),('German'); + +CREATE TABLE t3 ( d INT, e VARCHAR(32) ); +INSERT INTO t3 VALUES (3813,'United States'),(3814,'United States'); + +SELECT * FROM t1 AS alias1, t2 AS alias2 +WHERE NOT EXISTS ( + SELECT * FROM t1 LEFT OUTER JOIN t3 + ON (d = a) + WHERE b <= alias1.b OR e != alias2.c +); + +SELECT * FROM t1 AS alias1, t2 AS alias2 +WHERE NOT EXISTS ( + SELECT * FROM t1 LEFT OUTER JOIN t3 + ON (d = a) + WHERE b <= alias1.b OR e != alias2.c +) LIMIT ROWS EXAMINED 20; + +drop table t1, t2, t3; + +--echo +--echo MDEV-174: LIMIT ROWS EXAMINED: Assertion `0' failed in net_end_statement(THD*) +--echo with subquery in SELECT, constant table, aggregate function +--echo + +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( b INT, c INT, KEY(c) ); +INSERT INTO t2 VALUES + (5, 0),(3, 4),(6, 1), + (5, 8),(4, 9),(8, 1); + +SELECT (SELECT MAX(c) FROM t1, t2) +FROM t2 +WHERE c = (SELECT MAX(b) FROM t2) +LIMIT ROWS EXAMINED 3; + +drop table t1, t2; + +--echo +--echo MDEV-178: LIMIT ROWS EXAMINED: Assertion `0' failed in net_end_statement(THD*) on the +--echo 2nd PS execution, with DISTINCT, FROM subquery or view in SELECT, JOIN in nested subquery +--echo + +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (2),(3),(150); +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (2),(17),(3),(6); + +CREATE VIEW v AS +SELECT DISTINCT * FROM t1 WHERE a > (SELECT COUNT(*) FROM t1, t2 WHERE a = b); + +PREPARE ps FROM 'SELECT * FROM v LIMIT ROWS EXAMINED 21'; + +EXECUTE ps; +EXECUTE ps; + +drop view v; +drop table t1, t2; diff --git a/sql/lex.h b/sql/lex.h index 5d7546dcdc9..79a6b815373 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -204,6 +204,7 @@ static SYMBOL symbols[] = { { "EVENT", SYM(EVENT_SYM)}, { "EVENTS", SYM(EVENTS_SYM)}, { "EVERY", SYM(EVERY_SYM)}, + { "EXAMINED", SYM(EXAMINED_SYM)}, { "EXECUTE", SYM(EXECUTE_SYM)}, { "EXISTS", SYM(EXISTS)}, { "EXIT", SYM(EXIT_SYM)}, diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index e8d9f8b8e01..3dcf0324637 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6296,4 +6296,5 @@ ER_INTERNAL_ERROR eng "Internal error: '%-.192s'" ER_SPATIAL_MUST_HAVE_GEOM_COL 42000 eng "A SPATIAL index may only contain a geometrical type column" - +ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT + eng "Query execution was interrupted. The query examined at least %llu rows, which exceeds LIMIT ROWS EXAMINED (%llu). The query result may be incomplete." diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 819b87e3fdc..de3a0cbddfd 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -191,6 +191,10 @@ extern "C" sig_handler handle_fatal_signal(int sig) case KILL_SERVER_HARD: kreason= "KILL_SERVER"; break; + case ABORT_QUERY: + case ABORT_QUERY_HARD: + kreason= "ABORT_QUERY"; + break; } my_safe_printf_stderr("%s", "\n" "Trying to get some variables.\n" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9a72b647261..7075b24c83c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -675,6 +675,7 @@ THD::THD() first_successful_insert_id_in_cur_stmt(0), stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE), examined_row_count(0), + accessed_rows_and_keys(0), global_read_lock(0), global_disable_checkpoint(0), is_fatal_error(0), @@ -1373,26 +1374,31 @@ void THD::awake(killed_state state_to_set) int killed_errno(killed_state killed) { + DBUG_ENTER("killed_errno"); + DBUG_PRINT("enter", ("killed: %d", killed)); + switch (killed) { case NOT_KILLED: case KILL_HARD_BIT: - return 0; // Probably wrong usage + DBUG_RETURN(0); // Probably wrong usage case KILL_BAD_DATA: case KILL_BAD_DATA_HARD: - return 0; // Not a real error + case ABORT_QUERY_HARD: + case ABORT_QUERY: + DBUG_RETURN(0); // Not a real error case KILL_CONNECTION: case KILL_CONNECTION_HARD: case KILL_SYSTEM_THREAD: case KILL_SYSTEM_THREAD_HARD: - return ER_CONNECTION_KILLED; + DBUG_RETURN(ER_CONNECTION_KILLED); case KILL_QUERY: case KILL_QUERY_HARD: - return ER_QUERY_INTERRUPTED; + DBUG_RETURN(ER_QUERY_INTERRUPTED); case KILL_SERVER: case KILL_SERVER_HARD: - return ER_SERVER_SHUTDOWN; + DBUG_RETURN(ER_SERVER_SHUTDOWN); } - return 0; // Keep compiler happy + DBUG_RETURN(0); // Keep compiler happy } @@ -1975,6 +1981,8 @@ int select_send::send_data(List<Item> &items) unit->offset_limit_cnt--; return 0; } + if (thd->killed == ABORT_QUERY) + return 0; /* We may be passing the control from mysqld to the client: release the @@ -2293,6 +2301,8 @@ int select_export::send_data(List<Item> &items) unit->offset_limit_cnt--; DBUG_RETURN(0); } + if (thd->killed == ABORT_QUERY) + DBUG_RETURN(0); row_count++; Item *item; uint used_length=0,items_left=items.elements; @@ -2548,6 +2558,9 @@ int select_dump::send_data(List<Item> &items) unit->offset_limit_cnt--; DBUG_RETURN(0); } + if (thd->killed == ABORT_QUERY) + DBUG_RETURN(0); + if (row_count++ > 1) { my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); @@ -2594,6 +2607,8 @@ int select_singlerow_subselect::send_data(List<Item> &items) unit->offset_limit_cnt--; DBUG_RETURN(0); } + if (thd->killed == ABORT_QUERY) + DBUG_RETURN(0); List_iterator_fast<Item> li(items); Item *val_item; for (uint i= 0; (val_item= li++); i++) @@ -2737,6 +2752,8 @@ int select_exists_subselect::send_data(List<Item> &items) unit->offset_limit_cnt--; DBUG_RETURN(0); } + if (thd->killed == ABORT_QUERY) + DBUG_RETURN(0); it->value= 1; it->assigned(1); DBUG_RETURN(0); diff --git a/sql/sql_class.h b/sql/sql_class.h index 20ca9bd47c5..7d1847711fa 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -365,7 +365,10 @@ public: }; -/* Note: these states are actually bit coded with HARD */ +/** + These states are bit coded with HARD. For each state there must be a pair + <state_even_num>, and <state_odd_num>_HARD. +*/ enum killed_state { NOT_KILLED= 0, @@ -375,15 +378,23 @@ enum killed_state KILL_QUERY= 4, KILL_QUERY_HARD= 5, /* + ABORT_QUERY signals to the query processor to stop execution ASAP without + issuing an error. Instead a warning is issued, and when possible a partial + query result is returned to the client. + */ + ABORT_QUERY= 6, + ABORT_QUERY_HARD= 7, + /* All of the following killed states will kill the connection - KILL_CONNECTION must be the first of these! - */ - KILL_CONNECTION= 6, - KILL_CONNECTION_HARD= 7, - KILL_SYSTEM_THREAD= 8, - KILL_SYSTEM_THREAD_HARD= 9, - KILL_SERVER= 10, - KILL_SERVER_HARD= 11 + KILL_CONNECTION must be the first of these and it must start with + an even number (becasue of HARD bit)! + */ + KILL_CONNECTION= 8, + KILL_CONNECTION_HARD= 9, + KILL_SYSTEM_THREAD= 10, + KILL_SYSTEM_THREAD_HARD= 11, + KILL_SERVER= 12, + KILL_SERVER_HARD= 13 }; extern int killed_errno(killed_state killed); @@ -1951,6 +1962,20 @@ public: filesort() before reading it for e.g. update. */ ha_rows examined_row_count; + /** + The number of rows and/or keys examined by the query, both read, + changed or written. + */ + ulonglong accessed_rows_and_keys; + /** + Check if the number of rows accessed by a statement exceeded + LIMIT ROWS EXAMINED. If so, signal the query engine to stop execution. + */ + void check_limit_rows_examined() + { + if (++accessed_rows_and_keys > lex->limit_rows_examined_cnt) + killed= ABORT_QUERY; + } USER_CONN *user_connect; CHARSET_INFO *db_charset; @@ -3643,6 +3668,7 @@ void mark_transaction_to_rollback(THD *thd, bool all); inline void handler::increment_statistics(ulong SSV::*offset) const { status_var_increment(table->in_use->status_var.*offset); + table->in_use->check_limit_rows_examined(); } inline void handler::decrement_statistics(ulong SSV::*offset) const diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a4943d5e13a..88702317513 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3280,6 +3280,8 @@ int select_insert::send_data(List<Item> &values) unit->offset_limit_cnt--; DBUG_RETURN(0); } + if (thd->killed == ABORT_QUERY) + DBUG_RETURN(0); thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields store_values(values); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4a69cd3b1fa..73e4f3bea1b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -363,6 +363,8 @@ void lex_start(THD *thd) lex->is_lex_started= TRUE; lex->used_tables= 0; + lex->limit_rows_examined= 0; + lex->limit_rows_examined_cnt= ULONGLONG_MAX; DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index cefa092a874..87b213b0db5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1947,6 +1947,22 @@ typedef struct st_lex : public Query_tables_list into the select_lex. */ table_map used_tables; + /** + Maximum number of rows and/or keys examined by the query, both read, + changed or written. This is the argument of LIMIT ROWS EXAMINED. + The limit is represented by two variables - the Item is needed because + in case of parameters we have to delay its evaluation until execution. + Once evaluated, its value is stored in examined_rows_limit_cnt. + */ + Item *limit_rows_examined; + ulonglong limit_rows_examined_cnt; + inline void set_limit_rows_examined() + { + if (limit_rows_examined) + limit_rows_examined_cnt= limit_rows_examined->val_uint(); + else + limit_rows_examined_cnt= ULONGLONG_MAX; + } st_lex(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e84750369f9..5ab40021732 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5876,6 +5876,7 @@ void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat) thd->total_warn_count=0; // Warnings for this query thd->rand_used= 0; thd->sent_row_count= thd->examined_row_count= 0; + thd->accessed_rows_and_keys= 0; /* Copy data for user stats */ if ((thd->userstat_running= calculate_userstat)) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 437833eb90c..b2c75437b88 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -289,6 +289,21 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, res|= thd->is_error(); if (unlikely(res)) result->abort(); + if (thd->killed == ABORT_QUERY) + { + /* + If LIMIT ROWS EXAMINED interrupted query execution, issue a warning, + continue with normal processing and produce an incomplete query result. + */ + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT, + ER(ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT), + thd->accessed_rows_and_keys, + thd->lex->limit_rows_examined->val_uint()); + thd->killed= NOT_KILLED; + } + /* Disable LIMIT ROWS EXAMINED after query execution. */ + thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; DBUG_RETURN(res); } @@ -1682,6 +1697,19 @@ int JOIN::init_execution() DBUG_ASSERT(!(select_options & SELECT_DESCRIBE)); initialized= true; + /* + Enable LIMIT ROWS EXAMINED during query execution if: + (1) This JOIN is the outermost query (not a subquery or derived table) + This ensures that the limit is enabled when actual execution begins, and + not if a subquery is evaluated during optimization of the outer query. + (2) This JOIN is not the result of a UNION. In this case do not apply the + limit in order to produce the partial query result stored in the + UNION temp table. + */ + if (!select_lex->outer_select() && // (1) + select_lex != select_lex->master_unit()->fake_select_lex) // (2) + thd->lex->set_limit_rows_examined(); + /* Create a tmp table if distinct or if the sort is too complicated */ if (need_tmp) { @@ -15091,14 +15119,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) error= NESTED_LOOP_NO_MORE_ROWS; else error= sub_select(join,join_tab,0); - if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS) + if ((error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS) && + join->thd->killed != ABORT_QUERY) error= sub_select(join,join_tab,1); if (error == NESTED_LOOP_QUERY_LIMIT) error= NESTED_LOOP_OK; /* select_limit used */ } - if (error == NESTED_LOOP_NO_MORE_ROWS) + if (error == NESTED_LOOP_NO_MORE_ROWS || join->thd->killed == ABORT_QUERY) error= NESTED_LOOP_OK; - if (table == NULL) // If sending data to client { /* @@ -16652,11 +16680,6 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), TABLE *table=join->tmp_table; DBUG_ENTER("end_write"); - if (join->thd->killed) // Aborted by user - { - join->thd->send_kill_message(); - DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ - } if (!end_of_records) { copy_fields(&join->tmp_table_param); @@ -16701,11 +16724,15 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); join->do_send_rows=0; join->unit->select_limit_cnt = HA_POS_ERROR; - DBUG_RETURN(NESTED_LOOP_OK); } } } end: + if (join->thd->killed) + { + join->thd->send_kill_message(); + DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ + } DBUG_RETURN(NESTED_LOOP_OK); } @@ -16723,11 +16750,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (end_of_records) DBUG_RETURN(NESTED_LOOP_OK); - if (join->thd->killed) // Aborted by user - { - join->thd->send_kill_message(); - DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ - } join->found_records++; copy_fields(&join->tmp_table_param); // Groups are copied twice. @@ -16753,7 +16775,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), table->file->print_error(error,MYF(0)); /* purecov: inspected */ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ } - DBUG_RETURN(NESTED_LOOP_OK); + goto end; } /* @@ -16788,6 +16810,12 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), join->join_tab[join->top_join_tab_count-1].next_select=end_unique_update; } join->send_records++; +end: + if (join->thd->killed) + { + join->thd->send_kill_message(); + DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ + } DBUG_RETURN(NESTED_LOOP_OK); } @@ -16804,11 +16832,6 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (end_of_records) DBUG_RETURN(NESTED_LOOP_OK); - if (join->thd->killed) // Aborted by user - { - join->thd->send_kill_message(); - DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ - } init_tmptable_sum_functions(join->sum_funcs); copy_fields(&join->tmp_table_param); // Groups are copied twice. @@ -16838,6 +16861,11 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ } } + if (join->thd->killed) + { + join->thd->send_kill_message(); + DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ + } DBUG_RETURN(NESTED_LOOP_OK); } @@ -16851,11 +16879,6 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), int idx= -1; DBUG_ENTER("end_write_group"); - if (join->thd->killed) - { // Aborted by user - join->thd->send_kill_message(); - DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ - } if (!join->first_record || end_of_records || (idx=test_if_group_changed(join->group_fields)) >= 0) { @@ -16889,13 +16912,13 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), DBUG_RETURN(NESTED_LOOP_ERROR); } if (end_of_records) - DBUG_RETURN(NESTED_LOOP_OK); + goto end; } } else { if (end_of_records) - DBUG_RETURN(NESTED_LOOP_OK); + goto end; join->first_record=1; VOID(test_if_group_changed(join->group_fields)); } @@ -16908,13 +16931,19 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), DBUG_RETURN(NESTED_LOOP_ERROR); if (join->procedure) join->procedure->add(); - DBUG_RETURN(NESTED_LOOP_OK); + goto end; } } if (update_sum_func(join->sum_funcs)) DBUG_RETURN(NESTED_LOOP_ERROR); if (join->procedure) join->procedure->add(); +end: + if (join->thd->killed) + { + join->thd->send_kill_message(); + DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ + } DBUG_RETURN(NESTED_LOOP_OK); } @@ -18561,6 +18590,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) ulong reclength,offset; uint field_count; THD *thd= join->thd; + DBUG_ENTER("remove_duplicates"); entry->reginfo.lock_type=TL_WRITE; @@ -18586,6 +18616,13 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) offset(entry->record[0]) : 0); reclength=entry->s->reclength-offset; + /* + Disable LIMIT ROWS EXAMINED in order to avoid interrupting prematurely + duplicate removal, and produce a possibly incomplete query result. + */ + thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; + if (thd->killed == ABORT_QUERY) + thd->killed= NOT_KILLED; free_io_cache(entry); // Safety entry->file->info(HA_STATUS_VARIABLE); if (entry->s->db_type() == heap_hton || @@ -18599,6 +18636,8 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) error=remove_dup_with_compare(join->thd, entry, first_field, offset, having); + if (join->select_lex != join->select_lex->master_unit()->fake_select_lex) + thd->lex->set_limit_rows_examined(); free_blobs(first_field); DBUG_RETURN(error); } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 5c235fd1778..69a1cb2645a 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -57,6 +57,8 @@ int select_union::send_data(List<Item> &values) unit->offset_limit_cnt--; return 0; } + if (thd->killed == ABORT_QUERY) + return 0; if (table->no_rows_with_nulls) table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT; fill_record(thd, table->field, values, TRUE, FALSE); @@ -698,6 +700,20 @@ bool st_select_lex_unit::exec() add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong) ((table->file->stats.records - records_at_start))); } + if (thd->killed == ABORT_QUERY) + { + /* + Stop execution of the remaining queries in the UNIONS, and produce + the current result. + */ + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT, + ER(ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT), + thd->accessed_rows_and_keys, + thd->lex->limit_rows_examined->val_uint()); + thd->killed= NOT_KILLED; + break; + } } } @@ -706,6 +722,11 @@ bool st_select_lex_unit::exec() { List<Item_func_match> empty_list; empty_list.empty(); + /* + Disable LIMIT ROWS EXAMINED in order to produce the possibly incomplete + result of the UNION without interruption due to exceeding the limit. + */ + thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; if (!thd->is_fatal_error) // Check if EOM { @@ -726,7 +747,7 @@ bool st_select_lex_unit::exec() fake_select_lex->options, result))) { fake_select_lex->table_list.empty(); - DBUG_RETURN(TRUE); + goto err; } fake_select_lex->join->no_const_tables= TRUE; @@ -798,6 +819,8 @@ bool st_select_lex_unit::exec() } } thd->lex->current_select= lex_select_save; +err: + thd->lex->set_limit_rows_examined(); DBUG_RETURN(saved_error); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8760e936d36..4e89a4ce3d3 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -435,6 +435,17 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, goto err; } + if (lex->limit_rows_examined) + { + /* + LIMIT ROWS EXAMINED is not supported inside views to avoid complicated + side-effects and semantics of the clause. + */ + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LIMIT ROWS EXAMINED inside views"); + res= TRUE; + goto err; + } + sp_cache_invalidate(); if (!lex->definer) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 084314ff23f..6e383fedf71 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -865,6 +865,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token EVENTS_SYM %token EVENT_SYM %token EVERY_SYM /* SQL-2003-N */ +%token EXAMINED_SYM %token EXECUTE_SYM /* SQL-2003-R */ %token EXISTS /* SQL-2003-R */ %token EXIT_SYM @@ -9620,6 +9621,7 @@ opt_limit_clause_init: SELECT_LEX *sel= lex->current_select; sel->offset_limit= 0; sel->select_limit= 0; + lex->limit_rows_examined= 0; } | limit_clause {} ; @@ -9631,6 +9633,8 @@ opt_limit_clause: limit_clause: LIMIT limit_options {} + | LIMIT limit_options ROWS_SYM EXAMINED_SYM limit_rows_option {} + | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option {} ; limit_options: @@ -9682,6 +9686,13 @@ limit_option: } ; +limit_rows_option: + limit_option + { + LEX *lex=Lex; + lex->limit_rows_examined= $1; + } + delete_limit_clause: /* empty */ { @@ -9694,6 +9705,8 @@ delete_limit_clause: sel->select_limit= $2; sel->explicit_limit= 1; } + | LIMIT ROWS_SYM EXAMINED_SYM { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } + | LIMIT limit_option ROWS_SYM EXAMINED_SYM { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; } ; int_num: @@ -12131,6 +12144,7 @@ keyword: | DO_SYM {} | END {} | EXECUTE_SYM {} + | EXAMINED_SYM {} | FLUSH_SYM {} | HANDLER_SYM {} | HELP_SYM {} @@ -13011,6 +13025,7 @@ handler: MYSQL_YYABORT; lex->current_select->select_limit= one; lex->current_select->offset_limit= 0; + lex->limit_rows_examined= 0; if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) MYSQL_YYABORT; } |