Commit 8aebd44e authored by unknown's avatar unknown

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.
parent f92cfdb8
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;
...@@ -14,7 +14,7 @@ include/stop_slave.inc ...@@ -14,7 +14,7 @@ include/stop_slave.inc
# Suspend the INSERT statement in current transaction on SQL thread. # Suspend the INSERT statement in current transaction on SQL thread.
# It guarantees that SQL thread is applying the transaction when # It guarantees that SQL thread is applying the transaction when
# STOP SLAVE command launchs. # STOP SLAVE command launchs.
SET GLOBAL debug= 'd,after_mysql_insert'; SET GLOBAL debug= '+d,after_mysql_insert,*';
include/start_slave.inc include/start_slave.inc
# CREATE TEMPORARY TABLE with InnoDB engine # CREATE TEMPORARY TABLE with InnoDB engine
...@@ -131,7 +131,6 @@ include/diff_tables.inc [master:t1, slave:t1] ...@@ -131,7 +131,6 @@ include/diff_tables.inc [master:t1, slave:t1]
START SLAVE SQL_THREAD; START SLAVE SQL_THREAD;
include/wait_for_slave_sql_to_start.inc include/wait_for_slave_sql_to_start.inc
# Test end # Test end
SET GLOBAL debug= '$debug_save';
include/restart_slave.inc include/restart_slave.inc
[connection master] [connection master]
DROP TABLE t1, t2; DROP TABLE t1, t2;
...@@ -151,7 +150,7 @@ CREATE TABLE t1 (c1 INT KEY, c2 INT) ENGINE=InnoDB; ...@@ -151,7 +150,7 @@ CREATE TABLE t1 (c1 INT KEY, c2 INT) ENGINE=InnoDB;
CREATE TABLE t2 (c1 INT) ENGINE=MyISAM; CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES(1, 1); INSERT INTO t1 VALUES(1, 1);
[connection master] [connection master]
SET GLOBAL debug= 'd,dump_thread_wait_before_send_xid'; SET GLOBAL debug= '+d,dump_thread_wait_before_send_xid,*';
[connection slave] [connection slave]
include/restart_slave.inc include/restart_slave.inc
BEGIN; BEGIN;
...@@ -176,5 +175,4 @@ include/wait_for_slave_to_stop.inc ...@@ -176,5 +175,4 @@ include/wait_for_slave_to_stop.inc
include/start_slave.inc include/start_slave.inc
[connection master] [connection master]
DROP TABLE t1, t2; DROP TABLE t1, t2;
SET GLOBAL debug= $debug_save;
include/rpl_end.inc include/rpl_end.inc
...@@ -23,7 +23,7 @@ source include/stop_slave.inc; ...@@ -23,7 +23,7 @@ source include/stop_slave.inc;
--echo # It guarantees that SQL thread is applying the transaction when --echo # It guarantees that SQL thread is applying the transaction when
--echo # STOP SLAVE command launchs. --echo # STOP SLAVE command launchs.
let $debug_save= `SELECT @@GLOBAL.debug`; 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; source include/start_slave.inc;
--echo --echo
...@@ -53,7 +53,9 @@ let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM ...@@ -53,7 +53,9 @@ let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM
source extra/rpl_tests/rpl_stop_slave.test; source extra/rpl_tests/rpl_stop_slave.test;
--echo # Test end --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/restart_slave_sql.inc;
--source include/rpl_connection_master.inc --source include/rpl_connection_master.inc
...@@ -81,7 +83,7 @@ sync_slave_with_master; ...@@ -81,7 +83,7 @@ sync_slave_with_master;
--source include/rpl_connection_master.inc --source include/rpl_connection_master.inc
let $debug_save= `SELECT @@GLOBAL.debug`; 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/rpl_connection_slave.inc
source include/restart_slave_sql.inc; source include/restart_slave_sql.inc;
...@@ -121,5 +123,7 @@ source include/start_slave.inc; ...@@ -121,5 +123,7 @@ source include/start_slave.inc;
--source include/rpl_connection_master.inc --source include/rpl_connection_master.inc
DROP TABLE t1, t2; 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 --source include/rpl_end.inc
#
# 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;
...@@ -204,6 +204,7 @@ static SYMBOL symbols[] = { ...@@ -204,6 +204,7 @@ static SYMBOL symbols[] = {
{ "EVENT", SYM(EVENT_SYM)}, { "EVENT", SYM(EVENT_SYM)},
{ "EVENTS", SYM(EVENTS_SYM)}, { "EVENTS", SYM(EVENTS_SYM)},
{ "EVERY", SYM(EVERY_SYM)}, { "EVERY", SYM(EVERY_SYM)},
{ "EXAMINED", SYM(EXAMINED_SYM)},
{ "EXECUTE", SYM(EXECUTE_SYM)}, { "EXECUTE", SYM(EXECUTE_SYM)},
{ "EXISTS", SYM(EXISTS)}, { "EXISTS", SYM(EXISTS)},
{ "EXIT", SYM(EXIT_SYM)}, { "EXIT", SYM(EXIT_SYM)},
......
...@@ -6296,4 +6296,5 @@ ER_INTERNAL_ERROR ...@@ -6296,4 +6296,5 @@ ER_INTERNAL_ERROR
eng "Internal error: '%-.192s'" eng "Internal error: '%-.192s'"
ER_SPATIAL_MUST_HAVE_GEOM_COL 42000 ER_SPATIAL_MUST_HAVE_GEOM_COL 42000
eng "A SPATIAL index may only contain a geometrical type column" 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."
...@@ -191,6 +191,10 @@ extern "C" sig_handler handle_fatal_signal(int sig) ...@@ -191,6 +191,10 @@ extern "C" sig_handler handle_fatal_signal(int sig)
case KILL_SERVER_HARD: case KILL_SERVER_HARD:
kreason= "KILL_SERVER"; kreason= "KILL_SERVER";
break; break;
case ABORT_QUERY:
case ABORT_QUERY_HARD:
kreason= "ABORT_QUERY";
break;
} }
my_safe_printf_stderr("%s", "\n" my_safe_printf_stderr("%s", "\n"
"Trying to get some variables.\n" "Trying to get some variables.\n"
......
...@@ -675,6 +675,7 @@ THD::THD() ...@@ -675,6 +675,7 @@ THD::THD()
first_successful_insert_id_in_cur_stmt(0), first_successful_insert_id_in_cur_stmt(0),
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE), stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
examined_row_count(0), examined_row_count(0),
accessed_rows_and_keys(0),
global_read_lock(0), global_read_lock(0),
global_disable_checkpoint(0), global_disable_checkpoint(0),
is_fatal_error(0), is_fatal_error(0),
...@@ -1373,26 +1374,31 @@ void THD::awake(killed_state state_to_set) ...@@ -1373,26 +1374,31 @@ void THD::awake(killed_state state_to_set)
int killed_errno(killed_state killed) int killed_errno(killed_state killed)
{ {
DBUG_ENTER("killed_errno");
DBUG_PRINT("enter", ("killed: %d", killed));
switch (killed) { switch (killed) {
case NOT_KILLED: case NOT_KILLED:
case KILL_HARD_BIT: case KILL_HARD_BIT:
return 0; // Probably wrong usage DBUG_RETURN(0); // Probably wrong usage
case KILL_BAD_DATA: case KILL_BAD_DATA:
case KILL_BAD_DATA_HARD: 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:
case KILL_CONNECTION_HARD: case KILL_CONNECTION_HARD:
case KILL_SYSTEM_THREAD: case KILL_SYSTEM_THREAD:
case KILL_SYSTEM_THREAD_HARD: case KILL_SYSTEM_THREAD_HARD:
return ER_CONNECTION_KILLED; DBUG_RETURN(ER_CONNECTION_KILLED);
case KILL_QUERY: case KILL_QUERY:
case KILL_QUERY_HARD: case KILL_QUERY_HARD:
return ER_QUERY_INTERRUPTED; DBUG_RETURN(ER_QUERY_INTERRUPTED);
case KILL_SERVER: case KILL_SERVER:
case KILL_SERVER_HARD: 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) ...@@ -1975,6 +1981,8 @@ int select_send::send_data(List<Item> &items)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
return 0; return 0;
} }
if (thd->killed == ABORT_QUERY)
return 0;
/* /*
We may be passing the control from mysqld to the client: release the 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) ...@@ -2293,6 +2301,8 @@ int select_export::send_data(List<Item> &items)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
row_count++; row_count++;
Item *item; Item *item;
uint used_length=0,items_left=items.elements; uint used_length=0,items_left=items.elements;
...@@ -2548,6 +2558,9 @@ int select_dump::send_data(List<Item> &items) ...@@ -2548,6 +2558,9 @@ int select_dump::send_data(List<Item> &items)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
if (row_count++ > 1) if (row_count++ > 1)
{ {
my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); 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) ...@@ -2594,6 +2607,8 @@ int select_singlerow_subselect::send_data(List<Item> &items)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
List_iterator_fast<Item> li(items); List_iterator_fast<Item> li(items);
Item *val_item; Item *val_item;
for (uint i= 0; (val_item= li++); i++) for (uint i= 0; (val_item= li++); i++)
...@@ -2737,6 +2752,8 @@ int select_exists_subselect::send_data(List<Item> &items) ...@@ -2737,6 +2752,8 @@ int select_exists_subselect::send_data(List<Item> &items)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
it->value= 1; it->value= 1;
it->assigned(1); it->assigned(1);
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -365,7 +365,10 @@ public: ...@@ -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 enum killed_state
{ {
NOT_KILLED= 0, NOT_KILLED= 0,
...@@ -374,16 +377,24 @@ enum killed_state ...@@ -374,16 +377,24 @@ enum killed_state
KILL_BAD_DATA_HARD= 3, KILL_BAD_DATA_HARD= 3,
KILL_QUERY= 4, KILL_QUERY= 4,
KILL_QUERY_HARD= 5, 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 All of the following killed states will kill the connection
KILL_CONNECTION must be the first of these! KILL_CONNECTION must be the first of these and it must start with
*/ an even number (becasue of HARD bit)!
KILL_CONNECTION= 6, */
KILL_CONNECTION_HARD= 7, KILL_CONNECTION= 8,
KILL_SYSTEM_THREAD= 8, KILL_CONNECTION_HARD= 9,
KILL_SYSTEM_THREAD_HARD= 9, KILL_SYSTEM_THREAD= 10,
KILL_SERVER= 10, KILL_SYSTEM_THREAD_HARD= 11,
KILL_SERVER_HARD= 11 KILL_SERVER= 12,
KILL_SERVER_HARD= 13
}; };
extern int killed_errno(killed_state killed); extern int killed_errno(killed_state killed);
...@@ -1951,6 +1962,20 @@ public: ...@@ -1951,6 +1962,20 @@ public:
filesort() before reading it for e.g. update. filesort() before reading it for e.g. update.
*/ */
ha_rows examined_row_count; 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; USER_CONN *user_connect;
CHARSET_INFO *db_charset; CHARSET_INFO *db_charset;
...@@ -3643,6 +3668,7 @@ void mark_transaction_to_rollback(THD *thd, bool all); ...@@ -3643,6 +3668,7 @@ void mark_transaction_to_rollback(THD *thd, bool all);
inline void handler::increment_statistics(ulong SSV::*offset) const inline void handler::increment_statistics(ulong SSV::*offset) const
{ {
status_var_increment(table->in_use->status_var.*offset); 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 inline void handler::decrement_statistics(ulong SSV::*offset) const
......
...@@ -3280,6 +3280,8 @@ int select_insert::send_data(List<Item> &values) ...@@ -3280,6 +3280,8 @@ int select_insert::send_data(List<Item> &values)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
store_values(values); store_values(values);
......
...@@ -363,6 +363,8 @@ void lex_start(THD *thd) ...@@ -363,6 +363,8 @@ void lex_start(THD *thd)
lex->is_lex_started= TRUE; lex->is_lex_started= TRUE;
lex->used_tables= 0; lex->used_tables= 0;
lex->limit_rows_examined= 0;
lex->limit_rows_examined_cnt= ULONGLONG_MAX;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -1947,6 +1947,22 @@ typedef struct st_lex : public Query_tables_list ...@@ -1947,6 +1947,22 @@ typedef struct st_lex : public Query_tables_list
into the select_lex. into the select_lex.
*/ */
table_map used_tables; 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(); st_lex();
......
...@@ -5876,6 +5876,7 @@ void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat) ...@@ -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->total_warn_count=0; // Warnings for this query
thd->rand_used= 0; thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0; thd->sent_row_count= thd->examined_row_count= 0;
thd->accessed_rows_and_keys= 0;
/* Copy data for user stats */ /* Copy data for user stats */
if ((thd->userstat_running= calculate_userstat)) if ((thd->userstat_running= calculate_userstat))
......
...@@ -289,6 +289,21 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, ...@@ -289,6 +289,21 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
res|= thd->is_error(); res|= thd->is_error();
if (unlikely(res)) if (unlikely(res))
result->abort(); 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); DBUG_RETURN(res);
} }
...@@ -1682,6 +1697,19 @@ int JOIN::init_execution() ...@@ -1682,6 +1697,19 @@ int JOIN::init_execution()
DBUG_ASSERT(!(select_options & SELECT_DESCRIBE)); DBUG_ASSERT(!(select_options & SELECT_DESCRIBE));
initialized= true; 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 */ /* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp) if (need_tmp)
{ {
...@@ -15091,14 +15119,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -15091,14 +15119,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
error= NESTED_LOOP_NO_MORE_ROWS; error= NESTED_LOOP_NO_MORE_ROWS;
else else
error= sub_select(join,join_tab,0); 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); error= sub_select(join,join_tab,1);
if (error == NESTED_LOOP_QUERY_LIMIT) if (error == NESTED_LOOP_QUERY_LIMIT)
error= NESTED_LOOP_OK; /* select_limit used */ 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; error= NESTED_LOOP_OK;
if (table == NULL) // If sending data to client if (table == NULL) // If sending data to client
{ {
/* /*
...@@ -16652,11 +16680,6 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16652,11 +16680,6 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
TABLE *table=join->tmp_table; TABLE *table=join->tmp_table;
DBUG_ENTER("end_write"); 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) if (!end_of_records)
{ {
copy_fields(&join->tmp_table_param); copy_fields(&join->tmp_table_param);
...@@ -16701,11 +16724,15 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16701,11 +16724,15 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
join->do_send_rows=0; join->do_send_rows=0;
join->unit->select_limit_cnt = HA_POS_ERROR; join->unit->select_limit_cnt = HA_POS_ERROR;
DBUG_RETURN(NESTED_LOOP_OK);
} }
} }
} }
end: end:
if (join->thd->killed)
{
join->thd->send_kill_message();
DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */
}
DBUG_RETURN(NESTED_LOOP_OK); DBUG_RETURN(NESTED_LOOP_OK);
} }
...@@ -16723,11 +16750,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16723,11 +16750,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (end_of_records) if (end_of_records)
DBUG_RETURN(NESTED_LOOP_OK); 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++; join->found_records++;
copy_fields(&join->tmp_table_param); // Groups are copied twice. copy_fields(&join->tmp_table_param); // Groups are copied twice.
...@@ -16753,7 +16775,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16753,7 +16775,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->file->print_error(error,MYF(0)); /* purecov: inspected */ table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(NESTED_LOOP_ERROR); /* 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)), ...@@ -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->join_tab[join->top_join_tab_count-1].next_select=end_unique_update;
} }
join->send_records++; 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); DBUG_RETURN(NESTED_LOOP_OK);
} }
...@@ -16804,11 +16832,6 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16804,11 +16832,6 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (end_of_records) if (end_of_records)
DBUG_RETURN(NESTED_LOOP_OK); 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); init_tmptable_sum_functions(join->sum_funcs);
copy_fields(&join->tmp_table_param); // Groups are copied twice. 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)), ...@@ -16838,6 +16861,11 @@ end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ 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); DBUG_RETURN(NESTED_LOOP_OK);
} }
...@@ -16851,11 +16879,6 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16851,11 +16879,6 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
int idx= -1; int idx= -1;
DBUG_ENTER("end_write_group"); 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 || if (!join->first_record || end_of_records ||
(idx=test_if_group_changed(join->group_fields)) >= 0) (idx=test_if_group_changed(join->group_fields)) >= 0)
{ {
...@@ -16889,13 +16912,13 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16889,13 +16912,13 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(NESTED_LOOP_ERROR); DBUG_RETURN(NESTED_LOOP_ERROR);
} }
if (end_of_records) if (end_of_records)
DBUG_RETURN(NESTED_LOOP_OK); goto end;
} }
} }
else else
{ {
if (end_of_records) if (end_of_records)
DBUG_RETURN(NESTED_LOOP_OK); goto end;
join->first_record=1; join->first_record=1;
VOID(test_if_group_changed(join->group_fields)); VOID(test_if_group_changed(join->group_fields));
} }
...@@ -16908,13 +16931,19 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -16908,13 +16931,19 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(NESTED_LOOP_ERROR); DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure) if (join->procedure)
join->procedure->add(); join->procedure->add();
DBUG_RETURN(NESTED_LOOP_OK); goto end;
} }
} }
if (update_sum_func(join->sum_funcs)) if (update_sum_func(join->sum_funcs))
DBUG_RETURN(NESTED_LOOP_ERROR); DBUG_RETURN(NESTED_LOOP_ERROR);
if (join->procedure) if (join->procedure)
join->procedure->add(); 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); DBUG_RETURN(NESTED_LOOP_OK);
} }
...@@ -18561,6 +18590,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) ...@@ -18561,6 +18590,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
ulong reclength,offset; ulong reclength,offset;
uint field_count; uint field_count;
THD *thd= join->thd; THD *thd= join->thd;
DBUG_ENTER("remove_duplicates"); DBUG_ENTER("remove_duplicates");
entry->reginfo.lock_type=TL_WRITE; entry->reginfo.lock_type=TL_WRITE;
...@@ -18586,6 +18616,13 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) ...@@ -18586,6 +18616,13 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
offset(entry->record[0]) : 0); offset(entry->record[0]) : 0);
reclength=entry->s->reclength-offset; 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 free_io_cache(entry); // Safety
entry->file->info(HA_STATUS_VARIABLE); entry->file->info(HA_STATUS_VARIABLE);
if (entry->s->db_type() == heap_hton || if (entry->s->db_type() == heap_hton ||
...@@ -18599,6 +18636,8 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) ...@@ -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, error=remove_dup_with_compare(join->thd, entry, first_field, offset,
having); having);
if (join->select_lex != join->select_lex->master_unit()->fake_select_lex)
thd->lex->set_limit_rows_examined();
free_blobs(first_field); free_blobs(first_field);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
......
...@@ -57,6 +57,8 @@ int select_union::send_data(List<Item> &values) ...@@ -57,6 +57,8 @@ int select_union::send_data(List<Item> &values)
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
return 0; return 0;
} }
if (thd->killed == ABORT_QUERY)
return 0;
if (table->no_rows_with_nulls) if (table->no_rows_with_nulls)
table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT; table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT;
fill_record(thd, table->field, values, TRUE, FALSE); fill_record(thd, table->field, values, TRUE, FALSE);
...@@ -698,6 +700,20 @@ bool st_select_lex_unit::exec() ...@@ -698,6 +700,20 @@ bool st_select_lex_unit::exec()
add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong) add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong)
((table->file->stats.records - records_at_start))); ((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() ...@@ -706,6 +722,11 @@ bool st_select_lex_unit::exec()
{ {
List<Item_func_match> empty_list; List<Item_func_match> empty_list;
empty_list.empty(); 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 if (!thd->is_fatal_error) // Check if EOM
{ {
...@@ -726,7 +747,7 @@ bool st_select_lex_unit::exec() ...@@ -726,7 +747,7 @@ bool st_select_lex_unit::exec()
fake_select_lex->options, result))) fake_select_lex->options, result)))
{ {
fake_select_lex->table_list.empty(); fake_select_lex->table_list.empty();
DBUG_RETURN(TRUE); goto err;
} }
fake_select_lex->join->no_const_tables= TRUE; fake_select_lex->join->no_const_tables= TRUE;
...@@ -798,6 +819,8 @@ bool st_select_lex_unit::exec() ...@@ -798,6 +819,8 @@ bool st_select_lex_unit::exec()
} }
} }
thd->lex->current_select= lex_select_save; thd->lex->current_select= lex_select_save;
err:
thd->lex->set_limit_rows_examined();
DBUG_RETURN(saved_error); DBUG_RETURN(saved_error);
} }
......
...@@ -435,6 +435,17 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -435,6 +435,17 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
goto err; 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(); sp_cache_invalidate();
if (!lex->definer) if (!lex->definer)
......
...@@ -865,6 +865,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -865,6 +865,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EVENTS_SYM %token EVENTS_SYM
%token EVENT_SYM %token EVENT_SYM
%token EVERY_SYM /* SQL-2003-N */ %token EVERY_SYM /* SQL-2003-N */
%token EXAMINED_SYM
%token EXECUTE_SYM /* SQL-2003-R */ %token EXECUTE_SYM /* SQL-2003-R */
%token EXISTS /* SQL-2003-R */ %token EXISTS /* SQL-2003-R */
%token EXIT_SYM %token EXIT_SYM
...@@ -9620,6 +9621,7 @@ opt_limit_clause_init: ...@@ -9620,6 +9621,7 @@ opt_limit_clause_init:
SELECT_LEX *sel= lex->current_select; SELECT_LEX *sel= lex->current_select;
sel->offset_limit= 0; sel->offset_limit= 0;
sel->select_limit= 0; sel->select_limit= 0;
lex->limit_rows_examined= 0;
} }
| limit_clause {} | limit_clause {}
; ;
...@@ -9631,6 +9633,8 @@ opt_limit_clause: ...@@ -9631,6 +9633,8 @@ opt_limit_clause:
limit_clause: limit_clause:
LIMIT limit_options {} LIMIT limit_options {}
| LIMIT limit_options ROWS_SYM EXAMINED_SYM limit_rows_option {}
| LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option {}
; ;
limit_options: limit_options:
...@@ -9682,6 +9686,13 @@ limit_option: ...@@ -9682,6 +9686,13 @@ limit_option:
} }
; ;
limit_rows_option:
limit_option
{
LEX *lex=Lex;
lex->limit_rows_examined= $1;
}
delete_limit_clause: delete_limit_clause:
/* empty */ /* empty */
{ {
...@@ -9694,6 +9705,8 @@ delete_limit_clause: ...@@ -9694,6 +9705,8 @@ delete_limit_clause:
sel->select_limit= $2; sel->select_limit= $2;
sel->explicit_limit= 1; 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: int_num:
...@@ -12131,6 +12144,7 @@ keyword: ...@@ -12131,6 +12144,7 @@ keyword:
| DO_SYM {} | DO_SYM {}
| END {} | END {}
| EXECUTE_SYM {} | EXECUTE_SYM {}
| EXAMINED_SYM {}
| FLUSH_SYM {} | FLUSH_SYM {}
| HANDLER_SYM {} | HANDLER_SYM {}
| HELP_SYM {} | HELP_SYM {}
...@@ -13011,6 +13025,7 @@ handler: ...@@ -13011,6 +13025,7 @@ handler:
MYSQL_YYABORT; MYSQL_YYABORT;
lex->current_select->select_limit= one; lex->current_select->select_limit= one;
lex->current_select->offset_limit= 0; lex->current_select->offset_limit= 0;
lex->limit_rows_examined= 0;
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment