summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-03-28 20:25:31 +0200
committerSergei Golubchik <sergii@pisem.net>2012-03-28 20:25:31 +0200
commit867296c3edc4502093f7b706e7ac4c1670aa9515 (patch)
treeafcc8157b0b71a28edbcca6b862e6ca854fc743c
parent0d5adca0de0a51b1f0bd49045fc4062eac7d1d25 (diff)
parent6131d708e889cd4f93490c22bfee00d0728edfd2 (diff)
downloadmariadb-git-867296c3edc4502093f7b706e7ac4c1670aa9515.tar.gz
5.3 merge
-rw-r--r--mysql-test/r/innodb_ext_key.result8
-rw-r--r--mysql-test/r/subselect_sj2.result194
-rw-r--r--mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff16
-rw-r--r--mysql-test/r/subselect_sj2_jcl6.result204
-rw-r--r--mysql-test/r/subselect_sj2_mat.result194
-rw-r--r--mysql-test/suite/innodb/r/innodb-autoinc-61209.result30
-rw-r--r--mysql-test/suite/innodb/r/innodb-autoinc.result178
-rw-r--r--mysql-test/suite/innodb/t/innodb-autoinc-61209.test61
-rw-r--r--mysql-test/t/subselect_sj2.test138
-rw-r--r--mysys/thr_lock.c3
-rwxr-xr-xscripts/mytop.sh95
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_cmpfunc.h11
-rw-r--r--sql/opt_subselect.cc263
-rw-r--r--sql/sql_select.cc18
-rw-r--r--storage/innobase/handler/ha_innodb.cc67
-rw-r--r--storage/xtradb/handler/ha_innodb.cc67
17 files changed, 1337 insertions, 214 deletions
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index 0cdfb4f57a7..d2fb29a023c 100644
--- a/mysql-test/r/innodb_ext_key.result
+++ b/mysql-test/r/innodb_ext_key.result
@@ -681,9 +681,9 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t2)
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
a
@@ -694,9 +694,9 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t2)
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
a
diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result
index 0c41fef01ea..835403bb5b1 100644
--- a/mysql-test/r/subselect_sj2.result
+++ b/mysql-test/r/subselect_sj2.result
@@ -900,5 +900,199 @@ a b c
3 1 1
4 1 1
DROP TABLE t1,t2;
+#
+# BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output()
+# with index_merge+index_merge_sort_union+loosescan+semijoin
+#
+CREATE TABLE t1 (
+a INT, b VARCHAR(1), c INT,
+KEY(a), KEY(b)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5),
+(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9),
+(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4),
+(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0);
+CREATE TABLE t2 (
+pk INT, d VARCHAR(1), e INT,
+PRIMARY KEY(pk), KEY(d,e)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5),
+(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1),
+(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5),
+(15,'g',6),(16,'x',7),(17,'f',8);
+explain
+SELECT * FROM t1 WHERE b IN (
+SELECT d FROM t2, t1
+WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL b NULL NULL NULL 19
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index PRIMARY,d d 9 NULL 17 Using where; Using index
+2 MATERIALIZED t1 ref a a 5 test.t2.d 1 Using where; Using index
+SELECT * FROM t1 WHERE b IN (
+SELECT d FROM t2, t1
+WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+a b c
+DROP TABLE t1, t2;
+#
+# BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view
+#
+CREATE TABLE t1 (
+a VARCHAR(1),
+b VARCHAR(1) NOT NULL,
+KEY(a)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+('j','j'),('v','v'),('c','c'),('m','m'),('d','d'),
+('y','y'),('t','t'),('d','d'),('s','s'),('r','r'),
+('m','m'),('b','b'),('x','x'),('g','g'),('p','p'),
+('q','q'),('w','w'),('d','d'),('e','e');
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+# This query returned 6 rows instead of 19
+SELECT * FROM v1
+WHERE ( a, a ) IN (
+SELECT alias2.b, alias2.a
+FROM t1 AS alias1, t1 AS alias2
+WHERE alias2.b = alias1.a
+AND ( alias1.b >= alias1.a OR alias2.b = 'z' )
+);
+a b
+b b
+c c
+d d
+d d
+d d
+e e
+g g
+j j
+m m
+m m
+p p
+q q
+r r
+s s
+t t
+v v
+w w
+x x
+y y
+# Another testcase, without the VIEW:
+CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB;
+INSERT INTO t2 SELECT * FROM t1;
+INSERT INTO t2 SELECT * FROM t1;
+EXPLAIN
+SELECT * FROM t2
+WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+WHERE
+alias2.b = alias1.a AND
+(alias1.b >= alias1.a OR alias2.b = 'z'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 19
+1 PRIMARY t2 ref a a 4 test.alias1.a 1
+2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
+2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where
+SELECT * FROM t2
+WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+WHERE
+alias2.b = alias1.a AND
+(alias1.b >= alias1.a OR alias2.b = 'z'));
+a b
+b b
+b b
+c c
+c c
+d d
+d d
+d d
+d d
+d d
+d d
+e e
+e e
+g g
+g g
+j j
+j j
+m m
+m m
+m m
+m m
+p p
+p p
+q q
+q q
+r r
+r r
+s s
+s s
+t t
+t t
+v v
+v v
+w w
+w w
+x x
+x x
+y y
+y y
+DROP VIEW v1;
+DROP TABLE t1, t2;
+#
+# BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR
+# (this is a regression caused by the fix for BUG#951937)
+CREATE TABLE t1 ( a INT, b INT, c INT, d INT );
+INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8);
+SELECT * FROM t1
+WHERE a = d AND ( b = 50 AND b = d OR a = c );
+a b c d
+DROP TABLE t1;
+#
+# BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery
+#
+set @tmp_951283=@@optimizer_prune_level;
+SET optimizer_prune_level=0;
+CREATE TABLE t1 ( a INT ) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(10),(11),(12),(13),(14),(15),(16),
+(17),(18),(19),(20),(21),(22),(23);
+CREATE TABLE t2 (
+b INT PRIMARY KEY,
+c VARCHAR(1),
+d VARCHAR(1),
+KEY(c)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'),
+(5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'),
+(9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'),
+(13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'),
+(17,'q','q'),(18,'w','w'),(19,'d','d');
+EXPLAIN
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+WHERE alias5.b = alias4.b
+AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY alias3 ALL PRIMARY NULL NULL NULL 19 Using where
+1 PRIMARY alias4 ref PRIMARY,c c 4 test.alias3.d 1 Using index
+1 PRIMARY alias5 eq_ref PRIMARY PRIMARY 4 test.alias4.b 1 Using where; FirstMatch(alias3)
+1 PRIMARY alias2 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join)
+1 PRIMARY alias1 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join)
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+WHERE alias5.b = alias4.b
+AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+COUNT(*)
+3724
+set optimizer_prune_level=@tmp_951283;
+DROP TABLE t1,t2;
# This must be the last in the file:
set optimizer_switch=@subselect_sj2_tmp;
diff --git a/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff b/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff
index 528d3ac08ea..30df3c42a0d 100644
--- a/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff
+++ b/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff
@@ -1,5 +1,5 @@
---- r/subselect_sj2_jcl6.result 2012-01-11 18:05:14.000000000 +0100
-+++ r/subselect_sj2_jcl6.reject 2012-02-07 12:52:32.000000000 +0100
+--- r/subselect_sj2_jcl6.result 2012-03-28 20:10:41.000000000 +0200
++++ r/subselect_sj2_jcl6,innodb_plugin.reject 2012-03-28 20:21:14.000000000 +0200
@@ -81,7 +81,7 @@
explain select * from t3 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
@@ -18,3 +18,15 @@
2 MATERIALIZED t0 ALL NULL NULL NULL NULL 10 Using where
select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5);
a b pk1 pk2
+@@ -1006,9 +1006,9 @@
+ (alias1.b >= alias1.a OR alias2.b = 'z'));
+ id select_type table type possible_keys key key_len ref rows Extra
+ 1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 19
+-1 PRIMARY t2 ref a a 4 test.alias1.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
++1 PRIMARY t2 ref a a 4 test.alias1.a 1
+ 2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
+-2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
++2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where
+ SELECT * FROM t2
+ WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+ WHERE
diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result
index 073f1619b91..c4c8a858b68 100644
--- a/mysql-test/r/subselect_sj2_jcl6.result
+++ b/mysql-test/r/subselect_sj2_jcl6.result
@@ -914,6 +914,200 @@ a b c
3 1 1
4 1 1
DROP TABLE t1,t2;
+#
+# BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output()
+# with index_merge+index_merge_sort_union+loosescan+semijoin
+#
+CREATE TABLE t1 (
+a INT, b VARCHAR(1), c INT,
+KEY(a), KEY(b)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5),
+(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9),
+(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4),
+(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0);
+CREATE TABLE t2 (
+pk INT, d VARCHAR(1), e INT,
+PRIMARY KEY(pk), KEY(d,e)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5),
+(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1),
+(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5),
+(15,'g',6),(16,'x',7),(17,'f',8);
+explain
+SELECT * FROM t1 WHERE b IN (
+SELECT d FROM t2, t1
+WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL b NULL NULL NULL 19
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index PRIMARY,d d 9 NULL 17 Using where; Using index
+2 MATERIALIZED t1 ref a a 5 test.t2.d 1 Using where; Using index
+SELECT * FROM t1 WHERE b IN (
+SELECT d FROM t2, t1
+WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+a b c
+DROP TABLE t1, t2;
+#
+# BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view
+#
+CREATE TABLE t1 (
+a VARCHAR(1),
+b VARCHAR(1) NOT NULL,
+KEY(a)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+('j','j'),('v','v'),('c','c'),('m','m'),('d','d'),
+('y','y'),('t','t'),('d','d'),('s','s'),('r','r'),
+('m','m'),('b','b'),('x','x'),('g','g'),('p','p'),
+('q','q'),('w','w'),('d','d'),('e','e');
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+# This query returned 6 rows instead of 19
+SELECT * FROM v1
+WHERE ( a, a ) IN (
+SELECT alias2.b, alias2.a
+FROM t1 AS alias1, t1 AS alias2
+WHERE alias2.b = alias1.a
+AND ( alias1.b >= alias1.a OR alias2.b = 'z' )
+);
+a b
+b b
+c c
+d d
+d d
+d d
+e e
+g g
+j j
+m m
+m m
+p p
+q q
+r r
+s s
+t t
+v v
+w w
+x x
+y y
+# Another testcase, without the VIEW:
+CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB;
+INSERT INTO t2 SELECT * FROM t1;
+INSERT INTO t2 SELECT * FROM t1;
+EXPLAIN
+SELECT * FROM t2
+WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+WHERE
+alias2.b = alias1.a AND
+(alias1.b >= alias1.a OR alias2.b = 'z'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 19
+1 PRIMARY t2 ref a a 4 test.alias1.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
+2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+SELECT * FROM t2
+WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+WHERE
+alias2.b = alias1.a AND
+(alias1.b >= alias1.a OR alias2.b = 'z'));
+a b
+b b
+b b
+c c
+c c
+d d
+d d
+d d
+d d
+d d
+d d
+e e
+e e
+g g
+g g
+j j
+j j
+m m
+m m
+m m
+m m
+p p
+p p
+q q
+q q
+r r
+r r
+s s
+s s
+t t
+t t
+v v
+v v
+w w
+w w
+x x
+x x
+y y
+y y
+DROP VIEW v1;
+DROP TABLE t1, t2;
+#
+# BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR
+# (this is a regression caused by the fix for BUG#951937)
+CREATE TABLE t1 ( a INT, b INT, c INT, d INT );
+INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8);
+SELECT * FROM t1
+WHERE a = d AND ( b = 50 AND b = d OR a = c );
+a b c d
+DROP TABLE t1;
+#
+# BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery
+#
+set @tmp_951283=@@optimizer_prune_level;
+SET optimizer_prune_level=0;
+CREATE TABLE t1 ( a INT ) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(10),(11),(12),(13),(14),(15),(16),
+(17),(18),(19),(20),(21),(22),(23);
+CREATE TABLE t2 (
+b INT PRIMARY KEY,
+c VARCHAR(1),
+d VARCHAR(1),
+KEY(c)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'),
+(5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'),
+(9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'),
+(13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'),
+(17,'q','q'),(18,'w','w'),(19,'d','d');
+EXPLAIN
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+WHERE alias5.b = alias4.b
+AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY alias3 ALL PRIMARY NULL NULL NULL 19 Using where
+1 PRIMARY alias4 ref PRIMARY,c c 4 test.alias3.d 1 Using index
+1 PRIMARY alias5 eq_ref PRIMARY PRIMARY 4 test.alias4.b 1 Using where; FirstMatch(alias3)
+1 PRIMARY alias2 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join)
+1 PRIMARY alias1 ALL NULL NULL NULL NULL 14 Using join buffer (incremental, BNL join)
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+WHERE alias5.b = alias4.b
+AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+COUNT(*)
+3724
+set optimizer_prune_level=@tmp_951283;
+DROP TABLE t1,t2;
# This must be the last in the file:
set optimizer_switch=@subselect_sj2_tmp;
#
@@ -935,9 +1129,9 @@ SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 FirstMatch(t3)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
+1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t3); Using join buffer (incremental, BNL join)
1 PRIMARY t1 ref b b 4 test.t3.b 1 Using index
-1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t1)
SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
b c
@@ -963,9 +1157,9 @@ EXPLAIN
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2
-1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t1)
+1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where
+1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t2)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
pk a b
1 6 8
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index f15492c7322..b535f37ee90 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -902,6 +902,200 @@ a b c
3 1 1
4 1 1
DROP TABLE t1,t2;
+#
+# BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output()
+# with index_merge+index_merge_sort_union+loosescan+semijoin
+#
+CREATE TABLE t1 (
+a INT, b VARCHAR(1), c INT,
+KEY(a), KEY(b)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5),
+(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9),
+(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4),
+(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0);
+CREATE TABLE t2 (
+pk INT, d VARCHAR(1), e INT,
+PRIMARY KEY(pk), KEY(d,e)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5),
+(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1),
+(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5),
+(15,'g',6),(16,'x',7),(17,'f',8);
+explain
+SELECT * FROM t1 WHERE b IN (
+SELECT d FROM t2, t1
+WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL b NULL NULL NULL 19
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index PRIMARY,d d 9 NULL 17 Using where; Using index
+2 MATERIALIZED t1 ref a a 5 test.t2.d 1 Using where; Using index
+SELECT * FROM t1 WHERE b IN (
+SELECT d FROM t2, t1
+WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+a b c
+DROP TABLE t1, t2;
+#
+# BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view
+#
+CREATE TABLE t1 (
+a VARCHAR(1),
+b VARCHAR(1) NOT NULL,
+KEY(a)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+('j','j'),('v','v'),('c','c'),('m','m'),('d','d'),
+('y','y'),('t','t'),('d','d'),('s','s'),('r','r'),
+('m','m'),('b','b'),('x','x'),('g','g'),('p','p'),
+('q','q'),('w','w'),('d','d'),('e','e');
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+# This query returned 6 rows instead of 19
+SELECT * FROM v1
+WHERE ( a, a ) IN (
+SELECT alias2.b, alias2.a
+FROM t1 AS alias1, t1 AS alias2
+WHERE alias2.b = alias1.a
+AND ( alias1.b >= alias1.a OR alias2.b = 'z' )
+);
+a b
+b b
+c c
+d d
+d d
+d d
+e e
+g g
+j j
+m m
+m m
+p p
+q q
+r r
+s s
+t t
+v v
+w w
+x x
+y y
+# Another testcase, without the VIEW:
+CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB;
+INSERT INTO t2 SELECT * FROM t1;
+INSERT INTO t2 SELECT * FROM t1;
+EXPLAIN
+SELECT * FROM t2
+WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+WHERE
+alias2.b = alias1.a AND
+(alias1.b >= alias1.a OR alias2.b = 'z'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 19
+1 PRIMARY t2 ref a a 4 test.alias1.a 1
+2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
+2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where
+SELECT * FROM t2
+WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+WHERE
+alias2.b = alias1.a AND
+(alias1.b >= alias1.a OR alias2.b = 'z'));
+a b
+b b
+b b
+c c
+c c
+d d
+d d
+d d
+d d
+d d
+d d
+e e
+e e
+g g
+g g
+j j
+j j
+m m
+m m
+m m
+m m
+p p
+p p
+q q
+q q
+r r
+r r
+s s
+s s
+t t
+t t
+v v
+v v
+w w
+w w
+x x
+x x
+y y
+y y
+DROP VIEW v1;
+DROP TABLE t1, t2;
+#
+# BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR
+# (this is a regression caused by the fix for BUG#951937)
+CREATE TABLE t1 ( a INT, b INT, c INT, d INT );
+INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8);
+SELECT * FROM t1
+WHERE a = d AND ( b = 50 AND b = d OR a = c );
+a b c d
+DROP TABLE t1;
+#
+# BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery
+#
+set @tmp_951283=@@optimizer_prune_level;
+SET optimizer_prune_level=0;
+CREATE TABLE t1 ( a INT ) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(10),(11),(12),(13),(14),(15),(16),
+(17),(18),(19),(20),(21),(22),(23);
+CREATE TABLE t2 (
+b INT PRIMARY KEY,
+c VARCHAR(1),
+d VARCHAR(1),
+KEY(c)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'),
+(5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'),
+(9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'),
+(13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'),
+(17,'q','q'),(18,'w','w'),(19,'d','d');
+EXPLAIN
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+WHERE alias5.b = alias4.b
+AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY alias3 ALL PRIMARY NULL NULL NULL 19 Using where
+1 PRIMARY alias4 ref PRIMARY,c c 4 test.alias3.d 1 Using index
+1 PRIMARY alias5 eq_ref PRIMARY PRIMARY 4 test.alias4.b 1 Using where; FirstMatch(alias3)
+1 PRIMARY alias2 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join)
+1 PRIMARY alias1 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join)
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+WHERE alias5.b = alias4.b
+AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+COUNT(*)
+3724
+set optimizer_prune_level=@tmp_951283;
+DROP TABLE t1,t2;
# This must be the last in the file:
set optimizer_switch=@subselect_sj2_tmp;
set optimizer_switch=default;
diff --git a/mysql-test/suite/innodb/r/innodb-autoinc-61209.result b/mysql-test/suite/innodb/r/innodb-autoinc-61209.result
new file mode 100644
index 00000000000..daa9d54df4c
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-autoinc-61209.result
@@ -0,0 +1,30 @@
+DROP TABLE IF EXISTS bug_61209;
+CREATE TABLE bug_61209 (a INT auto_increment, PRIMARY KEY(a)) ENGINE=InnoDB;
+INSERT INTO bug_61209 VALUES (), ();
+
+# Connect con1
+
+# Connect con2
+
+# Connection con1
+SET SESSION auto_increment_increment=3;
+SET SESSION auto_increment_offset=2;
+SELECT GET_LOCK('a', 10);
+
+# Connection con2
+SET SESSION auto_increment_increment=3;
+SET SESSION auto_increment_offset=2;
+INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL + GET_LOCK('a', 10));
+
+# Connection con1 reap
+GET_LOCK('a', 10)
+1
+INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL);
+SELECT RELEASE_LOCK('a');
+
+# Connection con2 reap
+
+# Connection con1 reap
+RELEASE_LOCK('a')
+1
+DROP TABLE bug_61209;
diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result
index 0c8d16f27fb..fa821372337 100644
--- a/mysql-test/suite/innodb/r/innodb-autoinc.result
+++ b/mysql-test/suite/innodb/r/innodb-autoinc.result
@@ -366,7 +366,7 @@ c1
310
400
1000
-1010
+1110
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
@@ -648,7 +648,7 @@ t2 CREATE TABLE `t2` (
`n` int(10) unsigned NOT NULL,
`o` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`m`)
-) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 ;
SHOW CREATE TABLE t1;
Table Create Table
@@ -657,7 +657,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 ;
SELECT * FROM t1;
a b c
@@ -671,16 +671,16 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -688,7 +688,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SELECT * FROM t1;
a b c
@@ -702,21 +702,21 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
-23 1 FALSE
-24 2 FALSE
-25 3 FALSE
-26 4 FALSE
-27 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
+31 1 FALSE
+32 2 FALSE
+33 3 FALSE
+34 4 FALSE
+35 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -724,7 +724,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SELECT * FROM t1;
a b c
@@ -738,26 +738,26 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
-23 1 FALSE
-24 2 FALSE
-25 3 FALSE
-26 4 FALSE
-27 5 FALSE
-30 1 FALSE
-31 2 FALSE
-32 3 FALSE
-33 4 FALSE
-34 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
+31 1 FALSE
+32 2 FALSE
+33 3 FALSE
+34 4 FALSE
+35 5 FALSE
+38 1 FALSE
+39 2 FALSE
+40 3 FALSE
+41 4 FALSE
+42 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -765,7 +765,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SHOW CREATE TABLE t1;
Table Create Table
@@ -774,7 +774,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SHOW CREATE TABLE t1;
Table Create Table
@@ -783,7 +783,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SELECT * FROM t1;
a b c
@@ -797,41 +797,41 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
-23 1 FALSE
-24 2 FALSE
-25 3 FALSE
-26 4 FALSE
-27 5 FALSE
-30 1 FALSE
-31 2 FALSE
-32 3 FALSE
-33 4 FALSE
-34 5 FALSE
-37 1 FALSE
-38 2 FALSE
-39 3 FALSE
-40 4 FALSE
-41 5 FALSE
-44 1 FALSE
-45 2 FALSE
-46 3 FALSE
-47 4 FALSE
-48 5 FALSE
-51 1 FALSE
-52 2 FALSE
-53 3 FALSE
-54 4 FALSE
-55 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
+31 1 FALSE
+32 2 FALSE
+33 3 FALSE
+34 4 FALSE
+35 5 FALSE
+38 1 FALSE
+39 2 FALSE
+40 3 FALSE
+41 4 FALSE
+42 5 FALSE
+45 1 FALSE
+46 2 FALSE
+47 3 FALSE
+48 4 FALSE
+49 5 FALSE
+52 1 FALSE
+53 2 FALSE
+54 3 FALSE
+55 4 FALSE
+56 5 FALSE
+59 1 FALSE
+60 2 FALSE
+61 3 FALSE
+62 4 FALSE
+63 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -839,7 +839,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-61209.test b/mysql-test/suite/innodb/t/innodb-autoinc-61209.test
new file mode 100644
index 00000000000..12bdc236b90
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-autoinc-61209.test
@@ -0,0 +1,61 @@
+# This is the test case for bug #61209 - duplicate key errors
+# when using auto_increment_increment > 1 and auto_increment_offset > 1
+#
+--source include/have_innodb.inc
+
+#
+# Precautionary clean up.
+#
+--disable_warnings
+DROP TABLE IF EXISTS bug_61209;
+--enable_warnings
+
+#
+# Create test data.
+#
+CREATE TABLE bug_61209 (a INT auto_increment, PRIMARY KEY(a)) ENGINE=InnoDB;
+
+INSERT INTO bug_61209 VALUES (), ();
+
+--echo
+--echo # Connect con1
+--connect (con1,localhost,root,,)
+--echo
+--echo # Connect con2
+--connect (con2,localhost,root,,)
+
+--echo
+--echo # Connection con1
+--connection con1
+SET SESSION auto_increment_increment=3;
+SET SESSION auto_increment_offset=2;
+send SELECT GET_LOCK('a', 10);
+
+--echo
+--echo # Connection con2
+--connection con2
+SET SESSION auto_increment_increment=3;
+SET SESSION auto_increment_offset=2;
+send INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL + GET_LOCK('a', 10));
+
+--echo
+--echo # Connection con1 reap
+--connection con1
+reap;
+INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL);
+send SELECT RELEASE_LOCK('a');
+
+--echo
+--echo # Connection con2 reap
+--connection con2
+reap;
+
+--echo
+--echo # Connection con1 reap
+--connection con1
+reap;
+
+#
+# Clean up
+#
+DROP TABLE bug_61209;
diff --git a/mysql-test/t/subselect_sj2.test b/mysql-test/t/subselect_sj2.test
index ede631f32be..04d1f9e9d9c 100644
--- a/mysql-test/t/subselect_sj2.test
+++ b/mysql-test/t/subselect_sj2.test
@@ -1093,5 +1093,143 @@ SELECT * FROM t1, t2 WHERE c IN (SELECT c FROM t1, t2 WHERE a = b);
DROP TABLE t1,t2;
+--echo #
+--echo # BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output()
+--echo # with index_merge+index_merge_sort_union+loosescan+semijoin
+--echo #
+CREATE TABLE t1 (
+ a INT, b VARCHAR(1), c INT,
+ KEY(a), KEY(b)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES
+(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5),
+(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9),
+(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4),
+(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0);
+
+CREATE TABLE t2 (
+ pk INT, d VARCHAR(1), e INT,
+ PRIMARY KEY(pk), KEY(d,e)
+) ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES
+(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5),
+(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1),
+(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5),
+(15,'g',6),(16,'x',7),(17,'f',8);
+
+explain
+SELECT * FROM t1 WHERE b IN (
+ SELECT d FROM t2, t1
+ WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+SELECT * FROM t1 WHERE b IN (
+ SELECT d FROM t2, t1
+ WHERE a = d AND ( pk < 2 OR d = 'z' )
+);
+
+DROP TABLE t1, t2;
+
+--echo #
+--echo # BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view
+--echo #
+CREATE TABLE t1 (
+ a VARCHAR(1),
+ b VARCHAR(1) NOT NULL,
+ KEY(a)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+('j','j'),('v','v'),('c','c'),('m','m'),('d','d'),
+('y','y'),('t','t'),('d','d'),('s','s'),('r','r'),
+('m','m'),('b','b'),('x','x'),('g','g'),('p','p'),
+('q','q'),('w','w'),('d','d'),('e','e');
+
+CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
+
+--echo # This query returned 6 rows instead of 19
+--sorted_result
+SELECT * FROM v1
+WHERE ( a, a ) IN (
+ SELECT alias2.b, alias2.a
+ FROM t1 AS alias1, t1 AS alias2
+ WHERE alias2.b = alias1.a
+ AND ( alias1.b >= alias1.a OR alias2.b = 'z' )
+);
+
+--echo # Another testcase, without the VIEW:
+CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB;
+INSERT INTO t2 SELECT * FROM t1;
+INSERT INTO t2 SELECT * FROM t1;
+EXPLAIN
+SELECT * FROM t2
+ WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+ WHERE
+ alias2.b = alias1.a AND
+ (alias1.b >= alias1.a OR alias2.b = 'z'));
+
+--sorted_result
+SELECT * FROM t2
+ WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
+ WHERE
+ alias2.b = alias1.a AND
+ (alias1.b >= alias1.a OR alias2.b = 'z'));
+
+DROP VIEW v1;
+DROP TABLE t1, t2;
+
+--echo #
+--echo # BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR
+--echo # (this is a regression caused by the fix for BUG#951937)
+CREATE TABLE t1 ( a INT, b INT, c INT, d INT );
+INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8);
+
+SELECT * FROM t1
+WHERE a = d AND ( b = 50 AND b = d OR a = c );
+DROP TABLE t1;
+
+--echo #
+--echo # BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery
+--echo #
+set @tmp_951283=@@optimizer_prune_level;
+SET optimizer_prune_level=0;
+
+CREATE TABLE t1 ( a INT ) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+ (10),(11),(12),(13),(14),(15),(16),
+ (17),(18),(19),(20),(21),(22),(23);
+
+CREATE TABLE t2 (
+ b INT PRIMARY KEY,
+ c VARCHAR(1),
+ d VARCHAR(1),
+ KEY(c)
+) ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES
+ (1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'),
+ (5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'),
+ (9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'),
+ (13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'),
+ (17,'q','q'),(18,'w','w'),(19,'d','d');
+
+EXPLAIN
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+ SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+ WHERE alias5.b = alias4.b
+ AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+
+SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3
+WHERE alias3.d IN (
+ SELECT alias4.c FROM t2 AS alias4, t2 AS alias5
+ WHERE alias5.b = alias4.b
+ AND ( alias5.b >= alias3.b OR alias5.c != alias3.c )
+);
+
+set optimizer_prune_level=@tmp_951283;
+DROP TABLE t1,t2;
+
--echo # This must be the last in the file:
set optimizer_switch=@subselect_sj2_tmp;
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index e99956f9c8f..a7cbfa07db2 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -1168,6 +1168,9 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner,
if (result != THR_LOCK_SUCCESS)
{ /* Aborted */
thr_multi_unlock(data,(uint) (pos-data), 0);
+ /* Mark all requested locks as TL_UNLOCK (to simplify lock checking) */
+ for ( ; pos < end ; pos++)
+ (*pos)->type= TL_UNLOCK;
DBUG_RETURN(result);
}
DEBUG_SYNC_C("thr_multi_lock_after_thr_lock");
diff --git a/scripts/mytop.sh b/scripts/mytop.sh
index 7cec85e2136..a36fddf7368 100755
--- a/scripts/mytop.sh
+++ b/scripts/mytop.sh
@@ -18,8 +18,10 @@ use DBI;
use Getopt::Long;
use Socket;
use List::Util qw(min max);
+use File::Basename;
$main::VERSION = "1.9a";
+my $path_for_script= dirname($0);
$|=1;
$0 = 'mytop';
@@ -95,7 +97,8 @@ my %config = (
slow => 10, # slow query time
socket => '',
sort => 0, # default or reverse sort ("s")
- user => 'root'
+ user => 'root',
+ fullqueries => 0
);
my %qcache = (); ## The query cache--used for full query info support.
@@ -112,6 +115,17 @@ my $CLEAR = $WIN ? '': `clear`;
my $RM_RESET = 0;
my $RM_NOBLKRD = 3; ## using 4 traps Ctrl-C :-(
+# Add options from .my.cnf first
+
+my $my_print_defaults;
+if (!defined($my_print_defaults=my_which("my_print_defaults")))
+{
+ print "Warning: Can't find my_print_defaults. Please add it to your PATH!\n";
+ exit(1);
+}
+
+unshift @ARGV, split "\n", `$my_print_defaults client mytop`;
+
## Read the user's config file, if it exists.
my $config = "$ENV{HOME}/.mytop";
@@ -160,7 +174,8 @@ GetOptions(
"long_nums!" => \$config{long_nums},
"mode|m=s" => \$config{mode},
"slow=i" => \$config{slow},
- "sort=s" => \$config{sort}
+ "sort=s" => \$config{sort},
+ "fullqueries|L!" => \$config{fullqueries}
);
## User may have put the port with the host.
@@ -744,6 +759,25 @@ while (1)
{
$config{mode} = 'status';
}
+
+ ## L - full queries toggle
+
+ if ($key eq 'L')
+ {
+ if ($config{fullqueries})
+ {
+ $config{fullqueries} = 0;
+ print RED(), "-- full queries OFF --", RESET();
+ sleep 1;
+ }
+ else
+ {
+ $config{fullqueries} = 1;
+ print RED(), "-- full queries ON --", RESET();
+ sleep 1;
+ }
+ }
+
}
ReadMode($RM_RESET) unless $config{batchmode};
@@ -1115,7 +1149,13 @@ sub GetData()
my $state= $width <= 80 ? 6 : int(min(6+($width-80)/3, 15));
my $free = $width - $used - ($state - 6);
my $format= "%9s %8s %15s %9s %6s %5s %6s %${state}s %-.${free}s\n";
- my $format2= "%9d %8.8s %15.15s %9.9s %6d %5.1f %6.6s %${state}.${state}s %-${free}.${free}s\n";
+ my $format2;
+ if ($config{fullqueries})
+ {
+ $format2 = "%9d %8.8s %15.15s %9.9s %6d %5.1f %6.6s %${state}.${state}s %-${free}s\n";
+ } else {
+ $format2 = "%9d %8.8s %15.15s %9.9s %6d %5.1f %6.6s %${state}.${state}s %-${free}.${free}s\n";
+ }
print BOLD() if ($HAS_COLOR);
printf $format,
@@ -1244,7 +1284,12 @@ sub GetData()
if ($thread->{Info})
{
- $smInfo = substr $thread->{Info}, 0, $free;
+ if ($config{fullqueries})
+ {
+ $smInfo = $thread->{Info};
+ } else {
+ $smInfo = substr $thread->{Info}, 0, $free;
+ }
}
# if ($thread->{State})
# {
@@ -1690,6 +1735,7 @@ Origional work by Jeremy D. Zawodny <${YELLOW}Jeremy\@Zawodny.com${RESET}>
u - show only a specific user
V - show variablesi
: - enter a command (not yet implemented)
+ L - show full queries (do not strip to terminal width)
Base version from ${GREEN}http://www.mysqlfanboy.com/mytop${RESET}
This version comes as part of the ${GREEN}MariaDB${RESET} distribution.
@@ -1789,6 +1835,35 @@ sub FindProg($)
return $found;
}
+####
+#### my_which is used, because we can't assume that every system has the
+#### which -command. my_which can take only one argument at a time.
+#### Return values: requested system command with the first found path,
+#### or undefined, if not found.
+####
+
+sub my_which
+{
+ my ($command) = @_;
+ my (@paths, $path);
+
+ return $command if (-f $command && -x $command);
+
+ # Check first if this is a source distribution, then if this binary
+ # distribution and last in the path
+
+ push @paths, "./extra";
+ push @paths, $path_for_script;
+ push @paths, split(':', $ENV{'PATH'});
+
+ foreach $path (@paths)
+ {
+ $path .= "/$command";
+ return $path if (-f $path && -x $path);
+ }
+ return undef();
+}
+
=pod
=head1 SYNOPSIS
@@ -2056,11 +2131,15 @@ command-line arguments are applied.
=head2 Config File
Instead of always using bulky command-line parameters, you can also
-use a config file in your home directory (C<~/.mytop>). If present,
-B<mytop> will read it automatically. It is read I<before> any of your
+use a config files for the default value of your options.
+
+mytop will first read the [client] and [mytop] sections from your
+my.cnf files. After that it will read the (C<~/.mytop>) file from your
+home directory (if present). These are read I<before> any of your
command-line arguments are processed, so your command-line arguments
will override directives in the config file.
+
Here is a sample config file C<~/.mytop> which implements the defaults
described above.
@@ -2275,6 +2354,10 @@ Many thanks go to these fine folks:
=over
+=Item Jean Weisbuch
+
+Added --fullqueries and reading of .my.cnf
+
=item Sami Ahlroos (sami@avis-net.de)
Suggested the idle/noidle stuff.
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f5dc74c389c..d3251bc1fb3 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5463,7 +5463,7 @@ Item *Item_bool_rowready_func2::negated_item()
*/
Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
- : Item_bool_func(), eval_item(0), cond_false(0)
+ : Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL)
{
const_item_cache= 0;
with_const= with_const_item;
@@ -5486,7 +5486,7 @@ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
*/
Item_equal::Item_equal(Item_equal *item_equal)
- : Item_bool_func(), eval_item(0), cond_false(0)
+ : Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL)
{
const_item_cache= 0;
List_iterator_fast<Item> li(item_equal->equal_items);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 95d797c62cf..38dbc2901c6 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1693,9 +1693,16 @@ class Item_equal: public Item_bool_func
as datetimes. The comparator is used only if compare_as_dates=TRUE
*/
Arg_comparator cmp;
+
+ /*
+ For Item_equal objects inside an OR clause: one of the fields that were
+ used in the original equality.
+ */
+ Item_field *context_field;
public:
inline Item_equal()
- : Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0)
+ : Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0),
+ context_field(NULL)
{ const_item_cache=0 ;}
Item_equal(Item *f1, Item *f2, bool with_const_item);
Item_equal(Item_equal *item_equal);
@@ -1722,6 +1729,8 @@ public:
Item *transform(Item_transformer transformer, uchar *arg);
virtual void print(String *str, enum_query_type query_type);
CHARSET_INFO *compare_collation();
+
+ void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
friend class Item_equal_fields_iterator;
friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
Item_equal *item_equal);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index fe9b8da3a24..202e97dc190 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -188,6 +188,252 @@
*/
+/*
+EqualityPropagationAndSjmNests
+******************************
+
+Equalities are used for:
+P1. Equality propagation
+P2. Equality substitution [for a certain join order]
+
+The equality propagation is not affected by SJM nests. In fact, it is done
+before we determine the execution plan, i.e. before we even know we will use
+SJM-nests for execution.
+
+The equality substitution is affected.
+
+Substitution without SJMs
+=========================
+When one doesn't have SJM nests, tables have a strict join order:
+
+ --------------------------------->
+ t1 -- t2 -- t3 -- t4 --- t5
+
+
+ ? ^
+ \
+ --(part-of-WHERE)
+
+
+parts WHERE/ON and ref. expressions are attached at some point along the axis.
+Expression is allowed to refer to a table column if the table is to the left of
+the attachment point. For any given expression, we have a goal:
+
+ "Move leftmost allowed attachment point as much as possible to the left"
+
+Substitution with SJMs - task setting
+=====================================
+
+When SJM nests are present, there is no global strict table ordering anymore:
+
+
+ --------------------------------->
+
+ ot1 -- ot2 --- sjm -- ot4 --- ot5
+ |
+ | Main execution
+ - - - - - - - - - - - - - - - - - - - - - - - -
+ | Materialization
+ it1 -- it2 --/
+
+
+Besides that, we must take into account that
+ - values for outer table columns, otN.col, are inaccessible at
+ materialization step (SJM-RULE)
+ - values for inner table columns, itN.col, are inaccessible at Main execution
+ step, except for SJ-Materialization-Scan and columns that are in the
+ subquery's select list. (SJM-RULE)
+
+Substitution with SJMs - solution
+=================================
+
+First, we introduce global strict table ordering like this:
+
+ ot1 - ot2 --\ /--- ot3 -- ot5
+ \--- it1 --- it2 --/
+
+Now, let's see how to meet (SJM-RULE).
+
+SJ-Materialization is only applicable for uncorrelated subqueries. From this, it
+follows that any multiple equality will either
+1. include only columns of outer tables, or
+2. include only columns of inner tables, or
+3. include columns of inner and outer tables, joined together through one
+ of IN-equalities.
+
+Cases #1 and #2 can be handled in the same way as with regular inner joins.
+
+Case #3 requires special handling, so that we don't construct violations of
+(SJM-RULE). Let's consider possible ways to build violations.
+
+Equality propagation starts with the clause in this form
+
+ top_query_where AND subquery_where AND in_equalities
+
+First, it builds multi-equalities. It can also build a mixed multi-equality
+
+ multiple-equal(ot1.col, ot2.col, ... it1.col, itN.col)
+
+Multi-equalities are pushed down the OR-clauses in top_query_where and in
+subquery_where, so it's possible that clauses like this one are built:
+
+ subquery_cond OR (multiple-equal(it1.col, ot1.col,...) AND ...)
+ ^^^^^^^^^^^^^ \
+ | this must be evaluated
+ \- can only be evaluated at the main phase.
+ at the materialization phase
+
+Finally, equality substitution is started. It does two operations:
+
+
+1. Field reference substitution
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+(In the code, this is Item_field::replace_equal_field)
+
+This is a process of replacing each reference to "tblX.col"
+with the first element of the multi-equality. (REF-SUBST-ORIG)
+
+This behaviour can cause problems with Semi-join nests. Suppose, we have a
+condition:
+
+ func(it1.col, it2.col)
+
+and a multi-equality(ot1.col, it1.col). Then, reference to "it1.col" will be
+replaced with "ot1.col", constructing a condition
+
+ func(ot1.col, it2.col)
+
+which will be a violation of (SJM-RULE).
+
+In order to avoid this, (REF-SUBST-ORIG) is amended as follows:
+
+- references to tables "itX.col" that are inner wrt some SJM nest, are
+ replaced with references to the first inner table from the same SJM nest.
+
+- references to top-level tables "otX.col" are replaced with references to
+ the first element of the multi-equality, no matter if that first element is
+ a column of a top-level table or of table from some SJM nest.
+ (REF-SUBST-SJM)
+
+ The case where the first element is a table from an SJM nest $SJM is ok,
+ because it can be proven that $SJM uses SJ-Materialization-Scan, and
+ "unpacks" correct column values to the first element during the main
+ execution phase.
+
+2. Item_equal elimination
+~~~~~~~~~~~~~~~~~~~~~~~~~
+(In the code: eliminate_item_equal) This is a process of taking
+
+ multiple-equal(a,b,c,d,e)
+
+and replacing it with an equivalent expression which is an AND of pair-wise
+equalities:
+
+ a=b AND a=c AND ...
+
+The equalities are picked such that for any given join prefix (t1,t2...) the
+subset of equalities that can be evaluated gives the most restrictive
+filtering.
+
+Without SJM nests, it is sufficient to compare every multi-equality member
+with the first one:
+
+ elem1=elem2 AND elem1=elem3 AND elem1=elem4 ...
+
+When SJM nests are present, we should take care not to construct equalities
+that violate the (SJM-RULE). This is achieved by generating separate sets of
+equalites for top-level tables and for inner tables. That is, for the join
+order
+
+ ot1 - ot2 --\ /--- ot3 -- ot5
+ \--- it1 --- it2 --/
+
+we will generate
+ ot1.col=ot2.col
+ ot1.col=ot3.col
+ ot1.col=ot5.col
+ it2.col=it1.col
+
+
+2.1 The problem with Item_equals and ORs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+As has been mentioned above, multiple equalities are pushed down into OR
+clauses, possibly building clauses like this:
+
+ func(it.col2) OR multiple-equal(it1.col1, it1.col2, ot1.col) (1)
+
+where the first part of the clause has references to inner tables, while the
+second has references to the top-level tables, which is a violation of
+(SJM-RULE).
+
+AND-clauses of this kind do not create problems, because make_cond_for_table()
+will take them apart. OR-clauses will not be split. It is possible to
+split-out the part that's dependent on the inner table:
+
+ func(it.col2) OR it1.col1=it1.col2
+
+but this is a less-restrictive condition than condition (1). Current execution
+scheme will still try to generate the "remainder" condition:
+
+ func(it.col2) OR it1.col1=ot1.col
+
+which is a violation of (SJM-RULE).
+
+QQ: "ot1.col=it1.col" is checked at the upper level. Why was it not removed
+here?
+AA: because has a proper subset of conditions that are found on this level.
+ consider a join order of ot, sjm(it)
+ and a condition
+ ot.col=it.col AND ( ot.col=it.col='foo' OR it.col2='bar')
+
+ we will produce:
+ table ot: nothing
+ table it: ot.col=it.col AND (ot.col='foo' OR it.col2='bar')
+ ^^^^ ^^^^^^^^^^^^^^^^
+ | \ the problem is that
+ | this part condition didnt
+ | receive a substitution
+ |
+ +--- it was correct to subst, 'ot' is
+ the left-most.
+
+
+Does it make sense to push "inner=outer" down into ORs?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Yes. Consider the query:
+
+ select * from ot
+ where ot.col in (select it.col from it where (it.col='foo' OR it.col='bar'))
+
+here, it may be useful to infer that
+
+ (ot.col='foo' OR ot.col='bar') (CASE-FOR-SUBST)
+
+and attach that condition to the table 'ot'.
+
+Possible solutions for Item_equals and ORs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Solution #1
+~~~~~~~~~~~
+Let make_cond_for_table() chop analyze the OR clauses it has produced and
+discard them if they violate (SJM-RULE). This solution would allow to handle
+cases like (CASE-FOR-SUBST) at the expense of making semantics of
+make_cond_for_table() complicated.
+
+Solution #2
+~~~~~~~~~~~
+Before the equality propagation phase, none of the OR clauses violate the
+(SJM-RULE). This way, if we remember which tables the original equality
+referred to, we can only generate equalities that refer to the outer (or inner)
+tables. Note that this will disallow handling of cases like (CASE-FOR-SUBST).
+
+Currently, solution #2 is implemented.
+
+*/
+
static
bool subquery_types_allow_materialization(Item_in_subselect *in_subs);
@@ -2673,6 +2919,8 @@ bool Firstmatch_picker::check_qep(JOIN *join,
}
}
}
+ else
+ invalidate_firstmatch_prefix();
return FALSE;
}
@@ -3100,7 +3348,22 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
record_count, join->best_positions + idx,
&loose_scan_pos);
if (idx==first)
+ {
join->best_positions[idx]= loose_scan_pos;
+ /*
+ If LooseScan is based on ref access (including the "degenerate"
+ one with 0 key parts), we should use full index scan.
+
+ Unfortunately, lots of code assumes that if tab->type==JT_ALL &&
+ tab->quick!=NULL, then quick select should be used. The only
+ simple way to fix this is to remove the quick select:
+ */
+ if (join->best_positions[idx].key)
+ {
+ delete join->best_positions[idx].table->quick;
+ join->best_positions[idx].table->quick= NULL;
+ }
+ }
}
rem_tables &= ~join->best_positions[idx].table->table->map;
record_count *= join->best_positions[idx].records_read;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c7af4a37e9a..d905516b075 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -10859,6 +10859,9 @@ finish:
acceptable, as this happens rarely. The implementation without
copying would be much more complicated.
+ For description of how equality propagation works with SJM nests, grep
+ for EqualityPropagationAndSjmNests.
+
@param left_item left term of the quality to be checked
@param right_item right term of the equality to be checked
@param item equality item if the equality originates from a condition
@@ -10932,12 +10935,14 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
{
/* left_item_equal of an upper level contains left_item */
left_item_equal= new Item_equal(left_item_equal);
+ left_item_equal->set_context_field(((Item_field*) left_item));
cond_equal->current_level.push_back(left_item_equal);
}
if (right_copyfl)
{
/* right_item_equal of an upper level contains right_item */
right_item_equal= new Item_equal(right_item_equal);
+ right_item_equal->set_context_field(((Item_field*) right_item));
cond_equal->current_level.push_back(right_item_equal);
}
@@ -10967,6 +10972,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
Item_equal *item_equal= new Item_equal(orig_left_item,
orig_right_item,
FALSE);
+ item_equal->set_context_field((Item_field*)left_item);
cond_equal->current_level.push_back(item_equal);
}
}
@@ -11023,6 +11029,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
{
item_equal= new Item_equal(item_equal);
cond_equal->current_level.push_back(item_equal);
+ item_equal->set_context_field(field_item);
}
if (item_equal)
{
@@ -11036,6 +11043,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
else
{
item_equal= new Item_equal(const_item, orig_field_item, TRUE);
+ item_equal->set_context_field(field_item);
cond_equal->current_level.push_back(item_equal);
}
return TRUE;
@@ -11672,6 +11680,8 @@ static TABLE_LIST* embedding_sjm(Item *item)
Item_equal::get_first() also takes similar measures for dealing with
equality substitution in presense of SJM nests.
+ Grep for EqualityPropagationAndSjmNests for a more verbose description.
+
@return
- The condition with generated simple equalities or
a pointer to the simple generated equality, if success.
@@ -11735,9 +11745,13 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
on upper AND-levels.
*/
if (upper)
- {
+ {
+ TABLE_LIST *native_sjm= embedding_sjm(item_equal->context_field);
if (item_const && upper->get_const())
+ {
+ /* Upper item also has "field_item=const". Don't produce equality here */
item= 0;
+ }
else
{
Item_equal_fields_iterator li(*item_equal);
@@ -11748,6 +11762,8 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
break;
}
}
+ if (embedding_sjm(field_item) != native_sjm)
+ item= NULL; /* Don't produce equality */
}
bool produce_equality= test(item == field_item);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c7b530f381a..934ba6ee1ba 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1459,7 +1459,8 @@ innobase_next_autoinc(
ulonglong current, /*!< in: Current value */
ulonglong increment, /*!< in: increment current by */
ulonglong offset, /*!< in: AUTOINC offset */
- ulonglong max_value) /*!< in: max value for type */
+ ulonglong max_value, /*!< in: max value for type */
+ ulonglong reserve) /*!< in: how many values to reserve */
{
ulonglong next_value;
@@ -1468,51 +1469,16 @@ innobase_next_autoinc(
/* According to MySQL documentation, if the offset is greater than
the increment then the offset is ignored. */
- if (offset > increment) {
+ if (offset >= increment)
offset = 0;
- }
-
- if (max_value <= current) {
- next_value = max_value;
- } else if (offset <= 1) {
- /* Offset 0 and 1 are the same, because there must be at
- least one node in the system. */
- if (max_value - current <= increment) {
- next_value = max_value;
- } else {
- next_value = current + increment;
- }
- } else if (max_value > current) {
- if (current > offset) {
- next_value = ((current - offset) / increment) + 1;
- } else {
- next_value = ((offset - current) / increment) + 1;
- }
-
- ut_a(increment > 0);
- ut_a(next_value > 0);
-
- /* Check for multiplication overflow. */
- if (increment > (max_value / next_value)) {
-
- next_value = max_value;
- } else {
- next_value *= increment;
- ut_a(max_value >= next_value);
-
- /* Check for overflow. */
- if (max_value - next_value <= offset) {
- next_value = max_value;
- } else {
- next_value += offset;
- }
- }
- } else {
- next_value = max_value;
- }
-
- ut_a(next_value <= max_value);
+ if (max_value <= current)
+ return max_value;
+ next_value = (current / increment) + reserve;
+ next_value = next_value * increment + offset;
+ /* Check for overflow. */
+ if (next_value < current || next_value > max_value)
+ next_value = max_value;
return(next_value);
}
@@ -3799,8 +3765,7 @@ ha_innobase::innobase_initialize_autoinc()
nor the offset, so use a default increment of 1. */
auto_inc = innobase_next_autoinc(
- read_auto_inc, 1, 1, col_max_value);
-
+ read_auto_inc, 1, 1, col_max_value, 1);
break;
}
case DB_RECORD_NOT_FOUND:
@@ -5281,7 +5246,7 @@ set_max_autoinc:
auto_inc = innobase_next_autoinc(
auto_inc,
- need, offset, col_max_value);
+ need, offset, col_max_value, 1);
err = innobase_set_max_autoinc(
auto_inc);
@@ -5556,7 +5521,7 @@ ha_innobase::update_row(
need = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc(
- auto_inc, need, offset, col_max_value);
+ auto_inc, need, offset, col_max_value, 1);
error = innobase_set_max_autoinc(auto_inc);
}
@@ -10213,16 +10178,14 @@ ha_innobase::get_auto_increment(
/* With old style AUTOINC locking we only update the table's
AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
- ulonglong need;
ulonglong current;
ulonglong next_value;
current = *first_value > col_max_value ? autoinc : *first_value;
- need = *nb_reserved_values * increment;
-
+
/* Compute the last value in the interval */
next_value = innobase_next_autoinc(
- current, need, offset, col_max_value);
+ current, increment, offset, col_max_value, *nb_reserved_values);
prebuilt->autoinc_last_value = next_value;
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 7a51ecd8d2d..5c6c361962a 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1629,7 +1629,8 @@ innobase_next_autoinc(
ulonglong current, /*!< in: Current value */
ulonglong increment, /*!< in: increment current by */
ulonglong offset, /*!< in: AUTOINC offset */
- ulonglong max_value) /*!< in: max value for type */
+ ulonglong max_value, /*!< in: max value for type */
+ ulonglong reserve) /*!< in: how many values to reserve */
{
ulonglong next_value;
@@ -1638,51 +1639,16 @@ innobase_next_autoinc(
/* According to MySQL documentation, if the offset is greater than
the increment then the offset is ignored. */
- if (offset > increment) {
+ if (offset >= increment)
offset = 0;
- }
-
- if (max_value <= current) {
- next_value = max_value;
- } else if (offset <= 1) {
- /* Offset 0 and 1 are the same, because there must be at
- least one node in the system. */
- if (max_value - current <= increment) {
- next_value = max_value;
- } else {
- next_value = current + increment;
- }
- } else if (max_value > current) {
- if (current > offset) {
- next_value = ((current - offset) / increment) + 1;
- } else {
- next_value = ((offset - current) / increment) + 1;
- }
-
- ut_a(increment > 0);
- ut_a(next_value > 0);
-
- /* Check for multiplication overflow. */
- if (increment > (max_value / next_value)) {
-
- next_value = max_value;
- } else {
- next_value *= increment;
- ut_a(max_value >= next_value);
-
- /* Check for overflow. */
- if (max_value - next_value <= offset) {
- next_value = max_value;
- } else {
- next_value += offset;
- }
- }
- } else {
- next_value = max_value;
- }
-
- ut_a(next_value <= max_value);
+ if (max_value <= current)
+ return max_value;
+ next_value = (current / increment) + reserve;
+ next_value = next_value * increment + offset;
+ /* Check for overflow. */
+ if (next_value < current || next_value > max_value)
+ next_value = max_value;
return(next_value);
}
@@ -4190,8 +4156,7 @@ ha_innobase::innobase_initialize_autoinc()
nor the offset, so use a default increment of 1. */
auto_inc = innobase_next_autoinc(
- read_auto_inc, 1, 1, col_max_value);
-
+ read_auto_inc, 1, 1, col_max_value, 1);
break;
}
case DB_RECORD_NOT_FOUND:
@@ -5876,7 +5841,7 @@ set_max_autoinc:
auto_inc = innobase_next_autoinc(
auto_inc,
- need, offset, col_max_value);
+ need, offset, col_max_value, 1);
err = innobase_set_max_autoinc(
auto_inc);
@@ -6147,7 +6112,7 @@ ha_innobase::update_row(
need = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc(
- auto_inc, need, offset, col_max_value);
+ auto_inc, need, offset, col_max_value, 1);
error = innobase_set_max_autoinc(auto_inc);
}
@@ -10968,16 +10933,14 @@ ha_innobase::get_auto_increment(
/* With old style AUTOINC locking we only update the table's
AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
- ulonglong need;
ulonglong current;
ulonglong next_value;
current = *first_value > col_max_value ? autoinc : *first_value;
- need = *nb_reserved_values * increment;
-
+
/* Compute the last value in the interval */
next_value = innobase_next_autoinc(
- current, need, offset, col_max_value);
+ current, increment, offset, col_max_value, *nb_reserved_values);
prebuilt->autoinc_last_value = next_value;