summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_group.result2
-rw-r--r--mysql-test/r/func_str.result28
-rw-r--r--mysql-test/r/select.result49
-rw-r--r--mysql-test/r/subselect.result29
-rw-r--r--mysql-test/t/func_str.test15
-rw-r--r--mysql-test/t/select.test30
-rw-r--r--mysql-test/t/subselect.test17
-rw-r--r--sql/item_cmpfunc.cc22
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_strfunc.cc17
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/item_subselect.cc6
-rw-r--r--sql/item_subselect.h9
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_select.cc18
16 files changed, 242 insertions, 11 deletions
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index ffa68f279f3..932ef133087 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -824,6 +824,7 @@ select 1, min(a) from t1m where 1=99;
1 NULL
select 1, min(1) from t1m where a=99;
1 min(1)
+1 NULL
select 1, min(1) from t1m where 1=99;
1 min(1)
1 NULL
@@ -835,6 +836,7 @@ select 1, max(a) from t1m where 1=99;
1 NULL
select 1, max(1) from t1m where a=99;
1 max(1)
+1 NULL
select 1, max(1) from t1m where 1=99;
1 max(1)
1 NULL
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 61a77c211d7..2c15e5581e8 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1036,4 +1036,32 @@ a c
abc abc abc
xyz xyz xyz
DROP TABLE t1;
+CREATE TABLE t1 (s varchar(10));
+INSERT INTO t1 VALUES ('yadda'), ('yaddy');
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(s) > 'ab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1003 select test.t1.s AS `s` from test.t1 where (trim(test.t1.s) > _latin1'ab')
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM('y' FROM s) > 'ab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1003 select test.t1.s AS `s` from test.t1 where (trim(both _latin1'y' from test.t1.s) > _latin1'ab')
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(LEADING 'y' FROM s) > 'ab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1003 select test.t1.s AS `s` from test.t1 where (trim(leading _latin1'y' from test.t1.s) > _latin1'ab')
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(TRAILING 'y' FROM s) > 'ab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1003 select test.t1.s AS `s` from test.t1 where (trim(trailing _latin1'y' from test.t1.s) > _latin1'ab')
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(BOTH 'y' FROM s) > 'ab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
+Warnings:
+Note 1003 select test.t1.s AS `s` from test.t1 where (trim(both _latin1'y' from test.t1.s) > _latin1'ab')
+DROP TABLE t1;
End of 4.1 tests
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index c7df11ab018..d7c01fa5a57 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -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')
0 1 1 1
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;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index c78f0951469..983ad628425 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -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
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
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');
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
@@ -2868,3 +2868,30 @@ select 1 from dual where 1 < any (select 2 from dual);
select 1 from dual where 1 < all (select 2 from dual where 1!=1);
1
1
+create table t1 (s1 char);
+insert into t1 values (1),(2);
+select * from t1 where (s1 < any (select s1 from t1));
+s1
+1
+select * from t1 where not (s1 < any (select s1 from t1));
+s1
+2
+select * from t1 where (s1 < ALL (select s1+1 from t1));
+s1
+1
+select * from t1 where not(s1 < ALL (select s1+1 from t1));
+s1
+2
+select * from t1 where (s1+1 = ANY (select s1 from t1));
+s1
+1
+select * from t1 where NOT(s1+1 = ANY (select s1 from t1));
+s1
+2
+select * from t1 where (s1 = ALL (select s1/s1 from t1));
+s1
+1
+select * from t1 where NOT(s1 = ALL (select s1/s1 from t1));
+s1
+2
+drop table t1;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 9a1c75a8dc0..3c855a32eed 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -697,5 +697,20 @@ SELECT a, CONCAT(a,' ',a) AS c FROM t1
INSTR(REVERSE(CONCAT(a,' ',a))," ")) = a;
DROP TABLE t1;
+
+#
+# Bug#17526: WRONG PRINT for TRIM FUNCTION with two arguments
+#
+
+CREATE TABLE t1 (s varchar(10));
+INSERT INTO t1 VALUES ('yadda'), ('yaddy');
+
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(s) > 'ab';
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM('y' FROM s) > 'ab';
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(LEADING 'y' FROM s) > 'ab';
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(TRAILING 'y' FROM s) > 'ab';
+EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(BOTH 'y' FROM s) > 'ab';
+
+DROP TABLE t1;
--echo End of 4.1 tests
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 4cdfc220350..acf9fd77c1b 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -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;
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
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index e01310bba45..fc97d22cbb1 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1844,4 +1844,21 @@ select 1 from dual where 2 > any (select 1);
select 1 from dual where 2 > all (select 1);
select 1 from dual where 1 < any (select 2 from dual);
select 1 from dual where 1 < all (select 2 from dual where 1!=1);
+
+# BUG#20975 Wrong query results for subqueries within NOT
+create table t1 (s1 char);
+insert into t1 values (1),(2);
+
+select * from t1 where (s1 < any (select s1 from t1));
+select * from t1 where not (s1 < any (select s1 from t1));
+
+select * from t1 where (s1 < ALL (select s1+1 from t1));
+select * from t1 where not(s1 < ALL (select s1+1 from t1));
+
+select * from t1 where (s1+1 = ANY (select s1 from t1));
+select * from t1 where NOT(s1+1 = ANY (select s1 from t1));
+
+select * from t1 where (s1 = ALL (select s1/s1 from t1));
+select * from t1 where NOT(s1 = ALL (select s1/s1 from t1));
+drop table t1;
# End of 4.1 tests
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f14efc7187b..a32bd0a7337 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3099,6 +3099,28 @@ Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */
}
+Item *Item_func_nop_all::neg_transformer(THD *thd)
+{
+ /* "NOT (e $cmp$ ANY (SELECT ...)) -> e $rev_cmp$" ALL (SELECT ...) */
+ Item_func_not_all *new_item= new Item_func_not_all(args[0]);
+ Item_allany_subselect *allany= (Item_allany_subselect*)args[0];
+ allany->func= allany->func_creator(FALSE);
+ allany->all= !allany->all;
+ allany->upper_item= new_item;
+ return new_item;
+}
+
+Item *Item_func_not_all::neg_transformer(THD *thd)
+{
+ /* "NOT (e $cmp$ ALL (SELECT ...)) -> e $rev_cmp$" ANY (SELECT ...) */
+ Item_func_nop_all *new_item= new Item_func_nop_all(args[0]);
+ Item_allany_subselect *allany= (Item_allany_subselect*)args[0];
+ allany->all= !allany->all;
+ allany->func= allany->func_creator(TRUE);
+ allany->upper_item= new_item;
+ return new_item;
+}
+
Item *Item_func_eq::negated_item() /* a = b -> a != b */
{
return new Item_func_ne(args[0], args[1]);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 73abe208d9e..0e157fd412c 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -268,6 +268,7 @@ public:
void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; };
void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; };
bool empty_underlying_subquery();
+ Item *neg_transformer(THD *thd);
};
@@ -278,6 +279,7 @@ public:
Item_func_nop_all(Item *a) :Item_func_not_all(a) {}
longlong val_int();
const char *func_name() const { return "<nop>"; }
+ Item *neg_transformer(THD *thd);
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7bc7956283b..1c5b947cb2b 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1444,6 +1444,23 @@ void Item_func_trim::fix_length_and_dec()
}
}
+void Item_func_trim::print(String *str)
+{
+ if (arg_count == 1)
+ {
+ Item_func::print(str);
+ return;
+ }
+ str->append(Item_func_trim::func_name());
+ str->append('(');
+ str->append(mode_name());
+ str->append(' ');
+ args[1]->print(str);
+ str->append(" from ",6);
+ args[0]->print(str);
+ str->append(')');
+}
+
/* Item_func_password */
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index f800c17182b..880a19242ca 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -218,6 +218,8 @@ public:
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "trim"; }
+ void print(String *str);
+ virtual const char *mode_name() const { return "both"; }
};
@@ -228,6 +230,7 @@ public:
Item_func_ltrim(Item *a) :Item_func_trim(a) {}
String *val_str(String *);
const char *func_name() const { return "ltrim"; }
+ const char *mode_name() const { return "leading"; }
};
@@ -238,6 +241,7 @@ public:
Item_func_rtrim(Item *a) :Item_func_trim(a) {}
String *val_str(String *);
const char *func_name() const { return "rtrim"; }
+ const char *mode_name() const { return "trailing"; }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index f6f8eec9af5..c95a91de13e 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -542,14 +542,14 @@ Item_in_subselect::Item_in_subselect(Item * left_exp,
}
Item_allany_subselect::Item_allany_subselect(Item * left_exp,
- Comp_creator *fn,
+ chooser_compare_func_creator fc,
st_select_lex *select_lex,
bool all_arg)
- :Item_in_subselect(), all(all_arg)
+ :Item_in_subselect(), all(all_arg), func_creator(fc)
{
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
left_expr= left_exp;
- func= fn;
+ func= func_creator(all_arg);
init(select_lex, new select_exists_subselect(this));
max_columns= 1;
abort_on_null= 0;
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index dec32398a80..93171ad64a1 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -251,14 +251,13 @@ public:
/* ALL/ANY/SOME subselect */
class Item_allany_subselect :public Item_in_subselect
{
-protected:
- Comp_creator *func;
-
public:
+ chooser_compare_func_creator func_creator;
+ Comp_creator *func;
bool all;
- Item_allany_subselect(Item * left_expr, Comp_creator *f,
- st_select_lex *select_lex, bool all);
+ Item_allany_subselect(Item * left_expr, chooser_compare_func_creator fc,
+ st_select_lex *select_lex, bool all);
// only ALL subquery has upper not
subs_type substype() { return all?ALL_SUBS:ANY_SUBS; }
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index d231942bb7a..d03c6acac7c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -387,8 +387,9 @@ enum enum_var_type
OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL
};
class sys_var;
-#include "item.h"
+class Comp_creator;
typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
+#include "item.h"
/* sql_parse.cc */
void free_items(Item *item);
void cleanup_items(Item *item);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fbe36bfdc4a..660c77e81e4 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5436,7 +5436,7 @@ Item * all_any_subquery_creator(Item *left_expr,
return new Item_func_not(new Item_in_subselect(left_expr, select_lex));
Item_allany_subselect *it=
- new Item_allany_subselect(left_expr, (*cmp)(all), select_lex, all);
+ new Item_allany_subselect(left_expr, cmp, select_lex, all);
if (all)
return it->upper_item= new Item_func_not_all(it); /* ALL */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ce573136faf..339826b3692 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -547,6 +547,24 @@ JOIN::optimize()
}
zero_result_cause= "Select tables optimized away";
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)