Bug#12696518: MEMORY LEAKS IN HA_PARTITION (VALGRIND TESTS ON TRUNK)
(also 5.5+ solution for bug#11766879/bug#60106) The valgrind warning was due to an unused 'new handler_add_index(...)' which was never freed. The error handling did not work (fails as in bug#11766879) and the implementation was not as transparant as it could, therefore I made it a bit simpler and more transparant to the underlying handlers. This way it follows the api better and the error handling works and is also now tested. Also added a debug test to verify the error handling. Improved according to Jon Olavs review: Added class ha_partition_add_index. Also added base class Sql_alloc to handler_add_index. Update 3.
This commit is contained in:
parent
1a2b1ba6aa
commit
7d1cccae44
@ -1,3 +1,37 @@
|
|||||||
|
#
|
||||||
|
# Bug#11766879/Bug#60106: DIFF BETWEEN # OF INDEXES IN MYSQL VS INNODB,
|
||||||
|
# PARTITONING, ON INDEX CREATE
|
||||||
|
# Bug#12696518: MEMORY LEAKS IN HA_PARTITION (VALGRIND TESTS ON TRUNK)
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id bigint NOT NULL AUTO_INCREMENT,
|
||||||
|
time date,
|
||||||
|
id2 bigint not null,
|
||||||
|
PRIMARY KEY (id,time)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||||||
|
/*!50100 PARTITION BY RANGE(TO_DAYS(time))
|
||||||
|
(PARTITION p10 VALUES LESS THAN (734708) ENGINE = InnoDB,
|
||||||
|
PARTITION p20 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;
|
||||||
|
INSERT INTO t1 (time,id2) VALUES ('2011-07-24',1);
|
||||||
|
INSERT INTO t1 (time,id2) VALUES ('2011-07-25',1);
|
||||||
|
INSERT INTO t1 (time,id2) VALUES ('2011-07-25',1);
|
||||||
|
CREATE UNIQUE INDEX uk_time_id2 on t1(time,id2);
|
||||||
|
ERROR 23000: Duplicate entry '2011-07-25-1' for key 'uk_time_id2'
|
||||||
|
SELECT COUNT(*) FROM t1;
|
||||||
|
COUNT(*)
|
||||||
|
3
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
`time` date NOT NULL DEFAULT '0000-00-00',
|
||||||
|
`id2` bigint(20) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`,`time`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
|
||||||
|
/*!50100 PARTITION BY RANGE (TO_DAYS(time))
|
||||||
|
(PARTITION p10 VALUES LESS THAN (734708) ENGINE = InnoDB,
|
||||||
|
PARTITION p20 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
|
||||||
|
DROP TABLE t1;
|
||||||
call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB internal");
|
call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB internal");
|
||||||
#
|
#
|
||||||
# Bug#55091: Server crashes on ADD PARTITION after a failed attempt
|
# Bug#55091: Server crashes on ADD PARTITION after a failed attempt
|
||||||
|
@ -1,4 +1,75 @@
|
|||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
|
#
|
||||||
|
# Bug#12696518/Bug#11766879/60106:DIFF BETWEEN # OF INDEXES IN MYSQL
|
||||||
|
# VS INNODB, PARTITONING, ON INDEX CREATE
|
||||||
|
#
|
||||||
|
CREATE TABLE t1
|
||||||
|
(a INT PRIMARY KEY,
|
||||||
|
b VARCHAR(64))
|
||||||
|
ENGINE = InnoDB
|
||||||
|
PARTITION BY HASH (a) PARTITIONS 3;
|
||||||
|
INSERT INTO t1 VALUES (0, 'first row'), (1, 'second row'), (2, 'Third row');
|
||||||
|
INSERT INTO t1 VALUES (3, 'row id 3'), (4, '4 row'), (5, 'row5');
|
||||||
|
INSERT INTO t1 VALUES (6, 'X 6 row'), (7, 'Seventh row'), (8, 'Last row');
|
||||||
|
ALTER TABLE t1 ADD INDEX new_b_index (b);
|
||||||
|
ALTER TABLE t1 DROP INDEX new_b_index;
|
||||||
|
SET SESSION debug= "+d,ha_partition_fail_final_add_index";
|
||||||
|
ALTER TABLE t1 ADD INDEX (b);
|
||||||
|
ERROR HY000: Table has no partition for value 0
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` int(11) NOT NULL,
|
||||||
|
`b` varchar(64) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`a`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
/*!50100 PARTITION BY HASH (a)
|
||||||
|
PARTITIONS 3 */
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
0 first row
|
||||||
|
1 second row
|
||||||
|
2 Third row
|
||||||
|
3 row id 3
|
||||||
|
4 4 row
|
||||||
|
5 row5
|
||||||
|
6 X 6 row
|
||||||
|
7 Seventh row
|
||||||
|
8 Last row
|
||||||
|
FLUSH TABLES;
|
||||||
|
CREATE INDEX new_index ON t1 (b);
|
||||||
|
ERROR HY000: Table has no partition for value 0
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` int(11) NOT NULL,
|
||||||
|
`b` varchar(64) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`a`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
/*!50100 PARTITION BY HASH (a)
|
||||||
|
PARTITIONS 3 */
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
0 first row
|
||||||
|
1 second row
|
||||||
|
2 Third row
|
||||||
|
3 row id 3
|
||||||
|
4 4 row
|
||||||
|
5 row5
|
||||||
|
6 X 6 row
|
||||||
|
7 Seventh row
|
||||||
|
8 Last row
|
||||||
|
SET SESSION debug= "-d,ha_partition_fail_final_add_index";
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` int(11) NOT NULL,
|
||||||
|
`b` varchar(64) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`a`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
/*!50100 PARTITION BY HASH (a)
|
||||||
|
PARTITIONS 3 */
|
||||||
|
DROP TABLE t1;
|
||||||
call mtr.add_suppression("InnoDB: Warning: allocated tablespace .*, old maximum was");
|
call mtr.add_suppression("InnoDB: Warning: allocated tablespace .*, old maximum was");
|
||||||
call mtr.add_suppression("InnoDB: Error: table .* does not exist in the InnoDB internal");
|
call mtr.add_suppression("InnoDB: Error: table .* does not exist in the InnoDB internal");
|
||||||
call mtr.add_suppression("InnoDB: Warning: MySQL is trying to drop table ");
|
call mtr.add_suppression("InnoDB: Warning: MySQL is trying to drop table ");
|
||||||
|
@ -12,6 +12,41 @@ DROP TABLE IF EXISTS t1;
|
|||||||
|
|
||||||
--let $DATADIR= `SELECT @@datadir;`
|
--let $DATADIR= `SELECT @@datadir;`
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#12696518/Bug#11766879/60106:DIFF BETWEEN # OF INDEXES IN MYSQL
|
||||||
|
--echo # VS INNODB, PARTITONING, ON INDEX CREATE
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1
|
||||||
|
(a INT PRIMARY KEY,
|
||||||
|
b VARCHAR(64))
|
||||||
|
ENGINE = InnoDB
|
||||||
|
PARTITION BY HASH (a) PARTITIONS 3;
|
||||||
|
INSERT INTO t1 VALUES (0, 'first row'), (1, 'second row'), (2, 'Third row');
|
||||||
|
INSERT INTO t1 VALUES (3, 'row id 3'), (4, '4 row'), (5, 'row5');
|
||||||
|
INSERT INTO t1 VALUES (6, 'X 6 row'), (7, 'Seventh row'), (8, 'Last row');
|
||||||
|
|
||||||
|
ALTER TABLE t1 ADD INDEX new_b_index (b);
|
||||||
|
ALTER TABLE t1 DROP INDEX new_b_index;
|
||||||
|
|
||||||
|
SET SESSION debug= "+d,ha_partition_fail_final_add_index";
|
||||||
|
|
||||||
|
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
||||||
|
ALTER TABLE t1 ADD INDEX (b);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
--sorted_result
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
FLUSH TABLES;
|
||||||
|
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
||||||
|
CREATE INDEX new_index ON t1 (b);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
--sorted_result
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
SET SESSION debug= "-d,ha_partition_fail_final_add_index";
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
# Checking with #innodb what this is...
|
# Checking with #innodb what this is...
|
||||||
call mtr.add_suppression("InnoDB: Warning: allocated tablespace .*, old maximum was");
|
call mtr.add_suppression("InnoDB: Warning: allocated tablespace .*, old maximum was");
|
||||||
# If there is a crash or failure between the ddl_log is written and the
|
# If there is a crash or failure between the ddl_log is written and the
|
||||||
|
@ -3,6 +3,33 @@
|
|||||||
|
|
||||||
let $MYSQLD_DATADIR= `SELECT @@datadir`;
|
let $MYSQLD_DATADIR= `SELECT @@datadir`;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#11766879/Bug#60106: DIFF BETWEEN # OF INDEXES IN MYSQL VS INNODB,
|
||||||
|
--echo # PARTITONING, ON INDEX CREATE
|
||||||
|
--echo # Bug#12696518: MEMORY LEAKS IN HA_PARTITION (VALGRIND TESTS ON TRUNK)
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id bigint NOT NULL AUTO_INCREMENT,
|
||||||
|
time date,
|
||||||
|
id2 bigint not null,
|
||||||
|
PRIMARY KEY (id,time)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||||||
|
/*!50100 PARTITION BY RANGE(TO_DAYS(time))
|
||||||
|
(PARTITION p10 VALUES LESS THAN (734708) ENGINE = InnoDB,
|
||||||
|
PARTITION p20 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;
|
||||||
|
|
||||||
|
INSERT INTO t1 (time,id2) VALUES ('2011-07-24',1);
|
||||||
|
INSERT INTO t1 (time,id2) VALUES ('2011-07-25',1);
|
||||||
|
INSERT INTO t1 (time,id2) VALUES ('2011-07-25',1);
|
||||||
|
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
CREATE UNIQUE INDEX uk_time_id2 on t1(time,id2);
|
||||||
|
|
||||||
|
SELECT COUNT(*) FROM t1;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB internal");
|
call mtr.add_suppression("nnoDB: Error: table `test`.`t1` .* Partition.* InnoDB internal");
|
||||||
--echo #
|
--echo #
|
||||||
--echo # Bug#55091: Server crashes on ADD PARTITION after a failed attempt
|
--echo # Bug#55091: Server crashes on ADD PARTITION after a failed attempt
|
||||||
|
@ -6663,49 +6663,81 @@ bool ha_partition::check_if_incompatible_data(HA_CREATE_INFO *create_info,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Support of in-place add/drop index
|
Helper class for [final_]add_index, see handler.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class ha_partition_add_index : public handler_add_index
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
handler_add_index **add_array;
|
||||||
|
ha_partition_add_index(TABLE* table_arg, KEY* key_info_arg,
|
||||||
|
uint num_of_keys_arg)
|
||||||
|
: handler_add_index(table_arg, key_info_arg, num_of_keys_arg)
|
||||||
|
{}
|
||||||
|
~ha_partition_add_index() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Support of in-place add/drop index
|
||||||
|
|
||||||
|
@param table_arg Table to add index to
|
||||||
|
@param key_info Struct over the new keys to add
|
||||||
|
@param num_of_keys Number of keys to add
|
||||||
|
@param[out] add Data to be submitted with final_add_index
|
||||||
|
|
||||||
|
@return Operation status
|
||||||
|
@retval 0 Success
|
||||||
|
@retval != 0 Failure (error code returned, and all operations rollbacked)
|
||||||
|
*/
|
||||||
|
|
||||||
int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
|
int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
|
||||||
handler_add_index **add)
|
handler_add_index **add)
|
||||||
{
|
{
|
||||||
handler **file;
|
uint i;
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
|
THD *thd= ha_thd();
|
||||||
|
ha_partition_add_index *part_add_index;
|
||||||
|
|
||||||
DBUG_ENTER("ha_partition::add_index");
|
DBUG_ENTER("ha_partition::add_index");
|
||||||
*add= new handler_add_index(table, key_info, num_of_keys);
|
|
||||||
/*
|
/*
|
||||||
There has already been a check in fix_partition_func in mysql_alter_table
|
There has already been a check in fix_partition_func in mysql_alter_table
|
||||||
before this call, which checks for unique/primary key violations of the
|
before this call, which checks for unique/primary key violations of the
|
||||||
partitioning function. So no need for extra check here.
|
partitioning function. So no need for extra check here.
|
||||||
*/
|
*/
|
||||||
for (file= m_file; *file; file++)
|
|
||||||
|
/*
|
||||||
|
This will be freed at the end of the statement.
|
||||||
|
And destroyed at final_add_index. (Sql_alloc does not free in delete).
|
||||||
|
*/
|
||||||
|
part_add_index= new (thd->mem_root)
|
||||||
|
ha_partition_add_index(table_arg, key_info, num_of_keys);
|
||||||
|
if (!part_add_index)
|
||||||
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||||
|
part_add_index->add_array= (handler_add_index **)
|
||||||
|
thd->alloc(sizeof(void *) * m_tot_parts);
|
||||||
|
if (!part_add_index->add_array)
|
||||||
{
|
{
|
||||||
handler_add_index *add_index;
|
delete part_add_index;
|
||||||
if ((ret= (*file)->add_index(table_arg, key_info, num_of_keys, &add_index)))
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||||
goto err;
|
}
|
||||||
if ((ret= (*file)->final_add_index(add_index, true)))
|
|
||||||
|
for (i= 0; i < m_tot_parts; i++)
|
||||||
|
{
|
||||||
|
if ((ret= m_file[i]->add_index(table_arg, key_info, num_of_keys,
|
||||||
|
&part_add_index->add_array[i])))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
*add= part_add_index;
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
err:
|
err:
|
||||||
if (file > m_file)
|
/* Rollback all prepared partitions. i - 1 .. 0 */
|
||||||
|
while (i)
|
||||||
{
|
{
|
||||||
uint *key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys);
|
i--;
|
||||||
uint old_num_of_keys= table_arg->s->keys;
|
(void) m_file[i]->final_add_index(part_add_index->add_array[i], false);
|
||||||
uint i;
|
|
||||||
/* The newly created keys have the last id's */
|
|
||||||
for (i= 0; i < num_of_keys; i++)
|
|
||||||
key_numbers[i]= i + old_num_of_keys;
|
|
||||||
if (!table_arg->key_info)
|
|
||||||
table_arg->key_info= key_info;
|
|
||||||
while (--file >= m_file)
|
|
||||||
{
|
|
||||||
(void) (*file)->prepare_drop_index(table_arg, key_numbers, num_of_keys);
|
|
||||||
(void) (*file)->final_drop_index(table_arg);
|
|
||||||
}
|
|
||||||
if (table_arg->key_info == key_info)
|
|
||||||
table_arg->key_info= NULL;
|
|
||||||
}
|
}
|
||||||
|
delete part_add_index;
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6713,37 +6745,119 @@ err:
|
|||||||
/**
|
/**
|
||||||
Second phase of in-place add index.
|
Second phase of in-place add index.
|
||||||
|
|
||||||
|
@param add Info from add_index
|
||||||
|
@param commit Should we commit or rollback the add_index operation
|
||||||
|
|
||||||
|
@return Operation status
|
||||||
|
@retval 0 Success
|
||||||
|
@retval != 0 Failure (error code returned)
|
||||||
|
|
||||||
@note If commit is false, index changes are rolled back by dropping the
|
@note If commit is false, index changes are rolled back by dropping the
|
||||||
added indexes. If commit is true, nothing is done as the indexes
|
added indexes. If commit is true, nothing is done as the indexes
|
||||||
were already made active in ::add_index()
|
were already made active in ::add_index()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ha_partition::final_add_index(handler_add_index *add, bool commit)
|
int ha_partition::final_add_index(handler_add_index *add, bool commit)
|
||||||
{
|
{
|
||||||
|
ha_partition_add_index *part_add_index;
|
||||||
|
uint i;
|
||||||
|
int ret= 0;
|
||||||
|
|
||||||
DBUG_ENTER("ha_partition::final_add_index");
|
DBUG_ENTER("ha_partition::final_add_index");
|
||||||
// Rollback by dropping indexes.
|
|
||||||
if (!commit)
|
if (!add)
|
||||||
{
|
{
|
||||||
TABLE *table_arg= add->table;
|
DBUG_ASSERT(!commit);
|
||||||
uint num_of_keys= add->num_of_keys;
|
DBUG_RETURN(0);
|
||||||
handler **file;
|
|
||||||
uint *key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys);
|
|
||||||
uint old_num_of_keys= table_arg->s->keys;
|
|
||||||
uint i;
|
|
||||||
/* The newly created keys have the last id's */
|
|
||||||
for (i= 0; i < num_of_keys; i++)
|
|
||||||
key_numbers[i]= i + old_num_of_keys;
|
|
||||||
if (!table_arg->key_info)
|
|
||||||
table_arg->key_info= add->key_info;
|
|
||||||
for (file= m_file; *file; file++)
|
|
||||||
{
|
|
||||||
(void) (*file)->prepare_drop_index(table_arg, key_numbers, num_of_keys);
|
|
||||||
(void) (*file)->final_drop_index(table_arg);
|
|
||||||
}
|
|
||||||
if (table_arg->key_info == add->key_info)
|
|
||||||
table_arg->key_info= NULL;
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
part_add_index= static_cast<class ha_partition_add_index*>(add);
|
||||||
|
|
||||||
|
for (i= 0; i < m_tot_parts; i++)
|
||||||
|
{
|
||||||
|
if ((ret= m_file[i]->final_add_index(part_add_index->add_array[i], commit)))
|
||||||
|
goto err;
|
||||||
|
DBUG_EXECUTE_IF("ha_partition_fail_final_add_index", {
|
||||||
|
/* Simulate a failure by rollback the second partition */
|
||||||
|
if (m_tot_parts > 1)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
m_file[i]->final_add_index(part_add_index->add_array[i], false);
|
||||||
|
/* Set an error that is specific to ha_partition. */
|
||||||
|
ret= HA_ERR_NO_PARTITION_FOUND;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
delete part_add_index;
|
||||||
|
DBUG_RETURN(ret);
|
||||||
|
err:
|
||||||
|
uint j;
|
||||||
|
uint *key_numbers= NULL;
|
||||||
|
KEY *old_key_info= NULL;
|
||||||
|
uint num_of_keys= 0;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
/* How could this happen? Needed to create a covering test case :) */
|
||||||
|
DBUG_ASSERT(ret == HA_ERR_NO_PARTITION_FOUND);
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
num_of_keys= part_add_index->num_of_keys;
|
||||||
|
key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys);
|
||||||
|
if (!key_numbers)
|
||||||
|
{
|
||||||
|
sql_print_error("Failed with error handling of adding index:\n"
|
||||||
|
"committing index failed, and when trying to revert "
|
||||||
|
"already committed partitions we failed allocating\n"
|
||||||
|
"memory for the index for table '%s'",
|
||||||
|
table_share->table_name.str);
|
||||||
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||||
|
}
|
||||||
|
old_key_info= table->key_info;
|
||||||
|
/*
|
||||||
|
Use the newly added key_info as table->key_info to remove them.
|
||||||
|
Note that this requires the subhandlers to use name lookup of the
|
||||||
|
index. They must use given table->key_info[key_number], they cannot
|
||||||
|
use their local view of the keys, since table->key_info only include
|
||||||
|
the indexes to be removed here.
|
||||||
|
*/
|
||||||
|
for (j= 0; j < num_of_keys; j++)
|
||||||
|
key_numbers[j]= j;
|
||||||
|
table->key_info= part_add_index->key_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j= 0; j < m_tot_parts; j++)
|
||||||
|
{
|
||||||
|
if (j < i)
|
||||||
|
{
|
||||||
|
/* Remove the newly added index */
|
||||||
|
error= m_file[j]->prepare_drop_index(table, key_numbers, num_of_keys);
|
||||||
|
if (error || m_file[j]->final_drop_index(table))
|
||||||
|
{
|
||||||
|
sql_print_error("Failed with error handling of adding index:\n"
|
||||||
|
"committing index failed, and when trying to revert "
|
||||||
|
"already committed partitions we failed removing\n"
|
||||||
|
"the index for table '%s' partition nr %d",
|
||||||
|
table_share->table_name.str, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (j > i)
|
||||||
|
{
|
||||||
|
/* Rollback non finished partitions */
|
||||||
|
if (m_file[j]->final_add_index(part_add_index->add_array[j], false))
|
||||||
|
{
|
||||||
|
/* How could this happen? */
|
||||||
|
sql_print_error("Failed with error handling of adding index:\n"
|
||||||
|
"Rollback of add_index failed for table\n"
|
||||||
|
"'%s' partition nr %d",
|
||||||
|
table_share->table_name.str, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i > 0)
|
||||||
|
table->key_info= old_key_info;
|
||||||
|
delete part_add_index;
|
||||||
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ha_partition::prepare_drop_index(TABLE *table_arg, uint *key_num,
|
int ha_partition::prepare_drop_index(TABLE *table_arg, uint *key_num,
|
||||||
|
@ -1163,10 +1163,12 @@ uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Index creation context.
|
Index creation context.
|
||||||
Created by handler::add_index() and freed by handler::final_add_index().
|
Created by handler::add_index() and destroyed by handler::final_add_index().
|
||||||
|
And finally freed at the end of the statement.
|
||||||
|
(Sql_alloc does not free in delete).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class handler_add_index
|
class handler_add_index : public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Table where the indexes are added */
|
/* Table where the indexes are added */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user