Commit 8ed0235e authored by Davi Arnaut's avatar Davi Arnaut

Merge before pushing.

parents d6e7b04a a146cd94
......@@ -412,7 +412,10 @@ sub mtr_report_stats ($) {
# When trying to set lower_case_table_names = 2
# on a case sensitive file system. Bug#37402.
/lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive. Now setting lower_case_table_names to 0 to avoid future problems./
/lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive. Now setting lower_case_table_names to 0 to avoid future problems./ or
# this test is expected to print warnings
($testname eq 'main.innodb_bug39438')
)
{
next; # Skip these lines
......
......@@ -169,3 +169,413 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL, 1);
DELETE FROM t1 WHERE c1 = 1;
INSERT INTO t1 VALUES (2,1);
INSERT INTO t1 VALUES (NULL,8);
SELECT * FROM t1;
c1 c2
2 1
3 8
DROP TABLE t1;
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL, 1);
DELETE FROM t1 WHERE c1 = 1;
INSERT INTO t1 VALUES (2,1), (NULL, 8);
INSERT INTO t1 VALUES (NULL,9);
SELECT * FROM t1;
c1 c2
2 1
3 8
5 9
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(5),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
5
10
110
250
310
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
c1
5
10
110
250
310
400
410
1000
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0);
SELECT * FROM t1;
c1
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
-1
1
2
10
110
250
410
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
Got one of the listed errors
SELECT * FROM t1;
c1
-1
1
2
10
110
250
410
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
c1
-1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
-2
-1
1
2
10
250
310
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
c1
-2
-1
1
2
10
250
310
400
410
1000
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
SELECT * FROM t1;
c1
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
INSERT INTO t1 VALUES (-2);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (250);
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1;
c1
1
2
10
110
210
250
310
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
c1
1
2
10
110
210
250
310
400
1000
1010
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
SELECT * FROM t1;
c1
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
Warnings:
Warning 1264 Out of range value for column 'c1' at row 1
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
c1
1
2
10
110
210
250
410
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
Got one of the listed errors
SELECT * FROM t1;
c1
1
2
10
110
210
250
410
1000
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (9223372036854775794);
SELECT * FROM t1;
c1
1
9223372036854775794
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 2
auto_increment_offset 10
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
c1
1
9223372036854775794
9223372036854775796
9223372036854775798
9223372036854775800
9223372036854775802
9223372036854775804
9223372036854775806
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603);
SELECT * FROM t1;
c1
1
18446744073709551603
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 2
auto_increment_offset 10
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
c1
1
18446744073709551603
18446744073709551604
18446744073709551606
18446744073709551608
18446744073709551610
18446744073709551612
18446744073709551614
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603);
SELECT * FROM t1;
c1
1
18446744073709551603
SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 5
auto_increment_offset 7
INSERT INTO t1 VALUES (NULL),(NULL);
SELECT * FROM t1;
c1
1
18446744073709551603
18446744073709551607
18446744073709551612
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(-9223372036854775806);
INSERT INTO t1 VALUES(-9223372036854775807);
INSERT INTO t1 VALUES(-9223372036854775808);
SELECT * FROM t1;
c1
-9223372036854775808
-9223372036854775807
-9223372036854775806
1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 3
auto_increment_offset 3
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
c1
-9223372036854775808
-9223372036854775807
-9223372036854775806
1
3
6
9
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 1
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551610);
SELECT * FROM t1;
c1
1
18446744073709551610
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
Warnings:
Warning 1292 Truncated incorrect auto_increment_increment value: '1152921504606846976'
Warning 1292 Truncated incorrect auto_increment_offset value: '1152921504606846976'
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 65535
auto_increment_offset 65535
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1;
c1
1
18446744073709551610
18446744073709551615
DROP TABLE t1;
......@@ -3295,3 +3295,11 @@ info: Records: 5 Duplicates: 0 Warnings: 0
TRUNCATE TABLE t1;
affected rows: 0
DROP TABLE t1;
Variable_name Value
Handler_update 0
Variable_name Value
Handler_delete 0
Variable_name Value
Handler_update 1
Variable_name Value
Handler_delete 1
SET storage_engine=InnoDB;
INSERT INTO bug38231 VALUES (1), (10), (300);
SET autocommit=0;
SELECT * FROM bug38231 FOR UPDATE;
a
1
10
300
TRUNCATE TABLE bug38231;
COMMIT;
DROP TABLE bug38231;
SET storage_engine=InnoDB;
......@@ -115,14 +115,14 @@ master-bin.000001 # Xid # # COMMIT /* XID */
DROP TABLE t1;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 15
Binlog_cache_use 13
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 16
Binlog_cache_use 14
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
......@@ -131,7 +131,7 @@ delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 17
Binlog_cache_use 15
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
......
......@@ -139,3 +139,262 @@ SELECT c1 FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
#
# Bug 38839
# Reset the last value generated at end of statement
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL, 1);
DELETE FROM t1 WHERE c1 = 1;
INSERT INTO t1 VALUES (2,1);
INSERT INTO t1 VALUES (NULL,8);
SELECT * FROM t1;
DROP TABLE t1;
# Bug 38839 -- same as above but for multi value insert
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL, 1);
DELETE FROM t1 WHERE c1 = 1;
INSERT INTO t1 VALUES (2,1), (NULL, 8);
INSERT INTO t1 VALUES (NULL,9);
SELECT * FROM t1;
DROP TABLE t1;
#
# Test changes to AUTOINC next value calculation
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL),(5),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with SIGNED INT column, by inserting a 0 for the first column value
# 0 is treated in the same was NULL.
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
SET @@INSERT_ID=400;
# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
-- error ER_DUP_ENTRY,1062
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with SIGNED INT column
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with UNSIGNED INT column, single insert
# The sign in the value is ignored and a new column value is generated
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (-2);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (250);
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
DROP TABLE t1;
# Test with UNSIGNED INT column, multi-value inserts
# The sign in the value is ignored and a new column value is generated
# Reset the AUTOINC session variables
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-1);
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
INSERT INTO t1 VALUES (250),(NULL);
SELECT * FROM t1;
INSERT INTO t1 VALUES (1000);
SET @@INSERT_ID=400;
# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
-- error ER_DUP_ENTRY,1062
INSERT INTO t1 VALUES(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment is > 1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (9223372036854775794); -- 2^63 - 14
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
# This should just fit
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment and offser are > 1
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
SHOW VARIABLES LIKE "%auto_inc%";
# This should fail because of overflow but it doesn't, it seems to be
# a MySQL server bug. It wraps around to 0 for the last value.
# See MySQL Bug# 39828
#
# Instead of wrapping around, it asserts when MySQL is compiled --with-debug
# (see sql/handler.cc:handler::update_auto_increment()). Don't test for
# overflow until Bug #39828 is fixed.
#
# Since this asserts when compiled --with-debug, we can't properly test this
# until Bug #39828 is fixed. For now, this test is meaningless.
#if Bug #39828 is fixed
#INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
#else
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
#endif
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment and offset are odd numbers
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
SHOW VARIABLES LIKE "%auto_inc%";
# This should fail because of overflow but it doesn't. It fails with
# a duplicate entry message because of a MySQL server bug, it wraps
# around. See MySQL Bug# 39828, once MySQL fix the bug we can replace
# the ER_DUP_ENTRY, 1062 below with the appropriate error message
#
# Since this asserts when compiled --with-debug, we can't properly test this
# until Bug #39828 is fixed. For now, this test is meaningless.
#if Bug #39828 is fixed
# Still need to fix this error code, error should mention overflow
#-- error ER_DUP_ENTRY,1062
#INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
#else
INSERT INTO t1 VALUES (NULL),(NULL);
#endif
SELECT * FROM t1;
DROP TABLE t1;
# Check for overflow handling when increment and offset are odd numbers
# and check for large -ve numbers
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(-9223372036854775806); -- -2^63 + 2
INSERT INTO t1 VALUES(-9223372036854775807); -- -2^63 + 1
INSERT INTO t1 VALUES(-9223372036854775808); -- -2^63
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
SHOW VARIABLES LIKE "%auto_inc%";
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
SELECT * FROM t1;
DROP TABLE t1;
#
# Check for overflow handling when increment and offset are very
# large numbers 2^60
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SET @@INSERT_ID=1;
SHOW VARIABLES LIKE "%auto_inc%";
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
# TODO: Fix the autoinc init code
# We have to do this because of a bug in the AUTOINC init code.
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES (18446744073709551610); -- 2^64 - 2
SELECT * FROM t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
SHOW VARIABLES LIKE "%auto_inc%";
# This should fail because of overflow but it doesn't. It wraps around
# and the autoinc values look bogus too.
# See MySQL Bug# 39828, once MySQL fix the bug we can enable the error
# code expected test.
# -- error ER_AUTOINC_READ_FAILED,1467
#
# Since this asserts when compiled --with-debug, we can't properly test this
# until Bug #39828 is fixed. For now, this test is meaningless.
#if Bug #39828 is fixed
#-- error ER_AUTOINC_READ_FAILED,1467
#INSERT INTO t1 VALUES (NULL),(NULL);
#else
INSERT INTO t1 VALUES (NULL);
#endif
SELECT * FROM t1;
DROP TABLE t1;
......@@ -2475,6 +2475,7 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 't2';
DROP TABLE t2;
DROP TABLE t1;
# End 34920 test
#
# Bug #29507 TRUNCATE shows to many rows effected
#
CONNECTION default;
......@@ -2491,6 +2492,36 @@ TRUNCATE TABLE t1;
--disable_info
DROP TABLE t1;
#
# Bug#35537 Innodb doesn't increment handler_update and handler_delete.
#
-- disable_query_log
-- disable_result_log
CONNECT (c1,localhost,root,,);
DROP TABLE IF EXISTS bug35537;
CREATE TABLE bug35537 (
c1 int
) ENGINE=InnoDB;
INSERT INTO bug35537 VALUES (1);
-- enable_result_log
SHOW SESSION STATUS LIKE 'Handler_update%';
SHOW SESSION STATUS LIKE 'Handler_delete%';
UPDATE bug35537 SET c1 = 2 WHERE c1 = 1;
DELETE FROM bug35537 WHERE c1 = 2;
SHOW SESSION STATUS LIKE 'Handler_update%';
SHOW SESSION STATUS LIKE 'Handler_delete%';
DROP TABLE bug35537;
DISCONNECT c1;
CONNECTION default;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
......
#
# Bug#38231 Innodb crash in lock_reset_all_on_table() on TRUNCATE + LOCK / UNLOCK
# http://bugs.mysql.com/38231
#
-- source include/have_innodb.inc
SET storage_engine=InnoDB;
# we care only that the following SQL commands do not crash the server
-- disable_query_log
-- disable_result_log
DROP TABLE IF EXISTS bug38231;
CREATE TABLE bug38231 (a INT);
-- connect (con1,localhost,root,,)
-- connect (con2,localhost,root,,)
-- connect (con3,localhost,root,,)
-- connection con1
SET autocommit=0;
LOCK TABLE bug38231 WRITE;
-- connection con2
SET autocommit=0;
-- send
LOCK TABLE bug38231 WRITE;
-- connection con3
SET autocommit=0;
-- send
LOCK TABLE bug38231 WRITE;
-- connection default
-- send
TRUNCATE TABLE bug38231;
-- connection con1
# give time to TRUNCATE and others to be executed; without sleep, sometimes
# UNLOCK executes before TRUNCATE
-- sleep 0.2
# this crashes the server if the bug is present
UNLOCK TABLES;
# clean up
-- connection con2
UNLOCK TABLES;
-- connection con3
UNLOCK TABLES;
-- connection default
-- disconnect con1
-- disconnect con2
-- disconnect con3
# test that TRUNCATE works with with row-level locks
-- enable_query_log
-- enable_result_log
INSERT INTO bug38231 VALUES (1), (10), (300);
-- connect (con4,localhost,root,,)
-- connection con4
SET autocommit=0;
SELECT * FROM bug38231 FOR UPDATE;
-- connection default
TRUNCATE TABLE bug38231;
-- connection con4
COMMIT;
-- connection default
-- disconnect con4
DROP TABLE bug38231;
#
# Bug#39438 Testcase for Bug#39436 crashes on 5.1 in fil_space_get_latch
# http://bugs.mysql.com/39438
#
# This test must be run with innodb_file_per_table=1 because the crash
# only occurs if that option is turned on and DISCARD TABLESPACE only
# works with innodb_file_per_table.
#
-- source include/have_innodb.inc
SET storage_engine=InnoDB;
# we care only that the following SQL commands do not crash the server
-- disable_query_log
-- disable_result_log
DROP TABLE IF EXISTS bug39438;
CREATE TABLE bug39438 (id INT) ENGINE=INNODB;
ALTER TABLE bug39438 DISCARD TABLESPACE;
# this crashes the server if the bug is present
SHOW TABLE STATUS;
DROP TABLE bug39438;
......@@ -15,21 +15,21 @@
# Process this file with automake to create Makefile.in
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
MYSQLLIBdir= $(pkglibdir)
pkgplugindir = $(pkglibdir)/plugin
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
MYSQLDATAdir= $(localstatedir)
MYSQLSHAREdir= $(pkgdatadir)
MYSQLBASEdir= $(prefix)
MYSQLLIBdir= $(pkglibdir)
pkgplugindir= $(pkglibdir)/plugin
INCLUDES= -I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/storage/innobase/include \
-I$(top_srcdir)/sql \
-I$(srcdir)
-I$(srcdir)
DEFS = @DEFS@
DEFS= @DEFS@
noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
noinst_HEADERS= include/btr0btr.h include/btr0btr.ic \
include/btr0cur.h include/btr0cur.ic \
include/btr0pcur.h include/btr0pcur.ic \
include/btr0sea.h include/btr0sea.ic \
......@@ -121,9 +121,9 @@ noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
include/ut0list.ic include/ut0wqueue.h \
include/ha_prototypes.h handler/ha_innodb.h
EXTRA_LIBRARIES = libinnobase.a
noinst_LIBRARIES = @plugin_innobase_static_target@
libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
EXTRA_LIBRARIES= libinnobase.a
noinst_LIBRARIES= @plugin_innobase_static_target@
libinnobase_a_SOURCES= btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
btr/btr0sea.c buf/buf0buf.c buf/buf0flu.c \
buf/buf0lru.c buf/buf0rea.c data/data0data.c \
data/data0type.c dict/dict0boot.c \
......@@ -156,17 +156,17 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
handler/ha_innodb.cc
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
libinnobase_a_CFLAGS = $(AM_CFLAGS)
libinnobase_a_CFLAGS= $(AM_CFLAGS)
EXTRA_LTLIBRARIES = ha_innodb.la
EXTRA_LTLIBRARIES= ha_innodb.la
pkgplugin_LTLIBRARIES= @plugin_innobase_shared_target@
ha_innodb_la_LDFLAGS = -module -rpath $(pkgplugindir)
ha_innodb_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
ha_innodb_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
ha_innodb_la_SOURCES = $(libinnobase_a_SOURCES)
ha_innodb_la_LDFLAGS= -module -rpath $(pkgplugindir)
ha_innodb_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_la_SOURCES= $(libinnobase_a_SOURCES)
EXTRA_DIST = CMakeLists.txt plug.in \
EXTRA_DIST= CMakeLists.txt plug.in \
pars/make_bison.sh pars/make_flex.sh \
pars/pars0grm.y pars/pars0lex.l
......
......@@ -161,6 +161,7 @@ btr_search_info_create(
info->magic_n = BTR_SEARCH_MAGIC_N;
#endif /* UNIV_DEBUG */
info->ref_count = 0;
info->root_guess = NULL;
info->hash_analysis = 0;
......@@ -184,6 +185,31 @@ btr_search_info_create(
return(info);
}
/*********************************************************************
Returns the value of ref_count. The value is protected by
btr_search_latch. */
ulint
btr_search_info_get_ref_count(
/*==========================*/
/* out: ref_count value. */
btr_search_t* info) /* in: search info. */
{
ulint ret;
ut_ad(info);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
rw_lock_s_lock(&btr_search_latch);
ret = info->ref_count;
rw_lock_s_unlock(&btr_search_latch);
return(ret);
}
/*************************************************************************
Updates the search info of an index about hash successes. NOTE that info
is NOT protected by any semaphore, to save CPU time! Do not assume its fields
......@@ -1022,8 +1048,12 @@ next_rec:
ha_remove_all_nodes_to_page(table, folds[i], page);
}
ut_a(index->search_info->ref_count > 0);
index->search_info->ref_count--;
block->is_hashed = FALSE;
block->index = NULL;
cleanup:
if (UNIV_UNLIKELY(block->n_pointers)) {
/* Corruption */
......@@ -1244,6 +1274,15 @@ btr_search_build_page_hash_index(
goto exit_func;
}
/* This counter is decremented every time we drop page
hash index entries and is incremented here. Since we can
rebuild hash index for a page that is already hashed, we
have to take care not to increment the counter in that
case. */
if (!block->is_hashed) {
index->search_info->ref_count++;
}
block->is_hashed = TRUE;
block->n_hash_helps = 0;
......
......@@ -42,6 +42,11 @@ initial segment in buf_LRU_get_recent_limit */
#define BUF_LRU_INITIAL_RATIO 8
/* When dropping the search hash index entries before deleting an ibd
file, we build a local array of pages belonging to that tablespace
in the buffer pool. Following is the size of that array. */
#define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024
/* If we switch on the InnoDB monitor because there are too few available
frames in the buffer pool, we set this to TRUE */
ibool buf_lru_switched_on_innodb_mon = FALSE;
......@@ -65,6 +70,120 @@ buf_LRU_block_free_hashed_page(
buf_block_t* block); /* in: block, must contain a file page and
be in a state where it can be freed */
/**********************************************************************
Attempts to drop page hash index on a batch of pages belonging to a
particular space id. */
static
void
buf_LRU_drop_page_hash_batch(
/*=========================*/
ulint id, /* in: space id */
const ulint* arr, /* in: array of page_no */
ulint count) /* in: number of entries in array */
{
ulint i;
ut_ad(arr != NULL);
ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE);
for (i = 0; i < count; ++i) {
btr_search_drop_page_hash_when_freed(id, arr[i]);
}
}
/**********************************************************************
When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page
hash index entries belonging to that table. This function tries to
do that in batch. Note that this is a 'best effort' attempt and does
not guarantee that ALL hash entries will be removed. */
static
void
buf_LRU_drop_page_hash_for_tablespace(
/*==================================*/
ulint id) /* in: space id */
{
buf_block_t* block;
ulint* page_arr;
ulint num_entries;
page_arr = ut_malloc(sizeof(ulint)
* BUF_LRU_DROP_SEARCH_HASH_SIZE);
mutex_enter(&buf_pool->mutex);
scan_again:
num_entries = 0;
block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) {
buf_block_t* prev_block;
mutex_enter(&block->mutex);
prev_block = UT_LIST_GET_PREV(LRU, block);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (block->space != id
|| block->buf_fix_count > 0
|| block->io_fix != 0) {
/* We leave the fixed pages as is in this scan.
To be dealt with later in the final scan. */
mutex_exit(&block->mutex);
goto next_page;
}
ut_ad(block->space == id);
if (block->is_hashed) {
/* Store the offset(i.e.: page_no) in the array
so that we can drop hash index in a batch
later. */
page_arr[num_entries] = block->offset;
mutex_exit(&block->mutex);
ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
++num_entries;
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
goto next_page;
}
/* Array full. We release the buf_pool->mutex to
obey the latching order. */
mutex_exit(&buf_pool->mutex);
buf_LRU_drop_page_hash_batch(id, page_arr,
num_entries);
num_entries = 0;
mutex_enter(&buf_pool->mutex);
} else {
mutex_exit(&block->mutex);
}
next_page:
/* Note that we may have released the buf_pool->mutex
above after reading the prev_block during processing
of a page_hash_batch (i.e.: when the array was full).
This means that prev_block can change in LRU list.
This is OK because this function is a 'best effort'
to drop as many search hash entries as possible and
it does not guarantee that ALL such entries will be
dropped. */
block = prev_block;
/* If, however, block has been removed from LRU list
to the free list then we should restart the scan.
block->state is protected by buf_pool->mutex. */
if (block && block->state != BUF_BLOCK_FILE_PAGE) {
ut_a(num_entries == 0);
goto scan_again;
}
}
mutex_exit(&buf_pool->mutex);
/* Drop any remaining batch of search hashed pages. */
buf_LRU_drop_page_hash_batch(id, page_arr, num_entries);
ut_free(page_arr);
}
/**********************************************************************
Invalidates all pages belonging to a given tablespace when we are deleting
the data file(s) of that tablespace. */
......@@ -78,6 +197,14 @@ buf_LRU_invalidate_tablespace(
ulint page_no;
ibool all_freed;
/* Before we attempt to drop pages one by one we first
attempt to drop page hash index entries in batches to make
it more efficient. The batching attempt is a best effort
attempt and does not guarantee that all pages hash entries
will be dropped. We get rid of remaining page hash entries
one by one below. */
buf_LRU_drop_page_hash_for_tablespace(id);
scan_again:
mutex_enter(&(buf_pool->mutex));
......
......@@ -422,8 +422,7 @@ dict_table_autoinc_lock(
}
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
Unconditionally set the autoinc counter. */
void
dict_table_autoinc_initialize(
......@@ -433,7 +432,6 @@ dict_table_autoinc_initialize(
{
ut_ad(mutex_own(&table->autoinc_mutex));
table->autoinc_inited = TRUE;
table->autoinc = value;
}
......@@ -447,32 +445,25 @@ dict_table_autoinc_read(
/* out: value for a new row, or 0 */
dict_table_t* table) /* in: table */
{
ib_longlong value;
ut_ad(mutex_own(&table->autoinc_mutex));
if (!table->autoinc_inited) {
value = 0;
} else {
value = table->autoinc;
}
return(value);
return(table->autoinc);
}
/************************************************************************
Updates the autoinc counter if the value supplied is greater than the
current value. If not inited, does nothing. */
current value. */
void
dict_table_autoinc_update(
/*======================*/
dict_table_autoinc_update_if_greater(
/*=================================*/
dict_table_t* table, /* in: table */
ib_ulonglong value) /* in: value which was assigned to a row */
{
if (table->autoinc_inited && value > table->autoinc) {
ut_ad(mutex_own(&table->autoinc_mutex));
if (value > table->autoinc) {
table->autoinc = value;
}
......@@ -1394,12 +1385,59 @@ dict_index_remove_from_cache(
dict_index_t* index) /* in, own: index */
{
ulint size;
ulint retries = 0;
btr_search_t* info;
ut_ad(table && index);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(mutex_own(&(dict_sys->mutex)));
/* We always create search info whether or not adaptive
hash index is enabled or not. */
info = index->search_info;
ut_ad(info);
/* We are not allowed to free the in-memory index struct
dict_index_t until all entries in the adaptive hash index
that point to any of the page belonging to his b-tree index
are dropped. This is so because dropping of these entries
require access to dict_index_t struct. To avoid such scenario
We keep a count of number of such pages in the search_info and
only free the dict_index_t struct when this count drops to
zero. */
for (;;) {
ulint ref_count = btr_search_info_get_ref_count(info);
if (ref_count == 0) {
break;
}
/* Sleep for 10ms before trying again. */
os_thread_sleep(10000);
++retries;
if (retries % 500 == 0) {
/* No luck after 5 seconds of wait. */
fprintf(stderr, "InnoDB: Error: Waited for"
" %lu secs for hash index"
" ref_count (%lu) to drop"
" to 0.\n"
"index: \"%s\""
" table: \"%s\"\n",
retries/100,
ref_count,
index->name,
table->name);
}
/* To avoid a hang here we commit suicide if the
ref_count doesn't drop to zero in 600 seconds. */
if (retries >= 60000) {
ut_error;
}
}
rw_lock_free(&index->lock);
/* Remove the index from the list of indexes of the table */
......
......@@ -89,11 +89,7 @@ dict_mem_table_create(
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
table->autoinc_inited = FALSE;
/* The actual increment value will be set by MySQL, we simply
default to 1 here.*/
table->autoinc_increment = 1;
table->autoinc = 0;
/* The number of transactions that are either waiting on the
AUTOINC lock or have been granted the lock. */
......
This diff is collapsed.
......@@ -72,12 +72,15 @@ class ha_innobase: public handler
int update_thd(THD* thd);
int change_active_index(uint keynr);
int general_fetch(uchar* buf, uint direction, uint match_mode);
int innobase_read_and_init_auto_inc(ulonglong* ret);
ulong innobase_autoinc_lock();
ulong innobase_lock_autoinc();
ulonglong innobase_peek_autoinc();
ulong innobase_set_max_autoinc(ulonglong auto_inc);
ulong innobase_reset_autoinc(ulonglong auto_inc);
ulong innobase_get_auto_increment(ulonglong* value);
ulong innobase_get_autoinc(ulonglong* value);
ulong innobase_update_autoinc(ulonglong auto_inc);
ulong innobase_initialize_autoinc();
dict_index_t* innobase_get_index(uint keynr);
ulonglong innobase_get_int_col_max_value(const Field* field);
/* Init values for the class: */
public:
......
......@@ -40,6 +40,14 @@ btr_search_info_create(
/*===================*/
/* out, own: search info struct */
mem_heap_t* heap); /* in: heap where created */
/*********************************************************************
Returns the value of ref_count. The value is protected by
btr_search_latch. */
ulint
btr_search_info_get_ref_count(
/*==========================*/
/* out: ref_count value. */
btr_search_t* info); /* in: search info. */
/*************************************************************************
Updates the search info. */
UNIV_INLINE
......@@ -137,6 +145,13 @@ btr_search_validate(void);
/* The search info struct in an index */
struct btr_search_struct{
ulint ref_count; /* Number of blocks in this index tree
that have search index built
i.e. block->index points to this index.
Protected by btr_search_latch except
when during initialization in
btr_search_info_create(). */
/* The following fields are not protected by any latch.
Unfortunately, this means that they must be aligned to
the machine word, i.e., they cannot be turned into bit-fields. */
......
......@@ -178,8 +178,7 @@ dict_table_autoinc_lock(
/*====================*/
dict_table_t* table); /* in: table */
/************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */
Unconditionally set the autoinc counter. */
void
dict_table_autoinc_initialize(
......@@ -196,12 +195,12 @@ dict_table_autoinc_read(
/* out: value for a new row, or 0 */
dict_table_t* table); /* in: table */
/************************************************************************
Updates the autoinc counter if the value supplied is equal or bigger than the
current value. If not inited, does nothing. */
Updates the autoinc counter if the value supplied is greater than the
current value. */
void
dict_table_autoinc_update(
/*======================*/
dict_table_autoinc_update_if_greater(
/*=================================*/
dict_table_t* table, /* in: table */
ib_ulonglong value); /* in: value which was assigned to a row */
......
......@@ -405,17 +405,8 @@ struct dict_table_struct{
mutex_t autoinc_mutex;
/* mutex protecting the autoincrement
counter */
ibool autoinc_inited;
/* TRUE if the autoinc counter has been
inited; MySQL gets the init value by executing
SELECT MAX(auto inc column) */
ib_ulonglong autoinc;/* autoinc counter value to give to the
next inserted row */
ib_longlong autoinc_increment;
/* The increment step of the auto increment
column. Value must be greater than or equal
to 1 */
ulong n_waiting_or_granted_auto_inc_locks;
/* This counter is used to track the number
of granted and pending autoinc locks on this
......@@ -425,6 +416,7 @@ struct dict_table_struct{
acquired the AUTOINC lock or not. Of course
only one transaction can be granted the
lock but there can be multiple waiters. */
/*----------------------*/
#ifdef UNIV_DEBUG
ulint magic_n;/* magic number */
......
......@@ -63,5 +63,14 @@ thd_has_edited_nontrans_tables(
been edited */
void* thd); /* in: thread handle (THD*) */
/**********************************************************************
Returns true if the thread is executing a SELECT statement. */
ibool
thd_is_select(
/*==========*/
/* out: true if thd is executing SELECT */
const void* thd); /* in: thread handle (THD*) */
#endif
#endif
......@@ -463,14 +463,21 @@ void
lock_cancel_waiting_and_release(
/*============================*/
lock_t* lock); /* in: waiting lock request */
/*************************************************************************
Resets all locks, both table and record locks, on a table to be dropped.
No lock is allowed to be a wait lock. */
Removes locks on a table to be dropped or truncated.
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
also removed in addition to other table-level and record-level locks.
No lock, that is going to be removed, is allowed to be a wait lock. */
void
lock_reset_all_on_table(
/*====================*/
dict_table_t* table); /* in: table to be dropped */
lock_remove_all_on_table(
/*=====================*/
dict_table_t* table, /* in: table to be dropped
or truncated */
ibool remove_also_table_sx_locks);/* in: also removes
table S and X locks */
/*************************************************************************
Calculates the fold value of a page file address: used in inserting or
searching for a lock in the hash table. */
......
......@@ -683,7 +683,21 @@ struct row_prebuilt_struct {
to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */
ulonglong last_value; /* last value of AUTO-INC interval */
/*----------------------*/
ulonglong autoinc_last_value;/* last value of AUTO-INC interval */
ulonglong autoinc_increment;/* The increment step of the auto
increment column. Value must be
greater than or equal to 1. Required to
calculate the next value */
ulonglong autoinc_offset; /* The offset passed to
get_auto_increment() by MySQL. Required
to calculate the next value */
ulint autoinc_error; /* The actual error code encountered
while trying to init or read the
autoinc value from the table. We
store it here so that we can return
it to MySQL */
/*----------------------*/
ulint magic_n2; /* this should be the same as
magic_n */
};
......
......@@ -197,7 +197,7 @@ mutex_exit(
{
ut_ad(mutex_own(mutex));
ut_d(mutex->thread_id = ULINT_UNDEFINED);
ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
#ifdef UNIV_SYNC_DEBUG
sync_thread_reset_level(mutex);
......
......@@ -145,11 +145,15 @@ ib_time_t
ut_time(void);
/*=========*/
/**************************************************************
Returns system time. */
Returns system time.
Upon successful completion, the value 0 is returned; otherwise the
value -1 is returned and the global variable errno is set to indicate the
error. */
void
int
ut_usectime(
/*========*/
/* out: 0 on success, -1 otherwise */
ulint* sec, /* out: seconds since the Epoch */
ulint* ms); /* out: microseconds since the Epoch+*sec */
/**************************************************************
......
......@@ -3920,15 +3920,25 @@ lock_cancel_waiting_and_release(
trx_end_lock_wait(lock->trx);
}
/* True if a lock mode is S or X */
#define IS_LOCK_S_OR_X(lock) \
(lock_get_mode(lock) == LOCK_S \
|| lock_get_mode(lock) == LOCK_X)
/*************************************************************************
Resets all record and table locks of a transaction on a table to be dropped.
No lock is allowed to be a wait lock. */
Removes locks of a transaction on a table to be dropped.
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
also removed in addition to other table-level and record-level locks.
No lock, that is going to be removed, is allowed to be a wait lock. */
static
void
lock_reset_all_on_table_for_trx(
/*============================*/
dict_table_t* table, /* in: table to be dropped */
trx_t* trx) /* in: a transaction */
lock_remove_all_on_table_for_trx(
/*=============================*/
dict_table_t* table, /* in: table to be dropped */
trx_t* trx, /* in: a transaction */
ibool remove_also_table_sx_locks)/* in: also removes
table S and X locks */
{
lock_t* lock;
lock_t* prev_lock;
......@@ -3946,7 +3956,9 @@ lock_reset_all_on_table_for_trx(
lock_rec_discard(lock);
} else if (lock_get_type(lock) & LOCK_TABLE
&& lock->un_member.tab_lock.table == table) {
&& lock->un_member.tab_lock.table == table
&& (remove_also_table_sx_locks
|| !IS_LOCK_S_OR_X(lock))) {
ut_a(!lock_get_wait(lock));
......@@ -3958,26 +3970,65 @@ lock_reset_all_on_table_for_trx(
}
/*************************************************************************
Resets all locks, both table and record locks, on a table to be dropped.
No lock is allowed to be a wait lock. */
Removes locks on a table to be dropped or truncated.
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
also removed in addition to other table-level and record-level locks.
No lock, that is going to be removed, is allowed to be a wait lock. */
void
lock_reset_all_on_table(
/*====================*/
dict_table_t* table) /* in: table to be dropped */
lock_remove_all_on_table(
/*=====================*/
dict_table_t* table, /* in: table to be dropped
or truncated */
ibool remove_also_table_sx_locks)/* in: also removes
table S and X locks */
{
lock_t* lock;
lock_t* prev_lock;
mutex_enter(&kernel_mutex);
lock = UT_LIST_GET_FIRST(table->locks);
while (lock) {
ut_a(!lock_get_wait(lock));
while (lock != NULL) {
lock_reset_all_on_table_for_trx(table, lock->trx);
prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
lock);
lock = UT_LIST_GET_FIRST(table->locks);
/* If we should remove all locks (remove_also_table_sx_locks
is TRUE), or if the lock is not table-level S or X lock,
then check we are not going to remove a wait lock. */
if (remove_also_table_sx_locks
|| !(lock_get_type(lock) == LOCK_TABLE
&& IS_LOCK_S_OR_X(lock))) {
ut_a(!lock_get_wait(lock));
}
lock_remove_all_on_table_for_trx(table, lock->trx,
remove_also_table_sx_locks);
if (prev_lock == NULL) {
if (lock == UT_LIST_GET_FIRST(table->locks)) {
/* lock was not removed, pick its successor */
lock = UT_LIST_GET_NEXT(
un_member.tab_lock.locks, lock);
} else {
/* lock was removed, pick the first one */
lock = UT_LIST_GET_FIRST(table->locks);
}
} else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
prev_lock) != lock) {
/* If lock was removed by
lock_remove_all_on_table_for_trx() then pick the
successor of prev_lock ... */
lock = UT_LIST_GET_NEXT(
un_member.tab_lock.locks, prev_lock);
} else {
/* ... otherwise pick the successor of lock. */
lock = UT_LIST_GET_NEXT(
un_member.tab_lock.locks, lock);
}
}
mutex_exit(&kernel_mutex);
......
......@@ -1267,9 +1267,19 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
retry = os_file_handle_error(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
/* When srv_file_per_table is on, file creation failure may not
be critical to the whole instance. Do not crash the server in
case of unknown errors. */
if (srv_file_per_table) {
retry = os_file_handle_error_no_exit(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
} else {
retry = os_file_handle_error(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
}
if (retry) {
goto try_again;
}
......@@ -1344,9 +1354,19 @@ try_again:
if (file == -1) {
*success = FALSE;
retry = os_file_handle_error(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
/* When srv_file_per_table is on, file creation failure may not
be critical to the whole instance. Do not crash the server in
case of unknown errors. */
if (srv_file_per_table) {
retry = os_file_handle_error_no_exit(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
} else {
retry = os_file_handle_error(name,
create_mode == OS_FILE_CREATE ?
"create" : "open");
}
if (retry) {
goto try_again;
} else {
......
......@@ -15,25 +15,30 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
AC_CHECK_FUNCS(localtime_r)
AC_C_BIGENDIAN
case "$target_os" in
lin*)
CFLAGS="$CFLAGS -DUNIV_LINUX";;
hpux10*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
hp*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
aix*)
CFLAGS="$CFLAGS -DUNIV_AIX";;
irix*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
osf*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
*solaris*|*SunOS*)
CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
sysv5uw7*)
# Problem when linking on SCO
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
openbsd*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
lin*)
CFLAGS="$CFLAGS -DUNIV_LINUX";;
hpux10*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
hp*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
aix*)
CFLAGS="$CFLAGS -DUNIV_AIX";;
irix*|osf*|sysv5uw7*|openbsd*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
*solaris*|*SunOS*)
CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
esac
INNODB_DYNAMIC_CFLAGS="-DMYSQL_DYNAMIC_PLUGIN"
case "$target_cpu" in
x86_64)
# The AMD64 ABI forbids absolute addresses in shared libraries
;;
*86)
# Use absolute addresses on IA-32
INNODB_DYNAMIC_CFLAGS="$INNODB_DYNAMIC_CFLAGS -prefer-non-pic"
;;
esac
AC_SUBST(INNODB_DYNAMIC_CFLAGS)
])
# vim: set ft=config:
......@@ -661,7 +661,14 @@ row_create_prebuilt(
prebuilt->old_vers_heap = NULL;
prebuilt->last_value = 0;
prebuilt->autoinc_error = 0;
prebuilt->autoinc_offset = 0;
/* Default to 1, we will set the actual value later in
ha_innobase::get_auto_increment(). */
prebuilt->autoinc_increment = 1;
prebuilt->autoinc_last_value = 0;
return(prebuilt);
}
......@@ -1963,6 +1970,7 @@ row_create_index_for_mysql(
ulint err;
ulint i, j;
ulint len;
char* table_name;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
......@@ -1972,6 +1980,11 @@ row_create_index_for_mysql(
trx->op_info = "creating index";
/* Copy the table name because we may want to drop the
table later, after the index object is freed (inside
que_run_threads()) and thus index->table_name is not available. */
table_name = mem_strdup(index->table_name);
trx_start_if_not_started(trx);
/* Check that the same column does not appear twice in the index.
......@@ -2044,13 +2057,15 @@ error_handling:
trx_general_rollback_for_mysql(trx, FALSE, NULL);
row_drop_table_for_mysql(index->table_name, trx, FALSE);
row_drop_table_for_mysql(table_name, trx, FALSE);
trx->error_state = DB_SUCCESS;
}
trx->op_info = "";
mem_free(table_name);
return((int) err);
}
......@@ -2443,8 +2458,8 @@ row_discard_tablespace_for_mysql(
new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
/* Remove any locks there are on the table or its records */
lock_reset_all_on_table(table);
/* Remove all locks except the table-level S and X locks. */
lock_remove_all_on_table(table, FALSE);
info = pars_info_create();
......@@ -2779,9 +2794,8 @@ row_truncate_table_for_mysql(
goto funct_exit;
}
/* Remove any locks there are on the table or its records */
lock_reset_all_on_table(table);
/* Remove all locks except the table-level S and X locks. */
lock_remove_all_on_table(table, FALSE);
trx->table_id = table->id;
......@@ -2896,7 +2910,7 @@ next_rec:
/* MySQL calls ha_innobase::reset_auto_increment() which does
the same thing. */
dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 0);
dict_table_autoinc_initialize(table, 1);
dict_table_autoinc_unlock(table);
dict_update_statistics(table);
......@@ -3131,9 +3145,8 @@ check_next_foreign:
goto funct_exit;
}
/* Remove any locks there are on the table or its records */
lock_reset_all_on_table(table);
/* Remove all locks there are on the table or its records */
lock_remove_all_on_table(table, TRUE);
trx->dict_operation = TRUE;
trx->table_id = table->id;
......@@ -3429,8 +3442,6 @@ loop:
err = row_drop_table_for_mysql(table_name, trx, TRUE);
mem_free(table_name);
if (err != DB_SUCCESS) {
fputs("InnoDB: DROP DATABASE ", stderr);
ut_print_name(stderr, trx, TRUE, name);
......@@ -3438,8 +3449,11 @@ loop:
(ulint) err);
ut_print_name(stderr, trx, TRUE, table_name);
putc('\n', stderr);
mem_free(table_name);
break;
}
mem_free(table_name);
}
if (err == DB_SUCCESS) {
......
......@@ -32,6 +32,7 @@ Created 12/19/1997 Heikki Tuuri
#include "row0mysql.h"
#include "read0read.h"
#include "buf0lru.h"
#include "ha_prototypes.h"
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
......@@ -3577,20 +3578,12 @@ shortcut_fails_too_big_rec:
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& prebuilt->select_lock_type != LOCK_NONE
&& trx->mysql_query_str != NULL
&& *trx->mysql_query_str != NULL
&& trx->mysql_thd != NULL) {
&& trx->mysql_thd != NULL
&& thd_is_select(trx->mysql_thd)) {
/* It is a plain locking SELECT and the isolation
level is low: do not lock gaps */
/* Scan the MySQL query string; check if SELECT is the first
word there */
if (dict_str_starts_with_keyword(
trx->mysql_thd, *trx->mysql_query_str, "SELECT")) {
/* It is a plain locking SELECT and the isolation
level is low: do not lock gaps */
set_also_gap_locks = FALSE;
}
set_also_gap_locks = FALSE;
}
/* Note that if the search mode was GE or G, then the cursor
......
......@@ -1453,8 +1453,11 @@ srv_suspend_mysql_thread(
srv_n_lock_wait_count++;
srv_n_lock_wait_current_count++;
ut_usectime(&sec, &ms);
start_time = (ib_longlong)sec * 1000000 + ms;
if (ut_usectime(&sec, &ms) == -1) {
start_time = -1;
} else {
start_time = (ib_longlong)sec * 1000000 + ms;
}
}
/* Wake the lock timeout monitor thread, if it is suspended */
......@@ -1508,14 +1511,20 @@ srv_suspend_mysql_thread(
wait_time = ut_difftime(ut_time(), slot->suspend_time);
if (thr->lock_state == QUE_THR_LOCK_ROW) {
ut_usectime(&sec, &ms);
finish_time = (ib_longlong)sec * 1000000 + ms;
if (ut_usectime(&sec, &ms) == -1) {
finish_time = -1;
} else {
finish_time = (ib_longlong)sec * 1000000 + ms;
}
diff_time = (ulint) (finish_time - start_time);
srv_n_lock_wait_current_count--;
srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
if (diff_time > srv_n_lock_max_wait_time) {
if (diff_time > srv_n_lock_max_wait_time &&
/* only update the variable if we successfully
retrieved the start and finish times. See Bug#36819. */
start_time != -1 && finish_time != -1) {
srv_n_lock_max_wait_time = diff_time;
}
}
......
......@@ -202,13 +202,13 @@ srv_parse_data_file_paths_and_sizes(
str = srv_parse_megabytes(str, &size);
if (0 == memcmp(str, ":autoextend",
(sizeof ":autoextend") - 1)) {
if (0 == strncmp(str, ":autoextend",
(sizeof ":autoextend") - 1)) {
str += (sizeof ":autoextend") - 1;
if (0 == memcmp(str, ":max:",
(sizeof ":max:") - 1)) {
if (0 == strncmp(str, ":max:",
(sizeof ":max:") - 1)) {
str += (sizeof ":max:") - 1;
......@@ -290,14 +290,15 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_names)[i] = path;
(*data_file_sizes)[i] = size;
if (0 == memcmp(str, ":autoextend",
(sizeof ":autoextend") - 1)) {
if (0 == strncmp(str, ":autoextend",
(sizeof ":autoextend") - 1)) {
*is_auto_extending = TRUE;
str += (sizeof ":autoextend") - 1;
if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
if (0 == strncmp(str, ":max:",
(sizeof ":max:") - 1)) {
str += (sizeof ":max:") - 1;
......
......@@ -112,19 +112,45 @@ ut_time(void)
}
/**************************************************************
Returns system time. */
Returns system time.
Upon successful completion, the value 0 is returned; otherwise the
value -1 is returned and the global variable errno is set to indicate the
error. */
void
int
ut_usectime(
/*========*/
/* out: 0 on success, -1 otherwise */
ulint* sec, /* out: seconds since the Epoch */
ulint* ms) /* out: microseconds since the Epoch+*sec */
{
struct timeval tv;
int ret;
int errno_gettimeofday;
int i;
for (i = 0; i < 10; i++) {
ret = ut_gettimeofday(&tv, NULL);
if (ret == -1) {
errno_gettimeofday = errno;
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: gettimeofday(): %s\n",
strerror(errno_gettimeofday));
os_thread_sleep(100000); /* 0.1 sec */
errno = errno_gettimeofday;
} else {
break;
}
}
if (ret != -1) {
*sec = (ulint) tv.tv_sec;
*ms = (ulint) tv.tv_usec;
}
ut_gettimeofday(&tv, NULL);
*sec = (ulint) tv.tv_sec;
*ms = (ulint) tv.tv_usec;
return(ret);
}
/**************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment