From 9c89dd654e90d85fefc2459711063b680ed10f24 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Mar 2007 19:46:02 +0200 Subject: Bug #24484: To correctly decide which predicates can be evaluated with a given table the optimizer must know the exact set of tables that a predicate depends on. If that mask is too wide (refer to non-existing tables) the optimizer can erroneously skip a predicate. One such case of wrong table usage mask were the aggregate functions. The have a all-1 mask (meaning depend on all tables, including non-existent ones). Fixed by making a real used_tables mask for the aggregates. The mask is constructed in the following way : 1. OR the table dependency masks of all the arguments of the aggregate. 2. If all the arguments of the function are from the local name resolution context and it is evaluated in the same name resolution context where it is referenced all the tables from that name resolution context are OR-ed to the dependency mask. This is to denote that an aggregate function depends on the number of rows it processes. 3. Handle correctly the case of an aggregate function optimization (such that the aggregate function can be pre-calculated and made a constant). Made sure that an aggregate function is never a constant (unless subject of a specific optimization and pre-calculation). One other flaw was revealed and fixed in the process : references were not calling the recalculation method for used_tables of their targets. mysql-test/r/subselect3.result: Bug #24484: test case mysql-test/t/subselect3.test: Bug #24484: test case sql/item.h: Bug #24484: Item_ref must update the used tables. sql/item_sum.cc: Bug #24484: correct calculation of used_tables for aggregates. sql/item_sum.h: Bug #24484: correct calculation of used_tables for aggregates. sql/opt_range.cc: Bug #24484: fixed ref resolution in loose index scan sql/sql_base.cc: Bug #24484: moved counting of leaf tables inside setup_tables_and_check_access. sql/sql_class.h: Bug #24484: changed table count to more narrow type. sql/sql_insert.cc: Bug #24484: moved counting of leaf tables inside setup_tables_and_check_access. Substract the first table (and its subtables) of an INSERT statement from leaf_count. sql/sql_select.cc: Bug #24484: correct check for aggregates --- mysql-test/r/subselect3.result | 53 ++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/subselect3.test | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 29143b9e504..1320bc76222 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -645,3 +645,56 @@ a b Z 2 2 0 3 3 1 drop table t1,t2; +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t1 VALUES (1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), +(2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'),(3,3,'j'), (3,2,'k'), (3,1,'l'), +(1,9,'m'); +CREATE TABLE t2 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t2 SELECT * FROM t1; +SELECT a, MAX(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) +as test FROM t1 GROUP BY a; +a MAX(b) test +1 9 m +2 3 h +3 4 i +SELECT * FROM t1 GROUP by t1.a +HAVING (MAX(t1.b) > (SELECT MAX(t2.b) FROM t2 WHERE t2.c < t1.c +HAVING MAX(t2.b+t1.a) < 10)); +a b c +SELECT a, AVG(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=AVG(t1.b)) +AS test FROM t1 GROUP BY a; +a AVG(b) test +1 4.0000 NULL +2 2.0000 k +3 2.5000 NULL +SELECT a,b,c FROM t1 WHERE b in (9,3,4) ORDER BY b,c; +a b c +1 3 c +2 3 h +3 3 j +1 4 d +3 4 i +1 9 m +SELECT a, MAX(b), +(SELECT COUNT(DISTINCT t.c) FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) +LIMIT 1) +as cnt, +(SELECT t.b FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) +as t_b, +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) +as t_b, +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) ORDER BY t.c LIMIT 1) +as t_b +FROM t1 GROUP BY a; +a MAX(b) cnt t_b t_b t_b +1 9 1 9 m m +2 3 1 3 h h +3 4 1 4 i i +SELECT a, MAX(b), +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) as test +FROM t1 GROUP BY a; +a MAX(b) test +1 9 m +2 3 h +3 4 i +DROP TABLE t1, t2; diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index ed8480ba464..e3703c0da16 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -489,3 +489,44 @@ select a, b, (a,b) in (select a, min(b) from t2 group by a) Z from t1; drop table t1,t2; +# +# Bug #24484: Aggregate function used in column list subquery gives erroneous +# error +# +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t1 VALUES (1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), + (2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'),(3,3,'j'), (3,2,'k'), (3,1,'l'), + (1,9,'m'); +CREATE TABLE t2 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t2 SELECT * FROM t1; + +# Gives error, but should work since it is (a, b) is the PK so only one +# given match possible +SELECT a, MAX(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) + as test FROM t1 GROUP BY a; +SELECT * FROM t1 GROUP by t1.a + HAVING (MAX(t1.b) > (SELECT MAX(t2.b) FROM t2 WHERE t2.c < t1.c + HAVING MAX(t2.b+t1.a) < 10)); +SELECT a, AVG(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=AVG(t1.b)) + AS test FROM t1 GROUP BY a; + +SELECT a,b,c FROM t1 WHERE b in (9,3,4) ORDER BY b,c; + +SELECT a, MAX(b), + (SELECT COUNT(DISTINCT t.c) FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) + LIMIT 1) + as cnt, + (SELECT t.b FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) + as t_b, + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) + as t_b, + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) ORDER BY t.c LIMIT 1) + as t_b + FROM t1 GROUP BY a; + +SELECT a, MAX(b), + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) as test + FROM t1 GROUP BY a; + + +DROP TABLE t1, t2; -- cgit v1.2.1 From 91f7f3181670523aa657420ae47d1d20fcd07aea Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Mar 2007 11:51:09 -0700 Subject: Fixed bug #27257: queries containing subqueries with COUNT(*) aggregated in outer context returned wrong results. This happened only if the subquery did not contain any references to outer fields. As there were no references to outer fields the subquery erroneously was taken for non-correlated one. Now any set function aggregated in outer context makes the subquery correlated. mysql-test/r/subselect.result: Added a test case for bug #27257. mysql-test/t/subselect.test: Added a test case for bug #27257. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 21 +++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index f2d41bd44ae..72bde001e87 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3880,3 +3880,28 @@ this is a test. 3 this is a test. 1 this is a test. 2 DROP table t1; +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (m int, n int); +INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4); +INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44); +SELECT COUNT(*), a, +(SELECT m FROM t2 WHERE m = count(*) LIMIT 1) +FROM t1 GROUP BY a; +COUNT(*) a (SELECT m FROM t2 WHERE m = count(*) LIMIT 1) +2 2 2 +3 3 3 +1 4 1 +SELECT COUNT(*), a, +(SELECT MIN(m) FROM t2 WHERE m = count(*)) +FROM t1 GROUP BY a; +COUNT(*) a (SELECT MIN(m) FROM t2 WHERE m = count(*)) +2 2 2 +3 3 3 +1 4 1 +SELECT COUNT(*), a +FROM t1 GROUP BY a +HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1; +COUNT(*) a +2 2 +3 3 +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1655422c51e..a238c8f070b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2741,4 +2741,25 @@ SELECT * FROM (SELECT 'this is ' 'a test.' AS col1, a AS t2 FROM t1) t; DROP table t1; +# +# Bug #27257: COUNT(*) aggregated in outer query +# + +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (m int, n int); +INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4); +INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44); +SELECT COUNT(*), a, + (SELECT m FROM t2 WHERE m = count(*) LIMIT 1) + FROM t1 GROUP BY a; + +SELECT COUNT(*), a, + (SELECT MIN(m) FROM t2 WHERE m = count(*)) + FROM t1 GROUP BY a; + +SELECT COUNT(*), a + FROM t1 GROUP BY a + HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1; + +DROP TABLE t1,t2; -- cgit v1.2.1 From 16404523645b8f396ebaea9da5dfa4c453056d06 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Mar 2007 21:54:38 +0300 Subject: Bug#23345: Wrongly allowed INTO in a non-last select of a UNION. INTO clause can be specified only for the last select of a UNION and it receives the result of the whole query. But it was wrongly allowed in non-last selects of a UNION which leads to a confusing query result. Now INTO allowed only in the last select of a UNION. mysql-test/t/union.test: Added a test case for the bug#23345: Wrongly allowed INTO in a non-last select of a UNION. mysql-test/r/union.result: Added a test case for the bug#23345: Wrongly allowed INTO in a non-last select of a UNION. sql/sql_yacc.yy: Bug#23345: Wrongly allowed INTO in a non-last select of a UNION. Now INTO allowed only in the last select of a UNION. --- mysql-test/r/union.result | 8 ++++++++ mysql-test/t/union.test | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 9861b1bffeb..8219d68a681 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1381,4 +1381,12 @@ a SELECT a FROM (SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY c) AS test; ERROR 42S22: Unknown column 'c' in 'order clause' DROP TABLE t1; +(select 1 into @var) union (select 1); +ERROR HY000: Incorrect usage of UNION and INTO +(select 1) union (select 1 into @var); +select @var; +@var +1 +(select 2) union (select 1 into @var); +ERROR 42000: Result consisted of more than one row End of 5.0 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 29a9ee36481..22f09466b1c 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -868,4 +868,13 @@ SELECT a FROM (SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY c) AS test; DROP TABLE t1; +# +# Bug#23345: Wrongly allowed INTO in a non-last select of a UNION. +# +--error 1221 +(select 1 into @var) union (select 1); +(select 1) union (select 1 into @var); +select @var; +--error 1172 +(select 2) union (select 1 into @var); --echo End of 5.0 tests -- cgit v1.2.1 From a4a23fb907ce7b2c3e998735e074da647b3e9ffc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Mar 2007 00:05:36 -0700 Subject: Fixed bug #27362: crash at evaluation of IN predicate when one of its argument happened to be a decimal expression returning the NULL value. The crash was due to the fact the function in_decimal::set did not take into account that val_decimal() could return 0 if the decimal expression had been evaluated to NULL. mysql-test/r/func_in.result: Added a test case for bug #27362. mysql-test/t/func_in.test: Added a test case for bug #27362. --- mysql-test/r/func_in.result | 5 +++++ mysql-test/t/func_in.test | 11 +++++++++++ 2 files changed, 16 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index fad9a7157e1..87855091699 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -470,4 +470,9 @@ a Warnings: Warning 1292 Incorrect date value: '19772-07-29' for column 'a' at row 1 DROP TABLE t1,t2,t3,t4; +CREATE TABLE t1 (id int not null); +INSERT INTO t1 VALUES (1),(2); +SELECT id FROM t1 WHERE id IN(4564, (SELECT IF(1=0,1,1/0)) ); +id +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index f9749662ec1..77592d015eb 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -360,4 +360,15 @@ SELECT * FROM t4 WHERE a IN ('1972-02-06','19772-07-29'); DROP TABLE t1,t2,t3,t4; +# +# BUG#27362: IN with a decimal expression that may return NULL +# + +CREATE TABLE t1 (id int not null); +INSERT INTO t1 VALUES (1),(2); + +SELECT id FROM t1 WHERE id IN(4564, (SELECT IF(1=0,1,1/0)) ); + +DROP TABLE t1; + --echo End of 5.0 tests -- cgit v1.2.1 From 50b5064ccd0af957080d9c9efd022e33c7c9c060 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Mar 2007 12:24:56 +0400 Subject: bug #16546 (DATETIME + 0 not always coerced in the same way) fix for cast( AS DATETIME) + 0 operation. I just implemented Item_datetime_typecast::val() method as it is usually done in other classes. Should be fixed more radically in 5.0 mysql-test/r/type_datetime.result: result added mysql-test/t/type_datetime.test: testcase sql/item_timefunc.h: added double conversion to Item_datetime_typecast --- mysql-test/r/type_datetime.result | 3 +++ mysql-test/t/type_datetime.test | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'mysql-test') diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index f313a6b934b..64337bd2c2f 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -166,3 +166,6 @@ dt 0000-00-00 00:00:00 0000-00-00 00:00:00 drop table t1; +select cast('2006-12-05 22:10:10' as datetime) + 0; +cast('2006-12-05 22:10:10' as datetime) + 0 +20061205221010.000000 diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 4b6741b4242..87b86b55fc9 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -113,4 +113,10 @@ insert into t1 values ("00-00-00"), ("00-00-00 00:00:00"); select * from t1; drop table t1; +# +# Bug #16546 DATETIME+0 not always coerced the same way +# +select cast('2006-12-05 22:10:10' as datetime) + 0; + + # End of 4.1 tests -- cgit v1.2.1