summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sanja@montyprogram.com>2012-05-25 10:29:53 +0300
committerunknown <sanja@montyprogram.com>2012-05-25 10:29:53 +0300
commitf45784c8503d0bbe77f3aec351fc87ff536b19be (patch)
treeed6e0b6cc29483f0707c7ce7bb3abe666384fc9d
parentd56f5dae1ef60468dd7497453bcdca9b653922ca (diff)
downloadmariadb-git-f45784c8503d0bbe77f3aec351fc87ff536b19be.tar.gz
Fix of LP bug#992380 + revise fix_fields about missing with_subselect collection
The problem is that some fix_fields do not call Item_func::fix_fields and do not collect with subselect_information.
-rw-r--r--mysql-test/r/func_test.result41
-rw-r--r--mysql-test/r/negation_elimination.result4
-rw-r--r--mysql-test/r/ps.result56
-rw-r--r--mysql-test/t/func_test.test20
-rw-r--r--mysql-test/t/ps.test65
-rw-r--r--sql/item_cmpfunc.cc38
-rw-r--r--sql/item_cmpfunc.h3
7 files changed, 225 insertions, 2 deletions
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index a97e6869d09..e3c77a40a77 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -279,3 +279,44 @@ NULL
SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL;
GREATEST(1.5E+2,1.3E+2,NULL)
NULL
+create table t1 (a int);
+insert into t1 values (1), (100), (0), (NULL);
+select not a from t1;
+not a
+0
+0
+1
+NULL
+explain extended select not a from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00
+Warnings:
+Note 1003 select (`test`.`t1`.`a` = 0) AS `not a` from `test`.`t1`
+select * from t1 where not a;
+a
+0
+explain extended select * from t1 where not a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = 0)
+select not (a+0) from t1;
+not (a+0)
+0
+0
+1
+NULL
+explain extended select not (a+0) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00
+Warnings:
+Note 1003 select (not((`test`.`t1`.`a` + 0))) AS `not (a+0)` from `test`.`t1`
+select * from t1 where not (a+0);
+a
+0
+explain extended select * from t1 where not (a+0);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (not((`test`.`t1`.`a` + 0)))
+drop table t1;
diff --git a/mysql-test/r/negation_elimination.result b/mysql-test/r/negation_elimination.result
index af48002ed0f..35510242bcb 100644
--- a/mysql-test/r/negation_elimination.result
+++ b/mysql-test/r/negation_elimination.result
@@ -321,7 +321,7 @@ select * from t1 where not(NULL or a);
a
explain select * from t1 where not(NULL and a);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 5 NULL 21 Using where; Using index
+1 SIMPLE t1 ref a a 5 const 1 Using where; Using index
select * from t1 where not(NULL and a);
a
0
@@ -387,5 +387,5 @@ explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like "
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 5 NULL 4 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or `test`.`t1`.`a`) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0)
+Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or (`test`.`t1`.`a` <> 0)) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0)
drop table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index b3f4ad017d3..72558324b50 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -3040,3 +3040,59 @@ id select_type table type possible_keys key key_len ref rows Extra
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
End of 5.1 tests.
+#
+# LP bug#1001500 Crash on the second execution of the PS for
+# a query with degenerated conjunctive condition
+# (see also mysql bug#12582849)
+#
+CREATE TABLE t1 (
+pk INTEGER AUTO_INCREMENT,
+col_int_nokey INTEGER,
+col_int_key INTEGER,
+col_varchar_key VARCHAR(1),
+col_varchar_nokey VARCHAR(1),
+PRIMARY KEY (pk),
+KEY (col_int_key),
+KEY (col_varchar_key, col_int_key)
+);
+INSERT INTO t1 (
+col_int_key, col_int_nokey,
+col_varchar_key, col_varchar_nokey
+) VALUES
+(4, 2, 'v', 'v'),
+(62, 150, 'v', 'v');
+CREATE TABLE t2 (
+pk INTEGER AUTO_INCREMENT,
+col_int_nokey INTEGER,
+col_int_key INTEGER,
+col_varchar_key VARCHAR(1),
+col_varchar_nokey VARCHAR(1),
+PRIMARY KEY (pk),
+KEY (col_int_key),
+KEY (col_varchar_key, col_int_key)
+);
+INSERT INTO t2 (
+col_int_key, col_int_nokey,
+col_varchar_key, col_varchar_nokey
+) VALUES
+(8, NULL, 'x', 'x'),
+(7, 8, 'd', 'd');
+PREPARE stmt FROM '
+SELECT
+ ( SELECT MAX( SQ1_alias2 .col_int_nokey ) AS SQ1_field1
+ FROM ( t2 AS SQ1_alias1 RIGHT JOIN t1 AS SQ1_alias2
+ ON ( SQ1_alias2.col_varchar_key = SQ1_alias1.col_varchar_nokey )
+ )
+ WHERE SQ1_alias2.pk < alias1.col_int_nokey OR alias1.pk
+ ) AS field1
+FROM ( t1 AS alias1 JOIN t2 AS alias2 ON alias2.pk )
+GROUP BY field1
+';
+EXECUTE stmt;
+field1
+150
+EXECUTE stmt;
+field1
+150
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test
index 77bf3be5e72..4cba29986a1 100644
--- a/mysql-test/t/func_test.test
+++ b/mysql-test/t/func_test.test
@@ -160,3 +160,23 @@ SELECT LEAST(1.1,1.2,NULL,1.0) FROM DUAL;
SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL;
# End of 4.1 tests
+
+#
+# test of replacing NOT <field>
+#
+create table t1 (a int);
+insert into t1 values (1), (100), (0), (NULL);
+
+select not a from t1;
+explain extended select not a from t1;
+
+select * from t1 where not a;
+explain extended select * from t1 where not a;
+
+select not (a+0) from t1;
+explain extended select not (a+0) from t1;
+
+select * from t1 where not (a+0);
+explain extended select * from t1 where not (a+0);
+
+drop table t1;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 9b3f3e750e1..e3f2a5c87d1 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -3102,3 +3102,68 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo End of 5.1 tests.
+
+--echo #
+--echo # LP bug#1001500 Crash on the second execution of the PS for
+--echo # a query with degenerated conjunctive condition
+--echo # (see also mysql bug#12582849)
+--echo #
+
+CREATE TABLE t1 (
+ pk INTEGER AUTO_INCREMENT,
+ col_int_nokey INTEGER,
+ col_int_key INTEGER,
+
+ col_varchar_key VARCHAR(1),
+ col_varchar_nokey VARCHAR(1),
+
+ PRIMARY KEY (pk),
+ KEY (col_int_key),
+ KEY (col_varchar_key, col_int_key)
+);
+
+INSERT INTO t1 (
+ col_int_key, col_int_nokey,
+ col_varchar_key, col_varchar_nokey
+) VALUES
+(4, 2, 'v', 'v'),
+(62, 150, 'v', 'v');
+
+CREATE TABLE t2 (
+ pk INTEGER AUTO_INCREMENT,
+ col_int_nokey INTEGER,
+ col_int_key INTEGER,
+
+ col_varchar_key VARCHAR(1),
+ col_varchar_nokey VARCHAR(1),
+
+ PRIMARY KEY (pk),
+ KEY (col_int_key),
+ KEY (col_varchar_key, col_int_key)
+);
+
+INSERT INTO t2 (
+ col_int_key, col_int_nokey,
+ col_varchar_key, col_varchar_nokey
+) VALUES
+(8, NULL, 'x', 'x'),
+(7, 8, 'd', 'd');
+
+PREPARE stmt FROM '
+SELECT
+ ( SELECT MAX( SQ1_alias2 .col_int_nokey ) AS SQ1_field1
+ FROM ( t2 AS SQ1_alias1 RIGHT JOIN t1 AS SQ1_alias2
+ ON ( SQ1_alias2.col_varchar_key = SQ1_alias1.col_varchar_nokey )
+ )
+ WHERE SQ1_alias2.pk < alias1.col_int_nokey OR alias1.pk
+ ) AS field1
+FROM ( t1 AS alias1 JOIN t2 AS alias2 ON alias2.pk )
+GROUP BY field1
+';
+
+EXECUTE stmt;
+EXECUTE stmt;
+
+DEALLOCATE PREPARE stmt;
+
+DROP TABLE t1, t2;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index dda9ab418a4..61554bdf420 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4271,6 +4271,22 @@ Item_cond::fix_fields(THD *thd, Item **ref)
if (abort_on_null)
item->top_level_item();
+ /*
+ replace degraded condition:
+ was: <field>
+ become: <field> = 1
+ */
+ if (item->type() == FIELD_ITEM)
+ {
+ Query_arena backup, *arena;
+ Item *new_item;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+ if ((new_item= new Item_func_ne(item, new Item_int(0, 1))))
+ li.replace(item= new_item);
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ }
+
// item can be substituted in fix_fields
if ((!item->fixed &&
item->fix_fields(thd, li.ref())) ||
@@ -5283,6 +5299,28 @@ Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */
}
+bool Item_func_not::fix_fields(THD *thd, Item **ref)
+{
+ if (args[0]->type() == FIELD_ITEM)
+ {
+ /* replace "NOT <field>" with "<filed> == 0" */
+ Query_arena backup, *arena;
+ Item *new_item;
+ bool rc= TRUE;
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+ if ((new_item= new Item_func_eq(args[0], new Item_int(0, 1))))
+ {
+ new_item->name= name;
+ rc= (*ref= new_item)->fix_fields(thd, ref);
+ }
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ return rc;
+ }
+ return Item_func::fix_fields(thd, ref);
+}
+
+
Item *Item_bool_rowready_func2::neg_transformer(THD *thd)
{
Item *item= negated_item();
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 25b636397a8..7239079c56f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -413,6 +413,7 @@ public:
enum Functype functype() const { return NOT_FUNC; }
const char *func_name() const { return "not"; }
Item *neg_transformer(THD *thd);
+ bool fix_fields(THD *, Item **);
virtual void print(String *str, enum_query_type query_type);
};
@@ -479,6 +480,8 @@ public:
longlong val_int();
enum Functype functype() const { return NOT_ALL_FUNC; }
const char *func_name() const { return "<not>"; }
+ bool fix_fields(THD *thd, Item **ref)
+ {return Item_func::fix_fields(thd, ref);}
virtual void print(String *str, enum_query_type query_type);
void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; };
void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; };