summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <timour@askmonty.org>2012-03-11 14:39:20 +0200
committerunknown <timour@askmonty.org>2012-03-11 14:39:20 +0200
commit8aebd44e0ea9c4ae6f573f1ece27b276452122b8 (patch)
treee2907ea46e4680c18b85dace99b5ea00d5735043
parentf92cfdb8a9ff7f8287239c39ce4735789a23e3df (diff)
downloadmariadb-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.result846
-rw-r--r--mysql-test/suite/rpl/r/rpl_stop_slave.result6
-rw-r--r--mysql-test/suite/rpl/t/rpl_stop_slave.test12
-rw-r--r--mysql-test/t/limit_rows_examined.test576
-rw-r--r--sql/lex.h1
-rw-r--r--sql/share/errmsg.txt3
-rw-r--r--sql/signal_handler.cc4
-rw-r--r--sql/sql_class.cc29
-rw-r--r--sql/sql_class.h44
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h16
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_select.cc95
-rw-r--r--sql/sql_union.cc25
-rw-r--r--sql/sql_view.cc11
-rw-r--r--sql/sql_yacc.yy15
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;
}