mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fix for BUG#20954: avg(keyval) retuns 0.38 but max(keyval) returns an empty set
The problem was in that opt_sum_query() replaced MIN/MAX functions with the corresponding constant found in a key, but due to imprecise representation of float numbers, when evaluating the where clause, this comparison failed. When MIN/MAX optimization detects that all tables can be removed, also remove all conjuncts in a where clause that refer to these tables. As a result of this fix, these conditions are not evaluated twice, and in the case of float number comparisons we do not discard result rows due to imprecise float representation. As a side-effect this fix also corrects an unnoticed problem in bug 12882.
This commit is contained in:
@ -824,6 +824,7 @@ select 1, min(a) from t1m where 1=99;
|
|||||||
1 NULL
|
1 NULL
|
||||||
select 1, min(1) from t1m where a=99;
|
select 1, min(1) from t1m where a=99;
|
||||||
1 min(1)
|
1 min(1)
|
||||||
|
1 NULL
|
||||||
select 1, min(1) from t1m where 1=99;
|
select 1, min(1) from t1m where 1=99;
|
||||||
1 min(1)
|
1 min(1)
|
||||||
1 NULL
|
1 NULL
|
||||||
@ -835,6 +836,7 @@ select 1, max(a) from t1m where 1=99;
|
|||||||
1 NULL
|
1 NULL
|
||||||
select 1, max(1) from t1m where a=99;
|
select 1, max(1) from t1m where a=99;
|
||||||
1 max(1)
|
1 max(1)
|
||||||
|
1 NULL
|
||||||
select 1, max(1) from t1m where 1=99;
|
select 1, max(1) from t1m where 1=99;
|
||||||
1 max(1)
|
1 max(1)
|
||||||
1 NULL
|
1 NULL
|
||||||
|
@ -2744,3 +2744,52 @@ SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1;
|
|||||||
i='1e+01' i=1e+01 i in (1e+01) i in ('1e+01')
|
i='1e+01' i=1e+01 i in (1e+01) i in ('1e+01')
|
||||||
0 1 1 1
|
0 1 1 1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1));
|
||||||
|
CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2));
|
||||||
|
INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941);
|
||||||
|
INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941);
|
||||||
|
explain select max(key1) from t1 where key1 <= 0.6158;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
explain select max(key2) from t2 where key2 <= 1.6158;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
explain select min(key1) from t1 where key1 >= 0.3762;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
explain select min(key2) from t2 where key2 >= 1.3762;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
explain select max(key1), min(key2) from t1, t2
|
||||||
|
where key1 <= 0.6158 and key2 >= 1.3762;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select max(key1) from t1 where key1 <= 0.6158;
|
||||||
|
max(key1)
|
||||||
|
0.61580002307892
|
||||||
|
select max(key2) from t2 where key2 <= 1.6158;
|
||||||
|
max(key2)
|
||||||
|
1.6158000230789
|
||||||
|
select min(key1) from t1 where key1 >= 0.3762;
|
||||||
|
min(key1)
|
||||||
|
0.37619999051094
|
||||||
|
select min(key2) from t2 where key2 >= 1.3762;
|
||||||
|
min(key2)
|
||||||
|
1.3761999607086
|
||||||
|
select max(key1), min(key2) from t1, t2
|
||||||
|
where key1 <= 0.6158 and key2 >= 1.3762;
|
||||||
|
max(key1) min(key2)
|
||||||
|
0.61580002307892 1.3761999607086
|
||||||
|
select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
|
||||||
|
max(key1)
|
||||||
|
0.61580002307892
|
||||||
|
select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
|
||||||
|
min(key1)
|
||||||
|
0.37619999051094
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
@ -539,7 +539,7 @@ EXPLAIN EXTENDED SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select max(test.t1.numreponse) AS `MAX(numreponse)` from test.t1 where (test.t1.numeropost = _latin1'1')
|
Note 1003 select max(test.t1.numreponse) AS `MAX(numreponse)` from test.t1
|
||||||
EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
|
EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index
|
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index
|
||||||
|
@ -2297,4 +2297,34 @@ INSERT INTO t1 VALUES (10);
|
|||||||
SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1;
|
SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #20954 "avg(keyval) retuns 0.38 but max(keyval) returns an empty set"
|
||||||
|
#
|
||||||
|
--disable_ps_protocol
|
||||||
|
CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1));
|
||||||
|
CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2));
|
||||||
|
INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941);
|
||||||
|
INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941);
|
||||||
|
|
||||||
|
explain select max(key1) from t1 where key1 <= 0.6158;
|
||||||
|
explain select max(key2) from t2 where key2 <= 1.6158;
|
||||||
|
explain select min(key1) from t1 where key1 >= 0.3762;
|
||||||
|
explain select min(key2) from t2 where key2 >= 1.3762;
|
||||||
|
explain select max(key1), min(key2) from t1, t2
|
||||||
|
where key1 <= 0.6158 and key2 >= 1.3762;
|
||||||
|
explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
|
||||||
|
explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
|
||||||
|
|
||||||
|
select max(key1) from t1 where key1 <= 0.6158;
|
||||||
|
select max(key2) from t2 where key2 <= 1.6158;
|
||||||
|
select min(key1) from t1 where key1 >= 0.3762;
|
||||||
|
select min(key2) from t2 where key2 >= 1.3762;
|
||||||
|
select max(key1), min(key2) from t1, t2
|
||||||
|
where key1 <= 0.6158 and key2 >= 1.3762;
|
||||||
|
select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5;
|
||||||
|
select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
--enable_ps_protocol
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@ -547,6 +547,24 @@ JOIN::optimize()
|
|||||||
}
|
}
|
||||||
zero_result_cause= "Select tables optimized away";
|
zero_result_cause= "Select tables optimized away";
|
||||||
tables_list= 0; // All tables resolved
|
tables_list= 0; // All tables resolved
|
||||||
|
/*
|
||||||
|
Extract all table-independent conditions and replace the WHERE
|
||||||
|
clause with them. All other conditions were computed by opt_sum_query
|
||||||
|
and the MIN/MAX/COUNT function(s) have been replaced by constants,
|
||||||
|
so there is no need to compute the whole WHERE clause again.
|
||||||
|
Notice that make_cond_for_table() will always succeed to remove all
|
||||||
|
computed conditions, because opt_sum_query() is applicable only to
|
||||||
|
conjunctions.
|
||||||
|
*/
|
||||||
|
if (conds)
|
||||||
|
{
|
||||||
|
COND *table_independent_conds=
|
||||||
|
make_cond_for_table(conds, PSEUDO_TABLE_BITS, 0);
|
||||||
|
DBUG_EXECUTE("where",
|
||||||
|
print_where(table_independent_conds,
|
||||||
|
"where after opt_sum_query()"););
|
||||||
|
conds= table_independent_conds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tables_list)
|
if (!tables_list)
|
||||||
|
Reference in New Issue
Block a user