summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/derived_view.result29
-rw-r--r--mysql-test/r/distinct.result110
-rw-r--r--mysql-test/r/null.result9
-rw-r--r--mysql-test/t/derived_view.test33
-rw-r--r--mysql-test/t/distinct.test58
-rw-r--r--mysql-test/t/null.test12
-rw-r--r--sql/item.cc10
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_cmpfunc.cc24
-rw-r--r--sql/item_cmpfunc.h17
-rw-r--r--sql/item_func.cc10
-rw-r--r--sql/item_func.h15
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_select.cc43
-rw-r--r--sql/sql_select.h5
16 files changed, 346 insertions, 33 deletions
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index 8630087ba72..a3d38021a28 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -2215,6 +2215,35 @@ DROP VIEW v1;
DROP TABLE t1,t2;
set optimizer_switch=@save_optimizer_switch;
#
+# mdev-5078: sum over a view/derived table
+#
+CREATE TABLE t1 (a int);
+INSERT INTO t1 (a) VALUES (1), (2);
+CREATE TABLE t2 (b int(11));
+INSERT INTO t2 (b) VALUES (1), (2);
+CREATE VIEW v AS SELECT b as c FROM t2;
+SELECT a, (SELECT SUM(a + c) FROM v) FROM t1;
+a (SELECT SUM(a + c) FROM v)
+1 5
+2 7
+SELECT a, (SELECT SUM(a + c) FROM (SELECT b as c FROM t2) AS v1) FROM t1;
+a (SELECT SUM(a + c) FROM (SELECT b as c FROM t2) AS v1)
+1 5
+2 7
+DROP VIEW v;
+DROP TABLE t1,t2;
+#
+# mdev-5105: memory overwrite in multi-table update
+# using natuaral join with a view
+#
+create table t1(a int,b tinyint,c tinyint)engine=myisam;
+create table t2(a tinyint,b float,c int, d int, e int, f int, key (b), key(c), key(d), key(e), key(f))engine=myisam;
+create table t3(a int,b int,c int, d int, e int, f int, key(a), key(b), key(c), key(d), key(e), key(f))engine=myisam;
+create view v1 as select t2.b a, t1.b b, t2.c c, t2.d d, t2.e e, t2.f f from t1,t2 where t1.a=t2.a;
+update t3 natural join v1 set a:=1;
+drop view v1;
+drop table t1,t2,t3;
+#
# end of 5.3 tests
#
set optimizer_switch=@exit_optimizer_switch;
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 459ece978fd..1ba078c1c1c 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -879,6 +879,116 @@ NULL
7
drop view v;
drop table t1, t2;
+CREATE TABLE t1 (
+id int, i1 int, i2 int DEFAULT 0,
+d1 date DEFAULT '2000-01-01', d2 date DEFAULT '2000-01-01',
+t1 time DEFAULT '00:00:00', t2 time DEFAULT '00:00:00',
+dt1 datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+dt2 datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+c1 varchar(1) NOT NULL, c2 varchar(1) NOT NULL
+) ENGINE=MyISAM;
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+INSERT INTO t1 (id,i1,c1,c2) VALUES
+(1,7,'t','t'),(2,4,'k','k'),(3,2,'e','e'),(4,0,'i','i'),(5,1,'t','t'),(6,91,'m','m'),
+(7,6,'z','z'),(8,3,'c','c'),(9,6,'i','i'),(10,8,'v','v'), (11,1,'l','l'),(12,4,'j','j'),
+(13,5,'w','w'),(14,0,'r','r'),(15,7,'o','o'),(16,9,'o','o'),(17,7,'u','u'),(18,6,'f','f'),
+(19,0,'l','l'),(20,6,'g','g'),(21,1,'e','e'),(22,7,'y','y'),(23,0,'p','p'),(24,6,'v','v'),
+(25,5,'d','d'),(26,9,'i','i'),(27,5,'z','z'),(28,2,'q','q'),(29,4,'j','j'),(30,9,'m','m'),
+(31,8,'d','d'),(32,5,'r','r'),(33,1,'r','r'),(34,1,'k','k'),(35,4,'p','p'),(36,2,'x','x'),
+(37,5,'w','w'),(38,0,'k','k'),(39,7,'y','y'),(40,4,'p','p'),(41,9,'l','l'),(42,2,'u','u'),
+(43,3,'r','r'),(44,5,'y','y'),(45,3,'u','u'),(46,9,'t','t'),(47,8,'f','f'),(48,2,'f','f'),
+(49,2,'q','q'),(50,6,'v','v'),(51,6,'u','u'),(52,0,'b','b'),(53,1,'n','n'),(54,2,'p','p'),
+(55,0,'y','y'),(56,1,'l','l'),(57,1,'c','c'),(58,0,'d','d'),(59,2,'y','y'),(60,7,'l','l'),
+(61,6,'m','m'),(62,9,'q','q'),(63,0,'j','j'),(64,3,'u','u'),(65,4,'w','w'),(66,5,'p','p'),
+(67,8,'z','z'),(68,5,'u','u'),(69,7,'b','b'),(70,0,'f','f'),(71,6,'u','u'),(72,1,'i','i'),
+(73,9,'s','s'),(74,3,'y','y'),(75,5,'s','s'),(76,8,'x','x'),(77,3,'s','s'),(78,3,'l','l'),
+(79,8,'b','b'),(80,0,'p','p'),(81,9,'m','m'),(82,5,'k','k'),(83,7,'u','u'),(84,0,'y','y'),
+(85,2,'x','x'),(86,5,'h','h'),(87,5,'j','j'),(88,5,'o','o'),(89,9,'o','o'),(90,1,'c','c'),
+(91,7,'k','k'),(92,9,'t','t'),(93,3,'h','h'),(94,6,'g','g'),(95,9,'r','r'),(96,2,'i','i');
+CREATE TABLE t2 (i INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (7),(8);
+SELECT STRAIGHT_JOIN COUNT(DISTINCT t1.id) FROM
+t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+COUNT(DISTINCT t1.id)
+18
+EXPLAIN EXTENDED
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 96 100.00 Using where; Using temporary
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.i1 9 100.00 Using where; Distinct
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Distinct; Using join buffer (flat, BNL join)
+2 DERIVED t1 ALL NULL NULL NULL NULL 96 100.00
+Warnings:
+Note 1003 select straight_join distinct `test`.`t1`.`id` AS `id` from `test`.`t1` join `test`.`v1` join `test`.`t2` where ((`test`.`t2`.`i` = `v1`.`id`) and (`v1`.`i1` = `test`.`t1`.`i1`) and (`v1`.`id` <> 3))
+set join_buffer_size=1024;
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+id
+7
+8
+9
+18
+20
+24
+43
+45
+50
+51
+61
+64
+71
+74
+77
+78
+93
+94
+set join_buffer_size=1024*16;
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+id
+7
+9
+18
+20
+24
+8
+50
+51
+61
+43
+45
+71
+64
+74
+77
+78
+94
+93
+set join_buffer_size=default;
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+id
+7
+9
+18
+20
+24
+50
+51
+61
+71
+94
+8
+43
+45
+64
+74
+77
+78
+93
+DROP VIEW v1;
+DROP TABLE t1,t2;
#
# Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb
#
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 836de3d5842..ce233e0db23 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -373,3 +373,12 @@ id select_type table type possible_keys key key_len ref rows Extra
SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL);
dt
DROP TABLE t1;
+#
+# Bug mdev-5132: crash when exeicuting a join query
+# with IS NULL and IS NOT NULL in where
+#
+CREATE TABLE t1 (a DATE, b INT, c INT, KEY(a), KEY(b), KEY(c)) ENGINE=MyISAM;
+CREATE TABLE t2 (d DATE) ENGINE=MyISAM;
+SELECT * FROM t1,t2 WHERE 1 IS NOT NULL AND t1.b IS NULL;
+a b c d
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test
index 4b7e76e11ca..8d1b3109d20 100644
--- a/mysql-test/t/derived_view.test
+++ b/mysql-test/t/derived_view.test
@@ -1546,6 +1546,39 @@ set optimizer_switch=@save_optimizer_switch;
--echo #
+--echo # mdev-5078: sum over a view/derived table
+--echo #
+
+CREATE TABLE t1 (a int);
+INSERT INTO t1 (a) VALUES (1), (2);
+
+CREATE TABLE t2 (b int(11));
+INSERT INTO t2 (b) VALUES (1), (2);
+
+CREATE VIEW v AS SELECT b as c FROM t2;
+
+SELECT a, (SELECT SUM(a + c) FROM v) FROM t1;
+
+SELECT a, (SELECT SUM(a + c) FROM (SELECT b as c FROM t2) AS v1) FROM t1;
+
+DROP VIEW v;
+DROP TABLE t1,t2;
+
+--echo #
+--echo # mdev-5105: memory overwrite in multi-table update
+--echo # using natuaral join with a view
+--echo #
+
+create table t1(a int,b tinyint,c tinyint)engine=myisam;
+create table t2(a tinyint,b float,c int, d int, e int, f int, key (b), key(c), key(d), key(e), key(f))engine=myisam;
+create table t3(a int,b int,c int, d int, e int, f int, key(a), key(b), key(c), key(d), key(e), key(f))engine=myisam;
+create view v1 as select t2.b a, t1.b b, t2.c c, t2.d d, t2.e e, t2.f f from t1,t2 where t1.a=t2.a;
+
+update t3 natural join v1 set a:=1;
+drop view v1;
+drop table t1,t2,t3;
+
+--echo #
--echo # end of 5.3 tests
--echo #
diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test
index f1c120a313d..71643a25c5a 100644
--- a/mysql-test/t/distinct.test
+++ b/mysql-test/t/distinct.test
@@ -683,6 +683,64 @@ select distinct (select max(a) from t1 where alias.b = a) as field1 from t2 as a
drop view v;
drop table t1, t2;
+#
+# Bug mdev-5028: invalid distinct optimization when join buffer is used
+#
+
+CREATE TABLE t1 (
+ id int, i1 int, i2 int DEFAULT 0,
+ d1 date DEFAULT '2000-01-01', d2 date DEFAULT '2000-01-01',
+ t1 time DEFAULT '00:00:00', t2 time DEFAULT '00:00:00',
+ dt1 datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+ dt2 datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+ c1 varchar(1) NOT NULL, c2 varchar(1) NOT NULL
+) ENGINE=MyISAM;
+
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+
+INSERT INTO t1 (id,i1,c1,c2) VALUES
+(1,7,'t','t'),(2,4,'k','k'),(3,2,'e','e'),(4,0,'i','i'),(5,1,'t','t'),(6,91,'m','m'),
+(7,6,'z','z'),(8,3,'c','c'),(9,6,'i','i'),(10,8,'v','v'), (11,1,'l','l'),(12,4,'j','j'),
+(13,5,'w','w'),(14,0,'r','r'),(15,7,'o','o'),(16,9,'o','o'),(17,7,'u','u'),(18,6,'f','f'),
+(19,0,'l','l'),(20,6,'g','g'),(21,1,'e','e'),(22,7,'y','y'),(23,0,'p','p'),(24,6,'v','v'),
+(25,5,'d','d'),(26,9,'i','i'),(27,5,'z','z'),(28,2,'q','q'),(29,4,'j','j'),(30,9,'m','m'),
+(31,8,'d','d'),(32,5,'r','r'),(33,1,'r','r'),(34,1,'k','k'),(35,4,'p','p'),(36,2,'x','x'),
+(37,5,'w','w'),(38,0,'k','k'),(39,7,'y','y'),(40,4,'p','p'),(41,9,'l','l'),(42,2,'u','u'),
+(43,3,'r','r'),(44,5,'y','y'),(45,3,'u','u'),(46,9,'t','t'),(47,8,'f','f'),(48,2,'f','f'),
+(49,2,'q','q'),(50,6,'v','v'),(51,6,'u','u'),(52,0,'b','b'),(53,1,'n','n'),(54,2,'p','p'),
+(55,0,'y','y'),(56,1,'l','l'),(57,1,'c','c'),(58,0,'d','d'),(59,2,'y','y'),(60,7,'l','l'),
+(61,6,'m','m'),(62,9,'q','q'),(63,0,'j','j'),(64,3,'u','u'),(65,4,'w','w'),(66,5,'p','p'),
+(67,8,'z','z'),(68,5,'u','u'),(69,7,'b','b'),(70,0,'f','f'),(71,6,'u','u'),(72,1,'i','i'),
+(73,9,'s','s'),(74,3,'y','y'),(75,5,'s','s'),(76,8,'x','x'),(77,3,'s','s'),(78,3,'l','l'),
+(79,8,'b','b'),(80,0,'p','p'),(81,9,'m','m'),(82,5,'k','k'),(83,7,'u','u'),(84,0,'y','y'),
+(85,2,'x','x'),(86,5,'h','h'),(87,5,'j','j'),(88,5,'o','o'),(89,9,'o','o'),(90,1,'c','c'),
+(91,7,'k','k'),(92,9,'t','t'),(93,3,'h','h'),(94,6,'g','g'),(95,9,'r','r'),(96,2,'i','i');
+
+CREATE TABLE t2 (i INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (7),(8);
+
+SELECT STRAIGHT_JOIN COUNT(DISTINCT t1.id) FROM
+ t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+
+EXPLAIN EXTENDED
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+ t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+
+set join_buffer_size=1024;
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+ t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+
+set join_buffer_size=1024*16;
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+ t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+
+set join_buffer_size=default;
+SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
+ t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
+
+DROP VIEW v1;
+DROP TABLE t1,t2;
+
--echo #
--echo # Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb
--echo #
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 4a45240ec68..81951a9ce68 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -283,3 +283,15 @@ SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL);
SELECT * FROM t1 WHERE NOT (concat( dt, '1' ) IS NOT NULL);
DROP TABLE t1;
+
+--echo #
+--echo # Bug mdev-5132: crash when exeicuting a join query
+--echo # with IS NULL and IS NOT NULL in where
+--echo #
+
+CREATE TABLE t1 (a DATE, b INT, c INT, KEY(a), KEY(b), KEY(c)) ENGINE=MyISAM;
+CREATE TABLE t2 (d DATE) ENGINE=MyISAM;
+
+SELECT * FROM t1,t2 WHERE 1 IS NOT NULL AND t1.b IS NULL;
+
+DROP TABLE t1,t2;
diff --git a/sql/item.cc b/sql/item.cc
index 88e654d07b5..e94c4651ee3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5109,6 +5109,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
goto mark_non_agg_field;
}
+ if (thd->lex->in_sum_func &&
+ thd->lex->in_sum_func->nest_level ==
+ thd->lex->current_select->nest_level)
+ set_if_bigger(thd->lex->in_sum_func->max_arg_level,
+ thd->lex->current_select->nest_level);
/*
if it is not expression from merged VIEW we will set this field.
@@ -5125,11 +5130,6 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
return FALSE;
set_field(from_field);
- if (thd->lex->in_sum_func &&
- thd->lex->in_sum_func->nest_level ==
- thd->lex->current_select->nest_level)
- set_if_bigger(thd->lex->in_sum_func->max_arg_level,
- thd->lex->current_select->nest_level);
}
else if (thd->mark_used_columns != MARK_COLUMNS_NONE)
{
diff --git a/sql/item.h b/sql/item.h
index db2e00f2f90..ec99e857709 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1176,6 +1176,7 @@ public:
virtual bool view_used_tables_processor(uchar *arg) { return 0; }
virtual bool eval_not_null_tables(uchar *opt_arg) { return 0; }
virtual bool is_subquery_processor (uchar *opt_arg) { return 0; }
+ virtual bool count_sargable_conds(uchar *arg) { return 0; }
virtual bool limit_index_condition_pushdown_processor(uchar *opt_arg)
{
return FALSE;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 3d1bb6ce885..d71185d49a4 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1435,6 +1435,7 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
return FALSE;
}
+
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{
if ((!args[0]->fixed && args[0]->fix_fields(thd, args)) ||
@@ -2165,6 +2166,15 @@ bool Item_func_between::eval_not_null_tables(uchar *opt_arg)
}
+bool Item_func_between::count_sargable_conds(uchar *arg)
+{
+ SELECT_LEX *sel= (SELECT_LEX *) arg;
+ sel->cond_count++;
+ sel->between_count++;
+ return 0;
+}
+
+
void Item_func_between::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
/* This will re-calculate attributes of the arguments */
@@ -4752,6 +4762,7 @@ longlong Item_func_isnull::val_int()
return args[0]->is_null() ? 1: 0;
}
+
longlong Item_is_not_null_test::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -4955,6 +4966,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
return FALSE;
}
+
void Item_func_like::cleanup()
{
canDoTurboBM= FALSE;
@@ -5584,7 +5596,8 @@ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
equal_items.push_back(f1);
equal_items.push_back(f2);
compare_as_dates= with_const_item && f2->cmp_type() == TIME_RESULT;
- upper_levels= NULL;
+ upper_levels= NULL;
+ sargable= TRUE;
}
@@ -5614,6 +5627,7 @@ Item_equal::Item_equal(Item_equal *item_equal)
compare_as_dates= item_equal->compare_as_dates;
cond_false= item_equal->cond_false;
upper_levels= item_equal->upper_levels;
+ sargable= TRUE;
}
@@ -6000,6 +6014,14 @@ void Item_equal::update_used_tables()
}
+bool Item_equal::count_sargable_conds(uchar *arg)
+{
+ SELECT_LEX *sel= (SELECT_LEX *) arg;
+ uint m= equal_items.elements;
+ sel->cond_count+= m*(m-1);
+ return 0;
+}
+
/**
@brief
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 734e266ea26..57492b3d446 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -369,7 +369,8 @@ protected:
public:
Item_bool_func2(Item *a,Item *b)
- :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(FALSE) {}
+ :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1),
+ abort_on_null(FALSE) { sargable= TRUE; }
void fix_length_and_dec();
int set_cmp_func()
{
@@ -673,7 +674,7 @@ public:
/* TRUE <=> arguments will be compared as dates. */
Item *compare_as_dates;
Item_func_between(Item *a, Item *b, Item *c)
- :Item_func_opt_neg(a, b, c), compare_as_dates(FALSE) {}
+ :Item_func_opt_neg(a, b, c), compare_as_dates(FALSE) { sargable= TRUE; }
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
enum Functype functype() const { return BETWEEN; }
@@ -686,6 +687,7 @@ public:
uint decimal_precision() const { return 1; }
bool eval_not_null_tables(uchar *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
+ bool count_sargable_conds(uchar *arg);
};
@@ -1291,10 +1293,11 @@ public:
Item_func_in(List<Item> &list)
:Item_func_opt_neg(list), array(0), have_null(0),
- arg_types_compatible(FALSE)
+ arg_types_compatible(FALSE)
{
bzero(&cmp_items, sizeof(cmp_items));
allowed_arg_cols= 0; // Fetch this value from first argument
+ sargable= TRUE;
}
longlong val_int();
bool fix_fields(THD *, Item **);
@@ -1360,7 +1363,7 @@ public:
class Item_func_isnull :public Item_bool_func
{
public:
- Item_func_isnull(Item *a) :Item_bool_func(a) {}
+ Item_func_isnull(Item *a) :Item_bool_func(a) { sargable= TRUE; }
longlong val_int();
enum Functype functype() const { return ISNULL_FUNC; }
void fix_length_and_dec()
@@ -1422,7 +1425,8 @@ class Item_func_isnotnull :public Item_bool_func
{
bool abort_on_null;
public:
- Item_func_isnotnull(Item *a) :Item_bool_func(a), abort_on_null(0) {}
+ Item_func_isnotnull(Item *a) :Item_bool_func(a), abort_on_null(0)
+ { sargable= TRUE; }
longlong val_int();
enum Functype functype() const { return ISNOTNULL_FUNC; }
void fix_length_and_dec()
@@ -1709,7 +1713,7 @@ public:
inline Item_equal()
: Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0),
context_field(NULL)
- { const_item_cache=0 ;}
+ { const_item_cache=0; sargable= TRUE; }
Item_equal(Item *f1, Item *f2, bool with_const_item);
Item_equal(Item_equal *item_equal);
/* Currently the const item is always the first in the list of equal items */
@@ -1740,6 +1744,7 @@ public:
CHARSET_INFO *compare_collation();
void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
+ bool count_sargable_conds(uchar *arg);
friend class Item_equal_iterator<List_iterator_fast,Item>;
friend class Item_equal_iterator<List_iterator,Item>;
friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e4ec9c62b29..85c3a66d68b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -761,6 +761,16 @@ double Item_int_func::val_real()
return unsigned_flag ? (double) ((ulonglong) val_int()) : (double) val_int();
}
+bool Item_int_func::count_sargable_conds(uchar *arg)
+{
+ if (sargable)
+ {
+ SELECT_LEX *sel= (SELECT_LEX *) arg;
+ sel->cond_count++;
+ }
+ return 0;
+}
+
String *Item_int_func::val_str(String *str)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index de998087618..309b25f1933 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -568,23 +568,26 @@ class Item_num_op :public Item_func_numhybrid
class Item_int_func :public Item_func
{
+protected:
+ bool sargable;
public:
Item_int_func() :Item_func()
- { collation.set_numeric(); fix_char_length(21); }
+ { collation.set_numeric(); fix_char_length(21); sargable= false; }
Item_int_func(Item *a) :Item_func(a)
- { collation.set_numeric(); fix_char_length(21); }
+ { collation.set_numeric(); fix_char_length(21); sargable= false; }
Item_int_func(Item *a,Item *b) :Item_func(a,b)
- { collation.set_numeric(); fix_char_length(21); }
+ { collation.set_numeric(); fix_char_length(21); sargable= false; }
Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c)
- { collation.set_numeric(); fix_char_length(21); }
+ { collation.set_numeric(); fix_char_length(21); sargable= false; }
Item_int_func(List<Item> &list) :Item_func(list)
- { collation.set_numeric(); fix_char_length(21); }
+ { collation.set_numeric(); fix_char_length(21); sargable= false; }
Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item)
- { collation.set_numeric(); }
+ { collation.set_numeric(); sargable= false; }
double val_real();
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {}
+ bool count_sargable_conds(uchar *arg);
};
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b2b1b01f1b9..f0794ac7609 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8814,7 +8814,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
embedded->on_expr->fix_fields(thd, &embedded->on_expr)) ||
embedded->on_expr->check_cols(1))
goto err_no_arena;
- select_lex->cond_count++;
}
/*
If it's a semi-join nest, fix its "left expression", as it is used by
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 44cb270c884..bb55451e9dc 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -395,8 +395,6 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
if (dt_select->options & OPTION_SCHEMA_TABLE)
parent_lex->options |= OPTION_SCHEMA_TABLE;
- parent_lex->cond_count+= dt_select->cond_count;
-
if (!derived->get_unit()->prepared)
{
dt_select->leaf_tables.empty();
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 029fd37608f..85e56b34f96 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1904,9 +1904,10 @@ int JOIN::init_execution()
JOIN_TAB *last_join_tab= join_tab + top_join_tab_count - 1;
do
{
- if (used_tables & last_join_tab->table->map)
+ if (used_tables & last_join_tab->table->map ||
+ last_join_tab->use_join_cache)
break;
- last_join_tab->not_used_in_distinct=1;
+ last_join_tab->shortcut_for_distinct= true;
} while (last_join_tab-- != join_tab);
/* Optimize "select distinct b from t1 order by key_part_1 limit #" */
if (order && skip_sort_order)
@@ -4809,6 +4810,32 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
KEY_FIELD *key_fields, *end, *field;
uint sz;
uint m= max(select_lex->max_equal_elems,1);
+
+ SELECT_LEX *sel=thd->lex->current_select;
+ sel->cond_count= 0;
+ sel->between_count= 0;
+ if (cond)
+ cond->walk(&Item::count_sargable_conds, 0, (uchar*) sel);
+ for (i=0 ; i < tables ; i++)
+ {
+ if (*join_tab[i].on_expr_ref)
+ (*join_tab[i].on_expr_ref)->walk(&Item::count_sargable_conds,
+ 0, (uchar*) sel);
+ }
+ {
+ List_iterator<TABLE_LIST> li(*join_tab->join->join_list);
+ TABLE_LIST *table;
+ while ((table= li++))
+ {
+ if (table->nested_join)
+ {
+ if (table->on_expr)
+ table->on_expr->walk(&Item::count_sargable_conds, 0, (uchar*) sel);
+ if (table->sj_on_expr)
+ table->sj_on_expr->walk(&Item::count_sargable_conds, 0, (uchar*) sel);
+ }
+ }
+ }
/*
We use the same piece of memory to store both KEY_FIELD
@@ -4832,8 +4859,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
substitutions.
*/
sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
- (((thd->lex->current_select->cond_count+1)*2 +
- thd->lex->current_select->between_count)*m+1);
+ ((sel->cond_count*2 + sel->between_count)*m+1);
if (!(key_fields=(KEY_FIELD*) thd->alloc(sz)))
return TRUE; /* purecov: inspected */
and_level= 0;
@@ -8183,6 +8209,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
join_tab->keys.init();
join_tab->keys.set_all(); /* test everything in quick */
join_tab->ref.key = -1;
+ join_tab->shortcut_for_distinct= false;
join_tab->read_first_record= join_init_read_record;
join_tab->join= this;
join_tab->ref.key_parts= 0;
@@ -11539,13 +11566,10 @@ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row,
(Item_row *) left_item,
(Item_row *) right_item,
cond_equal, eq_list);
- if (!is_converted)
- thd->lex->current_select->cond_count++;
}
else
{
is_converted= check_simple_equality(left_item, right_item, 0, cond_equal);
- thd->lex->current_select->cond_count++;
}
if (!is_converted)
@@ -11604,7 +11628,6 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
{
- thd->lex->current_select->cond_count--;
return check_row_equality(thd,
(Item_row *) left_item,
(Item_row *) right_item,
@@ -16707,7 +16730,7 @@ static enum_nested_loop_state
evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
int error)
{
- bool not_used_in_distinct=join_tab->not_used_in_distinct;
+ bool shortcut_for_distinct= join_tab->shortcut_for_distinct;
ha_rows found_records=join->found_records;
COND *select_cond= join_tab->select_cond;
bool select_cond_result= TRUE;
@@ -16869,7 +16892,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
was not in the field list; In this case we can abort if
we found a row, as no new rows can be added to the result.
*/
- if (not_used_in_distinct && found_records != join->found_records)
+ if (shortcut_for_distinct && found_records != join->found_records)
DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
}
else
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 179d1ccf8c6..2415ad1f0b5 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -309,8 +309,9 @@ typedef struct st_join_table {
uint used_null_fields;
uint used_uneven_bit_fields;
enum join_type type;
- bool cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
- bool sorted;
+ bool cached_eq_ref_table,eq_ref_table;
+ bool shortcut_for_distinct;
+ bool sorted;
/*
If it's not 0 the number stored this field indicates that the index
scan has been chosen to access the table data and we expect to scan