Commit 108ca62a authored by Sergey Vojtovich's avatar Sergey Vojtovich

Merge InnoDB snapshot with mysql-5.1-bugteam.

parents 5f106ea2 ba6c1527
drop table if exists t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (null);
INSERT INTO t1 VALUES (null);
ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;
SELECT * FROM t1;
d1
1
2
SELECT * FROM t1;
d1
1
2
INSERT INTO t1 VALUES(null);
Got one of the listed errors
ALTER TABLE t1 AUTO_INCREMENT = 3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`d1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`d1`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
d1
1
2
3
DROP TABLE t1;
......@@ -868,35 +868,6 @@ Got one of the listed errors
DROP TABLE t1;
DROP TABLE t2;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (null);
INSERT INTO t1 VALUES (null);
ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;
SELECT * FROM t1;
d1
1
2
SELECT * FROM t1;
d1
1
2
INSERT INTO t1 VALUES(null);
Got one of the listed errors
ALTER TABLE t1 AUTO_INCREMENT = 3;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`d1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`d1`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
d1
1
2
3
DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
......
......@@ -11,3 +11,4 @@
##############################################################################
kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
innodb-autoinc-44030 : BUG#47621 2009-01-22 svoj MySQL and InnoDB dicts getting out of sync
-- source include/have_innodb.inc
# embedded server ignores 'delayed', so skip this
-- source include/not_embedded.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from
# the index (PRIMARY)
# This test requires a restart of the server
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (null);
INSERT INTO t1 VALUES (null);
ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;
SELECT * FROM t1;
# Restart the server
-- source include/restart_mysqld.inc
# The MySQL and InnoDB data dictionaries should now be out of sync.
# The select should print message to the error log
SELECT * FROM t1;
# MySQL have made a change (http://lists.mysql.com/commits/75268) that no
# longer results in the two data dictionaries being out of sync. If they
# revert their changes then this check for ER_AUTOINC_READ_FAILED will need
# to be enabled. Also, see http://bugs.mysql.com/bug.php?id=47621.
-- error ER_AUTOINC_READ_FAILED,1467
INSERT INTO t1 VALUES(null);
ALTER TABLE t1 AUTO_INCREMENT = 3;
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
DROP TABLE t1;
......@@ -478,32 +478,6 @@ INSERT INTO t2 SELECT c1 FROM t1;
INSERT INTO t2 SELECT NULL FROM t1;
DROP TABLE t1;
DROP TABLE t2;
#
# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from
# the index (PRIMARY)
# This test requires a restart of the server
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (null);
INSERT INTO t1 VALUES (null);
ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT;
SELECT * FROM t1;
# Restart the server
-- source include/restart_mysqld.inc
# The MySQL and InnoDB data dictionaries should now be out of sync.
# The select should print message to the error log
SELECT * FROM t1;
# MySQL have made a change (http://lists.mysql.com/commits/75268) that no
# longer results in the two data dictionaries being out of sync. If they
# revert their changes then this check for ER_AUTOINC_READ_FAILED will need
# to be enabled.
-- error ER_AUTOINC_READ_FAILED,1467
INSERT INTO t1 VALUES(null);
ALTER TABLE t1 AUTO_INCREMENT = 3;
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES(null);
SELECT * FROM t1;
DROP TABLE t1;
# If the user has specified negative values for an AUTOINC column then
# InnoDB should ignore those values when setting the table's max value.
......
......@@ -15,6 +15,8 @@
-- source include/have_innodb.inc
let $MYSQLD_DATADIR= `select @@datadir`;
# Save the original values of some variables in order to be able to
# estimate how much they have changed during the tests. Previously this
# test assumed that e.g. rows_deleted is 0 here and after deleting 23
......@@ -1699,7 +1701,7 @@ set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
# Embedded server doesn't chdir to data directory
--replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ ''
--replace_result $MYSQLD_DATADIR ./ master-data/ ''
-- error 1025
rename table t3 to t1;
set foreign_key_checks=1;
......@@ -2339,7 +2341,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
# mysqltest first does replace_regex, then replace_result
--replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
# Embedded server doesn't chdir to data directory
--replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ ''
--replace_result $MYSQLD_DATADIR ./ master-data/ ''
--error 1025
ALTER TABLE t2 MODIFY a INT NOT NULL;
DELETE FROM t1;
......
......@@ -2575,58 +2575,151 @@ normalize_table_name(
#endif
}
/************************************************************************
Get the upper limit of the MySQL integral and floating-point type. */
static
ulonglong
innobase_get_int_col_max_value(
/*===========================*/
/* out: maximum allowed value for the field */
const Field* field) /* in: MySQL field */
{
ulonglong max_value = 0;
switch(field->key_type()) {
/* TINY */
case HA_KEYTYPE_BINARY:
max_value = 0xFFULL;
break;
case HA_KEYTYPE_INT8:
max_value = 0x7FULL;
break;
/* SHORT */
case HA_KEYTYPE_USHORT_INT:
max_value = 0xFFFFULL;
break;
case HA_KEYTYPE_SHORT_INT:
max_value = 0x7FFFULL;
break;
/* MEDIUM */
case HA_KEYTYPE_UINT24:
max_value = 0xFFFFFFULL;
break;
case HA_KEYTYPE_INT24:
max_value = 0x7FFFFFULL;
break;
/* LONG */
case HA_KEYTYPE_ULONG_INT:
max_value = 0xFFFFFFFFULL;
break;
case HA_KEYTYPE_LONG_INT:
max_value = 0x7FFFFFFFULL;
break;
/* BIG */
case HA_KEYTYPE_ULONGLONG:
max_value = 0xFFFFFFFFFFFFFFFFULL;
break;
case HA_KEYTYPE_LONGLONG:
max_value = 0x7FFFFFFFFFFFFFFFULL;
break;
case HA_KEYTYPE_FLOAT:
/* We use the maximum as per IEEE754-2008 standard, 2^24 */
max_value = 0x1000000ULL;
break;
case HA_KEYTYPE_DOUBLE:
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
max_value = 0x20000000000000ULL;
break;
default:
ut_error;
}
return(max_value);
}
/************************************************************************
Set the autoinc column max value. This should only be called once from
ha_innobase::open(). Therefore there's no need for a covering lock. */
ulong
void
ha_innobase::innobase_initialize_autoinc()
/*======================================*/
{
dict_index_t* index;
ulonglong auto_inc;
const char* col_name;
ulint error = DB_SUCCESS;
dict_table_t* innodb_table = prebuilt->table;
const Field* field = table->found_next_number_field;
col_name = table->found_next_number_field->field_name;
index = innobase_get_index(table->s->next_number_index);
/* Execute SELECT MAX(col_name) FROM TABLE; */
error = row_search_max_autoinc(index, col_name, &auto_inc);
if (error == DB_SUCCESS) {
if (field != NULL) {
auto_inc = innobase_get_int_col_max_value(field);
} else {
/* We have no idea what's been passed in to us as the
autoinc column. We set it to the MAX_INT of our table
autoinc type. */
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
/* At the this stage we dont' know the increment
or the offset, so use default inrement of 1. */
++auto_inc;
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
"column name\n");
}
dict_table_autoinc_initialize(innodb_table, auto_inc);
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
/* If the recovery level is set so high that writes
are disabled we force the AUTOINC counter to the MAX
value effectively disabling writes to the table.
Secondly, we avoid reading the table in case the read
results in failure due to a corrupted table/index.
We will not return an error to the client, so that the
tables can be dumped with minimal hassle. If an error
were returned in this case, the first attempt to read
the table would fail and subsequent SELECTs would succeed. */
} else if (field == NULL) {
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
} else {
dict_index_t* index;
const char* col_name;
ulonglong read_auto_inc;
ulint err;
} else if (error == DB_RECORD_NOT_FOUND) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
"dictionaries are out of sync.\n"
"InnoDB: Unable to find the AUTOINC column %s in the "
"InnoDB table %s.\n"
"InnoDB: We set the next AUTOINC column value to the "
"maximum possible value,\n"
"InnoDB: in effect disabling the AUTOINC next value "
"generation.\n"
"InnoDB: You can either set the next AUTOINC value "
"explicitly using ALTER TABLE\n"
"InnoDB: or fix the data dictionary by recreating "
"the table.\n",
col_name, index->table->name);
update_thd(ha_thd());
col_name = field->field_name;
index = innobase_get_index(table->s->next_number_index);
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
/* Execute SELECT MAX(col_name) FROM TABLE; */
err = row_search_max_autoinc(index, col_name, &read_auto_inc);
dict_table_autoinc_initialize(innodb_table, auto_inc);
switch (err) {
case DB_SUCCESS:
/* At the this stage we do not know the increment
or the offset, so use a default increment of 1. */
auto_inc = read_auto_inc + 1;
break;
error = DB_SUCCESS;
} /* else other errors are still fatal */
case DB_RECORD_NOT_FOUND:
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: MySQL and InnoDB data "
"dictionaries are out of sync.\n"
"InnoDB: Unable to find the AUTOINC column "
"%s in the InnoDB table %s.\n"
"InnoDB: We set the next AUTOINC column "
"value to the maximum possible value,\n"
"InnoDB: in effect disabling the AUTOINC "
"next value generation.\n"
"InnoDB: You can either set the next "
"AUTOINC value explicitly using ALTER TABLE\n"
"InnoDB: or fix the data dictionary by "
"recreating the table.\n",
col_name, index->table->name);
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
break;
default:
/* row_search_max_autoinc() should only return
one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
ut_error;
}
}
return(ulong(error));
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
}
/*********************************************************************
......@@ -2824,8 +2917,6 @@ ha_innobase::open(
/* Only if the table has an AUTOINC column. */
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
ulint error;
dict_table_autoinc_lock(prebuilt->table);
/* Since a table can already be "open" in InnoDB's internal
......@@ -2834,8 +2925,7 @@ ha_innobase::open(
autoinc value from a previous MySQL open. */
if (dict_table_autoinc_read(prebuilt->table) == 0) {
error = innobase_initialize_autoinc();
ut_a(error == DB_SUCCESS);
innobase_initialize_autoinc();
}
dict_table_autoinc_unlock(prebuilt->table);
......@@ -3650,67 +3740,6 @@ build_template(
}
}
/************************************************************************
Get the upper limit of the MySQL integral and floating-point type. */
ulonglong
ha_innobase::innobase_get_int_col_max_value(
/*========================================*/
const Field* field)
{
ulonglong max_value = 0;
switch(field->key_type()) {
/* TINY */
case HA_KEYTYPE_BINARY:
max_value = 0xFFULL;
break;
case HA_KEYTYPE_INT8:
max_value = 0x7FULL;
break;
/* SHORT */
case HA_KEYTYPE_USHORT_INT:
max_value = 0xFFFFULL;
break;
case HA_KEYTYPE_SHORT_INT:
max_value = 0x7FFFULL;
break;
/* MEDIUM */
case HA_KEYTYPE_UINT24:
max_value = 0xFFFFFFULL;
break;
case HA_KEYTYPE_INT24:
max_value = 0x7FFFFFULL;
break;
/* LONG */
case HA_KEYTYPE_ULONG_INT:
max_value = 0xFFFFFFFFULL;
break;
case HA_KEYTYPE_LONG_INT:
max_value = 0x7FFFFFFFULL;
break;
/* BIG */
case HA_KEYTYPE_ULONGLONG:
max_value = 0xFFFFFFFFFFFFFFFFULL;
break;
case HA_KEYTYPE_LONGLONG:
max_value = 0x7FFFFFFFFFFFFFFFULL;
break;
case HA_KEYTYPE_FLOAT:
/* We use the maximum as per IEEE754-2008 standard, 2^24 */
max_value = 0x1000000ULL;
break;
case HA_KEYTYPE_DOUBLE:
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
max_value = 0x20000000000000ULL;
break;
default:
ut_error;
}
return(max_value);
}
/************************************************************************
This special handling is really to overcome the limitations of MySQL's
binlogging. We need to eliminate the non-determinism that will arise in
......
......@@ -78,9 +78,8 @@ class ha_innobase: public handler
ulong innobase_reset_autoinc(ulonglong auto_inc);
ulong innobase_get_autoinc(ulonglong* value);
ulong innobase_update_autoinc(ulonglong auto_inc);
ulong innobase_initialize_autoinc();
void 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:
......
......@@ -3245,19 +3245,13 @@ row_drop_table_for_mysql(
"END;\n"
, FALSE, trx);
if (err != DB_SUCCESS) {
ut_a(err == DB_OUT_OF_FILE_SPACE);
err = DB_MUST_GET_MORE_FILE_SPACE;
row_mysql_handle_errors(&err, trx, NULL, NULL);
ut_error;
} else {
switch (err) {
ibool is_path;
const char* name_or_path;
mem_heap_t* heap;
case DB_SUCCESS:
heap = mem_heap_create(200);
/* Clone the name, in case it has been allocated
......@@ -3322,7 +3316,27 @@ row_drop_table_for_mysql(
}
mem_heap_free(heap);
break;
case DB_TOO_MANY_CONCURRENT_TRXS:
/* Cannot even find a free slot for the
the undo log. We can directly exit here
and return the DB_TOO_MANY_CONCURRENT_TRXS
error. */
break;
case DB_OUT_OF_FILE_SPACE:
err = DB_MUST_GET_MORE_FILE_SPACE;
row_mysql_handle_errors(&err, trx, NULL, NULL);
/* Fall through to raise error */
default:
/* No other possible error returns */
ut_error;
}
funct_exit:
trx_commit_for_mysql(trx);
......
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