diff options
author | Sergei Golubchik <sergii@pisem.net> | 2012-03-28 20:25:31 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2012-03-28 20:25:31 +0200 |
commit | 867296c3edc4502093f7b706e7ac4c1670aa9515 (patch) | |
tree | afcc8157b0b71a28edbcca6b862e6ca854fc743c | |
parent | 0d5adca0de0a51b1f0bd49045fc4062eac7d1d25 (diff) | |
parent | 6131d708e889cd4f93490c22bfee00d0728edfd2 (diff) | |
download | mariadb-git-867296c3edc4502093f7b706e7ac4c1670aa9515.tar.gz |
5.3 merge
-rw-r--r-- | mysql-test/r/innodb_ext_key.result | 8 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj2.result | 194 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff | 16 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj2_jcl6.result | 204 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj2_mat.result | 194 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb-autoinc-61209.result | 30 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb-autoinc.result | 178 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb-autoinc-61209.test | 61 | ||||
-rw-r--r-- | mysql-test/t/subselect_sj2.test | 138 | ||||
-rw-r--r-- | mysys/thr_lock.c | 3 | ||||
-rwxr-xr-x | scripts/mytop.sh | 95 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 4 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 11 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 263 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 67 | ||||
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 67 |
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; |