mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Merge sgluhov@bk-internal.mysql.com:/home/bk/mysql-5.1-kt
into mysql.com:/home/gluh/MySQL/Merge/5.1-kt
This commit is contained in:
commit
07703f17bd
19 changed files with 758 additions and 91 deletions
|
@ -913,6 +913,28 @@ insert into t1 values (1);
|
|||
create index inx1 on t1(a);
|
||||
drop table t1;
|
||||
create table t1 (a int)
|
||||
PARTITION BY KEY (a)
|
||||
(PARTITION p0);
|
||||
set session sql_mode='no_table_options';
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
) PARTITION BY KEY (a) (PARTITION p0)
|
||||
set session sql_mode='';
|
||||
drop table t1;
|
||||
create table t1 (a int)
|
||||
partition by key (a)
|
||||
(partition p1 engine = innodb);
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
drop table t1;
|
||||
create table t1 (a int)
|
||||
partition by key (a)
|
||||
(partition p0 engine = MERGE);
|
||||
ERROR HY000: MyISAM Merge handler cannot be used in partitioned tables
|
||||
|
|
94
mysql-test/r/partition_innodb.result
Normal file
94
mysql-test/r/partition_innodb.result
Normal file
|
@ -0,0 +1,94 @@
|
|||
SET @max_row = 20;
|
||||
DROP TABLE IF EXISTS t0_template;
|
||||
CREATE TABLE t0_template (
|
||||
f_int1 INTEGER,
|
||||
f_int2 INTEGER,
|
||||
f_char1 CHAR(20),
|
||||
f_char2 CHAR(20),
|
||||
f_charbig VARCHAR(1000) ,
|
||||
PRIMARY KEY(f_int1))
|
||||
ENGINE = MEMORY;
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 20, f_int2 = 20, f_char1 = '20', f_char2 = '20',
|
||||
f_charbig = '===20===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 19, f_int2 = 19, f_char1 = '19', f_char2 = '19',
|
||||
f_charbig = '===19===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 18, f_int2 = 18, f_char1 = '18', f_char2 = '18',
|
||||
f_charbig = '===18===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 17, f_int2 = 17, f_char1 = '17', f_char2 = '17',
|
||||
f_charbig = '===17===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 16, f_int2 = 16, f_char1 = '16', f_char2 = '16',
|
||||
f_charbig = '===16===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 15, f_int2 = 15, f_char1 = '15', f_char2 = '15',
|
||||
f_charbig = '===15===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 14, f_int2 = 14, f_char1 = '14', f_char2 = '14',
|
||||
f_charbig = '===14===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 13, f_int2 = 13, f_char1 = '13', f_char2 = '13',
|
||||
f_charbig = '===13===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 12, f_int2 = 12, f_char1 = '12', f_char2 = '12',
|
||||
f_charbig = '===12===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 11, f_int2 = 11, f_char1 = '11', f_char2 = '11',
|
||||
f_charbig = '===11===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 10, f_int2 = 10, f_char1 = '10', f_char2 = '10',
|
||||
f_charbig = '===10===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 9, f_int2 = 9, f_char1 = '9', f_char2 = '9',
|
||||
f_charbig = '===9===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 8, f_int2 = 8, f_char1 = '8', f_char2 = '8',
|
||||
f_charbig = '===8===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 7, f_int2 = 7, f_char1 = '7', f_char2 = '7',
|
||||
f_charbig = '===7===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 6, f_int2 = 6, f_char1 = '6', f_char2 = '6',
|
||||
f_charbig = '===6===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 5, f_int2 = 5, f_char1 = '5', f_char2 = '5',
|
||||
f_charbig = '===5===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 4, f_int2 = 4, f_char1 = '4', f_char2 = '4',
|
||||
f_charbig = '===4===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 3, f_int2 = 3, f_char1 = '3', f_char2 = '3',
|
||||
f_charbig = '===3===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 2, f_int2 = 2, f_char1 = '2', f_char2 = '2',
|
||||
f_charbig = '===2===';
|
||||
INSERT INTO t0_template
|
||||
SET f_int1 = 1, f_int2 = 1, f_char1 = '1', f_char2 = '1',
|
||||
f_charbig = '===1===';
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30)) engine='InnoDB';
|
||||
INSERT INTO t1 (f_date, f_varchar)
|
||||
SELECT CONCAT(CAST((f_int1 + 999) AS CHAR),'-02-10'), CAST(f_char1 AS CHAR)
|
||||
FROM t0_template
|
||||
WHERE f_int1 + 999 BETWEEN 1000 AND 9999;
|
||||
SELECT IF(9999 - 1000 + 1 > @max_row, @max_row , 9999 - 1000 + 1)
|
||||
INTO @exp_row_count;
|
||||
ALTER TABLE t1 PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER));
|
||||
# 1.1.5 Add two named partitions + test
|
||||
ALTER TABLE t1 ADD PARTITION (PARTITION part1, PARTITION part7);
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30))
|
||||
ENGINE=InnoDB
|
||||
PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER));
|
||||
# This statement crashes the server.
|
||||
# CREATE partitioned table with three partitions in one step
|
||||
# would be harmless.
|
||||
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t0_aux;
|
||||
DROP TABLE IF EXISTS t0_definition;
|
||||
DROP TABLE IF EXISTS t0_template;
|
26
mysql-test/r/partition_mgm.result
Normal file
26
mysql-test/r/partition_mgm.result
Normal file
|
@ -0,0 +1,26 @@
|
|||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30))
|
||||
PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER)) PARTITIONS 2;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`f_date` date DEFAULT NULL,
|
||||
`f_varchar` varchar(30) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY HASH (CAST(YEAR(f_date) AS SIGNED INTEGER)) PARTITIONS 2
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1#P#p0.MYD
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1#P#p0.MYI
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1#P#p1.MYD
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1#P#p1.MYI
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1.frm
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1.par
|
||||
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`f_date` date DEFAULT NULL,
|
||||
`f_varchar` varchar(30) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY HASH (CAST(YEAR(f_date) AS SIGNED INTEGER)) PARTITIONS 1
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1#P#p0.MYD
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1#P#p0.MYI
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1.frm
|
||||
/home/pappa/bug19305/mysql-test/var/master-data/test/t1.par
|
|
@ -387,3 +387,108 @@ ALTER TABLE t1 DROP PARTITION p0;
|
|||
ALTER TABLE t1 DROP PARTITION p1;
|
||||
ALTER TABLE t1 DROP PARTITION p2;
|
||||
drop table t1;
|
||||
create table t1 (a int DEFAULT NULL,
|
||||
b varchar(30) DEFAULT NULL,
|
||||
c date DEFAULT NULL)
|
||||
ENGINE=MYISAM DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (1, 'abc', '1995-01-01');
|
||||
insert into t1 values (1, 'abc', '1995-01-02');
|
||||
insert into t1 values (1, 'abc', '1995-01-03');
|
||||
insert into t1 values (1, 'abc', '1995-01-04');
|
||||
insert into t1 values (1, 'abc', '1995-01-05');
|
||||
insert into t1 values (1, 'abc', '1995-01-06');
|
||||
insert into t1 values (1, 'abc', '1995-01-07');
|
||||
insert into t1 values (1, 'abc', '1995-01-08');
|
||||
insert into t1 values (1, 'abc', '1995-01-09');
|
||||
insert into t1 values (1, 'abc', '1995-01-10');
|
||||
insert into t1 values (1, 'abc', '1995-01-11');
|
||||
insert into t1 values (1, 'abc', '1995-01-12');
|
||||
insert into t1 values (1, 'abc', '1995-01-13');
|
||||
insert into t1 values (1, 'abc', '1995-01-14');
|
||||
insert into t1 values (1, 'abc', '1995-01-15');
|
||||
insert into t1 values (1, 'abc', '1997-01-01');
|
||||
insert into t1 values (1, 'abc', '1997-01-02');
|
||||
insert into t1 values (1, 'abc', '1997-01-03');
|
||||
insert into t1 values (1, 'abc', '1997-01-04');
|
||||
insert into t1 values (1, 'abc', '1997-01-05');
|
||||
insert into t1 values (1, 'abc', '1997-01-06');
|
||||
insert into t1 values (1, 'abc', '1997-01-07');
|
||||
insert into t1 values (1, 'abc', '1997-01-08');
|
||||
insert into t1 values (1, 'abc', '1997-01-09');
|
||||
insert into t1 values (1, 'abc', '1997-01-10');
|
||||
insert into t1 values (1, 'abc', '1997-01-11');
|
||||
insert into t1 values (1, 'abc', '1997-01-12');
|
||||
insert into t1 values (1, 'abc', '1997-01-13');
|
||||
insert into t1 values (1, 'abc', '1997-01-14');
|
||||
insert into t1 values (1, 'abc', '1997-01-15');
|
||||
insert into t1 values (1, 'abc', '1998-01-01');
|
||||
insert into t1 values (1, 'abc', '1998-01-02');
|
||||
insert into t1 values (1, 'abc', '1998-01-03');
|
||||
insert into t1 values (1, 'abc', '1998-01-04');
|
||||
insert into t1 values (1, 'abc', '1998-01-05');
|
||||
insert into t1 values (1, 'abc', '1998-01-06');
|
||||
insert into t1 values (1, 'abc', '1998-01-07');
|
||||
insert into t1 values (1, 'abc', '1998-01-08');
|
||||
insert into t1 values (1, 'abc', '1998-01-09');
|
||||
insert into t1 values (1, 'abc', '1998-01-10');
|
||||
insert into t1 values (1, 'abc', '1998-01-11');
|
||||
insert into t1 values (1, 'abc', '1998-01-12');
|
||||
insert into t1 values (1, 'abc', '1998-01-13');
|
||||
insert into t1 values (1, 'abc', '1998-01-14');
|
||||
insert into t1 values (1, 'abc', '1998-01-15');
|
||||
insert into t1 values (1, 'abc', '1999-01-01');
|
||||
insert into t1 values (1, 'abc', '1999-01-02');
|
||||
insert into t1 values (1, 'abc', '1999-01-03');
|
||||
insert into t1 values (1, 'abc', '1999-01-04');
|
||||
insert into t1 values (1, 'abc', '1999-01-05');
|
||||
insert into t1 values (1, 'abc', '1999-01-06');
|
||||
insert into t1 values (1, 'abc', '1999-01-07');
|
||||
insert into t1 values (1, 'abc', '1999-01-08');
|
||||
insert into t1 values (1, 'abc', '1999-01-09');
|
||||
insert into t1 values (1, 'abc', '1999-01-10');
|
||||
insert into t1 values (1, 'abc', '1999-01-11');
|
||||
insert into t1 values (1, 'abc', '1999-01-12');
|
||||
insert into t1 values (1, 'abc', '1999-01-13');
|
||||
insert into t1 values (1, 'abc', '1999-01-14');
|
||||
insert into t1 values (1, 'abc', '1999-01-15');
|
||||
insert into t1 values (1, 'abc', '2000-01-01');
|
||||
insert into t1 values (1, 'abc', '2000-01-02');
|
||||
insert into t1 values (1, 'abc', '2000-01-03');
|
||||
insert into t1 values (1, 'abc', '2000-01-04');
|
||||
insert into t1 values (1, 'abc', '2000-01-05');
|
||||
insert into t1 values (1, 'abc', '2000-01-06');
|
||||
insert into t1 values (1, 'abc', '2000-01-07');
|
||||
insert into t1 values (1, 'abc', '2000-01-08');
|
||||
insert into t1 values (1, 'abc', '2000-01-09');
|
||||
insert into t1 values (1, 'abc', '2000-01-15');
|
||||
insert into t1 values (1, 'abc', '2000-01-11');
|
||||
insert into t1 values (1, 'abc', '2000-01-12');
|
||||
insert into t1 values (1, 'abc', '2000-01-13');
|
||||
insert into t1 values (1, 'abc', '2000-01-14');
|
||||
insert into t1 values (1, 'abc', '2000-01-15');
|
||||
insert into t1 values (1, 'abc', '2001-01-01');
|
||||
insert into t1 values (1, 'abc', '2001-01-02');
|
||||
insert into t1 values (1, 'abc', '2001-01-03');
|
||||
insert into t1 values (1, 'abc', '2001-01-04');
|
||||
insert into t1 values (1, 'abc', '2001-01-05');
|
||||
insert into t1 values (1, 'abc', '2001-01-06');
|
||||
insert into t1 values (1, 'abc', '2001-01-07');
|
||||
insert into t1 values (1, 'abc', '2001-01-08');
|
||||
insert into t1 values (1, 'abc', '2001-01-09');
|
||||
insert into t1 values (1, 'abc', '2001-01-15');
|
||||
insert into t1 values (1, 'abc', '2001-01-11');
|
||||
insert into t1 values (1, 'abc', '2001-01-12');
|
||||
insert into t1 values (1, 'abc', '2001-01-13');
|
||||
insert into t1 values (1, 'abc', '2001-01-14');
|
||||
insert into t1 values (1, 'abc', '2001-01-15');
|
||||
alter table t1
|
||||
partition by range (year(c))
|
||||
(partition p5 values less than (2000), partition p10 values less than (2010));
|
||||
alter table t1
|
||||
reorganize partition p5 into
|
||||
(partition p1 values less than (1996),
|
||||
partition p2 values less than (1997),
|
||||
partition p3 values less than (1998),
|
||||
partition p4 values less than (1999),
|
||||
partition p5 values less than (2000));
|
||||
drop table t1;
|
||||
|
|
|
@ -1036,6 +1036,34 @@ insert into t1 values (1);
|
|||
create index inx1 on t1(a);
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug 19695 Partitions: SHOW CREATE TABLE shows table options even when it
|
||||
# shouldn't
|
||||
#
|
||||
create table t1 (a int)
|
||||
PARTITION BY KEY (a)
|
||||
(PARTITION p0);
|
||||
set session sql_mode='no_table_options';
|
||||
show create table t1;
|
||||
set session sql_mode='';
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG 19122 Crash after ALTER TABLE t1 REBUILD PARTITION p1
|
||||
#
|
||||
create table t1 (a int)
|
||||
partition by key (a)
|
||||
(partition p1 engine = innodb);
|
||||
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
alter table t1 rebuild partition p1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG 19304 Partitions: MERGE handler not allowed in partitioned tables
|
||||
#
|
||||
|
|
68
mysql-test/t/partition_innodb.test
Normal file
68
mysql-test/t/partition_innodb.test
Normal file
|
@ -0,0 +1,68 @@
|
|||
-- source include/have_innodb.inc
|
||||
|
||||
SET @max_row = 20;
|
||||
let $engine= 'InnoDB';
|
||||
let $MAX_VALUE= (2147483646);
|
||||
|
||||
let $max_row= `SELECT @max_row`;
|
||||
|
||||
# Column list with definition for all tables to be checked
|
||||
let $column_list= f_int1 INTEGER,
|
||||
f_int2 INTEGER,
|
||||
f_char1 CHAR(20),
|
||||
f_char2 CHAR(20),
|
||||
f_charbig VARCHAR(1000);
|
||||
|
||||
let $sub_part_no= 3;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t0_template;
|
||||
--enable_warnings
|
||||
eval CREATE TABLE t0_template (
|
||||
$column_list ,
|
||||
PRIMARY KEY(f_int1))
|
||||
ENGINE = MEMORY;
|
||||
let $num= `SELECT @max_row`;
|
||||
while ($num)
|
||||
{
|
||||
eval INSERT INTO t0_template
|
||||
SET f_int1 = $num, f_int2 = $num, f_char1 = '$num', f_char2 = '$num',
|
||||
f_charbig = '===$num===';
|
||||
dec $num;
|
||||
}
|
||||
# 1. Create the table
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
eval CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30)) engine=$engine;
|
||||
# 2. Fill the table t1 with records
|
||||
INSERT INTO t1 (f_date, f_varchar)
|
||||
SELECT CONCAT(CAST((f_int1 + 999) AS CHAR),'-02-10'), CAST(f_char1 AS CHAR)
|
||||
FROM t0_template
|
||||
WHERE f_int1 + 999 BETWEEN 1000 AND 9999;
|
||||
# 3. Calculate the number of inserted records.
|
||||
SELECT IF(9999 - 1000 + 1 > @max_row, @max_row , 9999 - 1000 + 1)
|
||||
INTO @exp_row_count;
|
||||
# DEBUG SELECT @exp_row_count;
|
||||
# 4. Print the layout, check Readability
|
||||
ALTER TABLE t1 PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER));
|
||||
--echo # 1.1.5 Add two named partitions + test
|
||||
ALTER TABLE t1 ADD PARTITION (PARTITION part1, PARTITION part7);
|
||||
drop table t1;
|
||||
|
||||
CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30))
|
||||
ENGINE=InnoDB
|
||||
PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER));
|
||||
|
||||
--echo # This statement crashes the server.
|
||||
--echo # CREATE partitioned table with three partitions in one step
|
||||
--echo # would be harmless.
|
||||
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
|
||||
|
||||
--disable_warnings
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t0_aux;
|
||||
DROP TABLE IF EXISTS t0_definition;
|
||||
DROP TABLE IF EXISTS t0_template;
|
||||
--enable_warnings
|
||||
|
15
mysql-test/t/partition_mgm.test
Normal file
15
mysql-test/t/partition_mgm.test
Normal file
|
@ -0,0 +1,15 @@
|
|||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30))
|
||||
PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER)) PARTITIONS 2;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--exec ls $MYSQLTEST_VARDIR/master-data/test/t1*
|
||||
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||
SHOW CREATE TABLE t1;
|
||||
--exec ls $MYSQLTEST_VARDIR/master-data/test/t1*
|
||||
|
||||
|
||||
|
||||
|
|
@ -416,3 +416,117 @@ ALTER TABLE t1 DROP PARTITION p0;
|
|||
ALTER TABLE t1 DROP PARTITION p1;
|
||||
ALTER TABLE t1 DROP PARTITION p2;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug 19830: ALTER TABLE t1 REORGANIZE PARTITION crashes
|
||||
#
|
||||
create table t1 (a int DEFAULT NULL,
|
||||
b varchar(30) DEFAULT NULL,
|
||||
c date DEFAULT NULL)
|
||||
ENGINE=MYISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
insert into t1 values (1, 'abc', '1995-01-01');
|
||||
insert into t1 values (1, 'abc', '1995-01-02');
|
||||
insert into t1 values (1, 'abc', '1995-01-03');
|
||||
insert into t1 values (1, 'abc', '1995-01-04');
|
||||
insert into t1 values (1, 'abc', '1995-01-05');
|
||||
insert into t1 values (1, 'abc', '1995-01-06');
|
||||
insert into t1 values (1, 'abc', '1995-01-07');
|
||||
insert into t1 values (1, 'abc', '1995-01-08');
|
||||
insert into t1 values (1, 'abc', '1995-01-09');
|
||||
insert into t1 values (1, 'abc', '1995-01-10');
|
||||
insert into t1 values (1, 'abc', '1995-01-11');
|
||||
insert into t1 values (1, 'abc', '1995-01-12');
|
||||
insert into t1 values (1, 'abc', '1995-01-13');
|
||||
insert into t1 values (1, 'abc', '1995-01-14');
|
||||
insert into t1 values (1, 'abc', '1995-01-15');
|
||||
insert into t1 values (1, 'abc', '1997-01-01');
|
||||
insert into t1 values (1, 'abc', '1997-01-02');
|
||||
insert into t1 values (1, 'abc', '1997-01-03');
|
||||
insert into t1 values (1, 'abc', '1997-01-04');
|
||||
insert into t1 values (1, 'abc', '1997-01-05');
|
||||
insert into t1 values (1, 'abc', '1997-01-06');
|
||||
insert into t1 values (1, 'abc', '1997-01-07');
|
||||
insert into t1 values (1, 'abc', '1997-01-08');
|
||||
insert into t1 values (1, 'abc', '1997-01-09');
|
||||
insert into t1 values (1, 'abc', '1997-01-10');
|
||||
insert into t1 values (1, 'abc', '1997-01-11');
|
||||
insert into t1 values (1, 'abc', '1997-01-12');
|
||||
insert into t1 values (1, 'abc', '1997-01-13');
|
||||
insert into t1 values (1, 'abc', '1997-01-14');
|
||||
insert into t1 values (1, 'abc', '1997-01-15');
|
||||
insert into t1 values (1, 'abc', '1998-01-01');
|
||||
insert into t1 values (1, 'abc', '1998-01-02');
|
||||
insert into t1 values (1, 'abc', '1998-01-03');
|
||||
insert into t1 values (1, 'abc', '1998-01-04');
|
||||
insert into t1 values (1, 'abc', '1998-01-05');
|
||||
insert into t1 values (1, 'abc', '1998-01-06');
|
||||
insert into t1 values (1, 'abc', '1998-01-07');
|
||||
insert into t1 values (1, 'abc', '1998-01-08');
|
||||
insert into t1 values (1, 'abc', '1998-01-09');
|
||||
insert into t1 values (1, 'abc', '1998-01-10');
|
||||
insert into t1 values (1, 'abc', '1998-01-11');
|
||||
insert into t1 values (1, 'abc', '1998-01-12');
|
||||
insert into t1 values (1, 'abc', '1998-01-13');
|
||||
insert into t1 values (1, 'abc', '1998-01-14');
|
||||
insert into t1 values (1, 'abc', '1998-01-15');
|
||||
insert into t1 values (1, 'abc', '1999-01-01');
|
||||
insert into t1 values (1, 'abc', '1999-01-02');
|
||||
insert into t1 values (1, 'abc', '1999-01-03');
|
||||
insert into t1 values (1, 'abc', '1999-01-04');
|
||||
insert into t1 values (1, 'abc', '1999-01-05');
|
||||
insert into t1 values (1, 'abc', '1999-01-06');
|
||||
insert into t1 values (1, 'abc', '1999-01-07');
|
||||
insert into t1 values (1, 'abc', '1999-01-08');
|
||||
insert into t1 values (1, 'abc', '1999-01-09');
|
||||
insert into t1 values (1, 'abc', '1999-01-10');
|
||||
insert into t1 values (1, 'abc', '1999-01-11');
|
||||
insert into t1 values (1, 'abc', '1999-01-12');
|
||||
insert into t1 values (1, 'abc', '1999-01-13');
|
||||
insert into t1 values (1, 'abc', '1999-01-14');
|
||||
insert into t1 values (1, 'abc', '1999-01-15');
|
||||
insert into t1 values (1, 'abc', '2000-01-01');
|
||||
insert into t1 values (1, 'abc', '2000-01-02');
|
||||
insert into t1 values (1, 'abc', '2000-01-03');
|
||||
insert into t1 values (1, 'abc', '2000-01-04');
|
||||
insert into t1 values (1, 'abc', '2000-01-05');
|
||||
insert into t1 values (1, 'abc', '2000-01-06');
|
||||
insert into t1 values (1, 'abc', '2000-01-07');
|
||||
insert into t1 values (1, 'abc', '2000-01-08');
|
||||
insert into t1 values (1, 'abc', '2000-01-09');
|
||||
insert into t1 values (1, 'abc', '2000-01-15');
|
||||
insert into t1 values (1, 'abc', '2000-01-11');
|
||||
insert into t1 values (1, 'abc', '2000-01-12');
|
||||
insert into t1 values (1, 'abc', '2000-01-13');
|
||||
insert into t1 values (1, 'abc', '2000-01-14');
|
||||
insert into t1 values (1, 'abc', '2000-01-15');
|
||||
insert into t1 values (1, 'abc', '2001-01-01');
|
||||
insert into t1 values (1, 'abc', '2001-01-02');
|
||||
insert into t1 values (1, 'abc', '2001-01-03');
|
||||
insert into t1 values (1, 'abc', '2001-01-04');
|
||||
insert into t1 values (1, 'abc', '2001-01-05');
|
||||
insert into t1 values (1, 'abc', '2001-01-06');
|
||||
insert into t1 values (1, 'abc', '2001-01-07');
|
||||
insert into t1 values (1, 'abc', '2001-01-08');
|
||||
insert into t1 values (1, 'abc', '2001-01-09');
|
||||
insert into t1 values (1, 'abc', '2001-01-15');
|
||||
insert into t1 values (1, 'abc', '2001-01-11');
|
||||
insert into t1 values (1, 'abc', '2001-01-12');
|
||||
insert into t1 values (1, 'abc', '2001-01-13');
|
||||
insert into t1 values (1, 'abc', '2001-01-14');
|
||||
insert into t1 values (1, 'abc', '2001-01-15');
|
||||
|
||||
alter table t1
|
||||
partition by range (year(c))
|
||||
(partition p5 values less than (2000), partition p10 values less than (2010));
|
||||
|
||||
alter table t1
|
||||
reorganize partition p5 into
|
||||
(partition p1 values less than (1996),
|
||||
partition p2 values less than (1997),
|
||||
partition p3 values less than (1998),
|
||||
partition p4 values less than (1999),
|
||||
partition p5 values less than (2000));
|
||||
|
||||
drop table t1;
|
||||
|
||||
|
|
|
@ -611,6 +611,8 @@ int ha_partition::drop_partitions(const char *path)
|
|||
DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff));
|
||||
if ((ret_error= file->delete_table((const char *) part_name_buff)))
|
||||
error= ret_error;
|
||||
if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
|
||||
error= 1;
|
||||
} while (++j < no_subparts);
|
||||
}
|
||||
else
|
||||
|
@ -622,6 +624,8 @@ int ha_partition::drop_partitions(const char *path)
|
|||
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
|
||||
if ((ret_error= file->delete_table((const char *) part_name_buff)))
|
||||
error= ret_error;
|
||||
if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos))
|
||||
error= 1;
|
||||
}
|
||||
if (part_elem->part_state == PART_IS_CHANGED)
|
||||
part_elem->part_state= PART_NORMAL;
|
||||
|
@ -629,6 +633,7 @@ int ha_partition::drop_partitions(const char *path)
|
|||
part_elem->part_state= PART_IS_DROPPED;
|
||||
}
|
||||
} while (++i < no_parts);
|
||||
VOID(sync_ddl_log());
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
@ -745,6 +750,7 @@ int ha_partition::rename_partitions(const char *path)
|
|||
*/
|
||||
part_elem= part_it++;
|
||||
if (part_elem->part_state == PART_IS_CHANGED ||
|
||||
part_elem->part_state == PART_TO_BE_DROPPED ||
|
||||
(part_elem->part_state == PART_IS_ADDED && temp_partitions))
|
||||
{
|
||||
if (m_is_sub_partitioned)
|
||||
|
|
34
sql/lock.cc
34
sql/lock.cc
|
@ -828,7 +828,7 @@ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
|
|||
if (wait_if_global_read_lock(thd, 0, 1))
|
||||
DBUG_RETURN(1);
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
if ((lock_retcode = lock_table_name(thd, table_list)) < 0)
|
||||
if ((lock_retcode = lock_table_name(thd, table_list, TRUE)) < 0)
|
||||
goto end;
|
||||
if (lock_retcode && wait_for_locked_table_names(thd, table_list))
|
||||
{
|
||||
|
@ -851,6 +851,7 @@ end:
|
|||
lock_table_name()
|
||||
thd Thread handler
|
||||
table_list Lock first table in this list
|
||||
check_in_use Do we need to check if table already in use by us
|
||||
|
||||
WARNING
|
||||
If you are going to update the table, you should use
|
||||
|
@ -870,7 +871,7 @@ end:
|
|||
> 0 table locked, but someone is using it
|
||||
*/
|
||||
|
||||
int lock_table_name(THD *thd, TABLE_LIST *table_list)
|
||||
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
|
||||
{
|
||||
TABLE *table;
|
||||
char key[MAX_DBKEY_LENGTH];
|
||||
|
@ -882,17 +883,22 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
|
|||
|
||||
key_length= create_table_def_key(thd, key, table_list, 0);
|
||||
|
||||
/* Only insert the table if we haven't insert it already */
|
||||
for (table=(TABLE*) hash_first(&open_cache, (byte*)key, key_length, &state);
|
||||
table ;
|
||||
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length, &state))
|
||||
if (check_in_use)
|
||||
{
|
||||
if (table->in_use == thd)
|
||||
/* Only insert the table if we haven't insert it already */
|
||||
for (table=(TABLE*) hash_first(&open_cache, (byte*)key,
|
||||
key_length, &state);
|
||||
table ;
|
||||
table = (TABLE*) hash_next(&open_cache,(byte*) key,
|
||||
key_length, &state))
|
||||
{
|
||||
DBUG_PRINT("info", ("Table is in use"));
|
||||
table->s->version= 0; // Ensure no one can use this
|
||||
table->locked_by_name= 1;
|
||||
DBUG_RETURN(0);
|
||||
if (table->in_use == thd)
|
||||
{
|
||||
DBUG_PRINT("info", ("Table is in use"));
|
||||
table->s->version= 0; // Ensure no one can use this
|
||||
table->locked_by_name= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -917,10 +923,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
|
|||
my_free((gptr) table,MYF(0));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
|
||||
/* Return 1 if table is in use */
|
||||
DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name,
|
||||
RTFC_NO_FLAG)));
|
||||
check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1003,7 +1009,7 @@ bool lock_table_names(THD *thd, TABLE_LIST *table_list)
|
|||
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
|
||||
{
|
||||
int got_lock;
|
||||
if ((got_lock=lock_table_name(thd,lock_table)) < 0)
|
||||
if ((got_lock=lock_table_name(thd,lock_table, TRUE)) < 0)
|
||||
goto end; // Fatal error
|
||||
if (got_lock)
|
||||
got_all_locks=0; // Someone is using table
|
||||
|
|
|
@ -1174,7 +1174,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
HA_CREATE_INFO *create_info,
|
||||
TABLE_LIST *table_list,
|
||||
List<create_field> *create_list,
|
||||
List<Key> *key_list, const char *db,
|
||||
List<Key> *key_list, char *db,
|
||||
const char *table_name,
|
||||
uint fast_alter_partition);
|
||||
uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
|
||||
|
@ -1204,10 +1204,12 @@ void create_subpartition_name(char *out, const char *in1,
|
|||
|
||||
typedef struct st_lock_param_type
|
||||
{
|
||||
TABLE_LIST table_list;
|
||||
ulonglong copied;
|
||||
ulonglong deleted;
|
||||
THD *thd;
|
||||
HA_CREATE_INFO *create_info;
|
||||
ALTER_INFO *alter_info;
|
||||
List<create_field> *create_list;
|
||||
List<create_field> new_create_list;
|
||||
List<Key> *key_list;
|
||||
|
@ -1687,7 +1689,7 @@ void unset_protect_against_global_read_lock(void);
|
|||
|
||||
/* Lock based on name */
|
||||
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
|
||||
int lock_table_name(THD *thd, TABLE_LIST *table_list);
|
||||
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use);
|
||||
void unlock_table_name(THD *thd, TABLE_LIST *table_list);
|
||||
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
|
||||
bool lock_table_names(THD *thd, TABLE_LIST *table_list);
|
||||
|
|
|
@ -2686,7 +2686,7 @@ retry:
|
|||
goto err;
|
||||
|
||||
// Code below is for repairing a crashed file
|
||||
if ((error= lock_table_name(thd, table_list)))
|
||||
if ((error= lock_table_name(thd, table_list, TRUE)))
|
||||
{
|
||||
if (error < 0)
|
||||
goto err;
|
||||
|
|
|
@ -1675,6 +1675,7 @@ static int add_partition_options(File fptr, partition_element *p_elem)
|
|||
{
|
||||
int err= 0;
|
||||
|
||||
err+= add_space(fptr);
|
||||
if (p_elem->tablespace_name)
|
||||
err+= add_keyword_string(fptr,"TABLESPACE", FALSE,
|
||||
p_elem->tablespace_name);
|
||||
|
@ -1702,7 +1703,7 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
|||
|
||||
if (part_info->part_type == RANGE_PARTITION)
|
||||
{
|
||||
err+= add_string(fptr, "VALUES LESS THAN ");
|
||||
err+= add_string(fptr, " VALUES LESS THAN ");
|
||||
if (p_elem->range_value != LONGLONG_MAX)
|
||||
{
|
||||
err+= add_begin_parenthesis(fptr);
|
||||
|
@ -1716,7 +1717,7 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
|||
{
|
||||
uint i;
|
||||
List_iterator<longlong> list_val_it(p_elem->list_val_list);
|
||||
err+= add_string(fptr, "VALUES IN ");
|
||||
err+= add_string(fptr, " VALUES IN ");
|
||||
uint no_items= p_elem->list_val_list.elements;
|
||||
err+= add_begin_parenthesis(fptr);
|
||||
if (p_elem->has_null_value)
|
||||
|
@ -1740,7 +1741,7 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
|||
err+= add_end_parenthesis(fptr);
|
||||
}
|
||||
end:
|
||||
return err + add_space(fptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1754,6 +1755,7 @@ end:
|
|||
buf_length A pointer to the returned buffer length
|
||||
use_sql_alloc Allocate buffer from sql_alloc if true
|
||||
otherwise use my_malloc
|
||||
show_partition_options Should we display partition options
|
||||
|
||||
RETURN VALUES
|
||||
NULL error
|
||||
|
@ -1781,7 +1783,8 @@ end:
|
|||
|
||||
char *generate_partition_syntax(partition_info *part_info,
|
||||
uint *buf_length,
|
||||
bool use_sql_alloc)
|
||||
bool use_sql_alloc,
|
||||
bool show_partition_options)
|
||||
{
|
||||
uint i,j, tot_no_parts, no_subparts, no_parts;
|
||||
partition_element *part_elem;
|
||||
|
@ -1882,12 +1885,12 @@ char *generate_partition_syntax(partition_info *part_info,
|
|||
first= FALSE;
|
||||
err+= add_partition(fptr);
|
||||
err+= add_name_string(fptr, part_elem->partition_name);
|
||||
err+= add_space(fptr);
|
||||
err+= add_partition_values(fptr, part_info, part_elem);
|
||||
if (!part_info->is_sub_partitioned() ||
|
||||
part_info->use_default_subpartitions)
|
||||
{
|
||||
err+= add_partition_options(fptr, part_elem);
|
||||
if (show_partition_options)
|
||||
err+= add_partition_options(fptr, part_elem);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1900,8 +1903,8 @@ char *generate_partition_syntax(partition_info *part_info,
|
|||
part_elem= sub_it++;
|
||||
err+= add_subpartition(fptr);
|
||||
err+= add_name_string(fptr, part_elem->partition_name);
|
||||
err+= add_space(fptr);
|
||||
err+= add_partition_options(fptr, part_elem);
|
||||
if (show_partition_options)
|
||||
err+= add_partition_options(fptr, part_elem);
|
||||
if (j != (no_subparts-1))
|
||||
{
|
||||
err+= add_comma(fptr);
|
||||
|
@ -4996,8 +4999,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
|
|||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
*next_entry= log_entry->entry_pos;
|
||||
if (temp_list)
|
||||
sub_elem->log_entry= log_entry;
|
||||
sub_elem->log_entry= log_entry;
|
||||
insert_part_info_log_entry_list(part_info, log_entry);
|
||||
} while (++j < no_subparts);
|
||||
}
|
||||
|
@ -5015,8 +5017,7 @@ static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
|
|||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
*next_entry= log_entry->entry_pos;
|
||||
if (temp_list)
|
||||
part_elem->log_entry= log_entry;
|
||||
part_elem->log_entry= log_entry;
|
||||
insert_part_info_log_entry_list(part_info, log_entry);
|
||||
}
|
||||
}
|
||||
|
@ -5290,7 +5291,7 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
|
|||
lpt->table_name, "#");
|
||||
pthread_mutex_lock(&LOCK_gdl);
|
||||
if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
|
||||
TRUE))
|
||||
lpt->alter_info->flags & ALTER_REORGANIZE_PARTITION))
|
||||
goto error;
|
||||
if (write_log_changed_partitions(lpt, &next_entry, (const char*)path))
|
||||
goto error;
|
||||
|
@ -5377,6 +5378,79 @@ static void release_log_entries(partition_info *part_info)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Get a lock on table name to avoid that anyone can open the table in
|
||||
a critical part of the ALTER TABLE.
|
||||
SYNOPSIS
|
||||
get_name_lock()
|
||||
lpt Struct carrying parameters
|
||||
RETURN VALUES
|
||||
FALSE Success
|
||||
TRUE Failure
|
||||
*/
|
||||
|
||||
static int get_name_lock(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
{
|
||||
int error= 0;
|
||||
DBUG_ENTER("get_name_lock");
|
||||
|
||||
bzero(&lpt->table_list, sizeof(lpt->table_list));
|
||||
lpt->table_list.db= (char*)lpt->db;
|
||||
lpt->table_list.table= lpt->table;
|
||||
lpt->table_list.table_name= (char*)lpt->table_name;
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
error= lock_table_name(lpt->thd, &lpt->table_list, FALSE);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Unlock and close table before renaming and dropping partitions
|
||||
SYNOPSIS
|
||||
alter_close_tables()
|
||||
lpt Struct carrying parameters
|
||||
RETURN VALUES
|
||||
0
|
||||
*/
|
||||
|
||||
static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
{
|
||||
THD *thd= lpt->thd;
|
||||
TABLE *table= lpt->table;
|
||||
DBUG_ENTER("alter_close_tables");
|
||||
/*
|
||||
We need to also unlock tables and close all handlers.
|
||||
We set lock to zero to ensure we don't do this twice
|
||||
and we set db_stat to zero to ensure we don't close twice.
|
||||
*/
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock= 0;
|
||||
table->file->close();
|
||||
table->db_stat= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Release a lock name
|
||||
SYNOPSIS
|
||||
release_name_lock()
|
||||
lpt
|
||||
RETURN VALUES
|
||||
0
|
||||
*/
|
||||
|
||||
static int release_name_lock(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
{
|
||||
DBUG_ENTER("release_name_lock");
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_name(lpt->thd, &lpt->table_list);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Handle errors for ALTER TABLE for partitioning
|
||||
SYNOPSIS
|
||||
|
@ -5527,7 +5601,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
HA_CREATE_INFO *create_info,
|
||||
TABLE_LIST *table_list,
|
||||
List<create_field> *create_list,
|
||||
List<Key> *key_list, const char *db,
|
||||
List<Key> *key_list, char *db,
|
||||
const char *table_name,
|
||||
uint fast_alter_partition)
|
||||
{
|
||||
|
@ -5544,6 +5618,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
|
||||
lpt->thd= thd;
|
||||
lpt->part_info= part_info;
|
||||
lpt->alter_info= alter_info;
|
||||
lpt->create_info= create_info;
|
||||
lpt->create_list= create_list;
|
||||
lpt->key_list= key_list;
|
||||
|
@ -5667,8 +5742,17 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
2) Write the ddl log to ensure that the operation is completed
|
||||
even in the presence of a MySQL Server crash
|
||||
3) Lock the table in TL_WRITE_ONLY to ensure all other accesses to
|
||||
the table have completed
|
||||
4) Write the bin log
|
||||
the table have completed. This ensures that other threads can not
|
||||
execute on the table in parallel.
|
||||
4) Get a name lock on the table. This ensures that we can release all
|
||||
locks on the table and since no one can open the table, there can
|
||||
be no new threads accessing the table. They will be hanging on the
|
||||
name lock.
|
||||
5) Close all tables that have already been opened but didn't stumble on
|
||||
the abort locked previously. This is done as part of the
|
||||
get_name_lock call.
|
||||
6) We are now ready to release all locks we got in this thread.
|
||||
7) Write the bin log
|
||||
Unfortunately the writing of the binlog is not synchronised with
|
||||
other logging activities. So no matter in which order the binlog
|
||||
is written compared to other activities there will always be cases
|
||||
|
@ -5679,14 +5763,13 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
require writing the statement first in the ddl log and then
|
||||
when recovering from the crash read the binlog and insert it into
|
||||
the binlog if not written already.
|
||||
5) Install the previously written shadow frm file
|
||||
6) Ensure that any users that has opened the table but not yet
|
||||
reached the abort lock do that before downgrading the lock.
|
||||
7) Prepare MyISAM handlers for drop of partitions
|
||||
8) Drop the partitions
|
||||
9) Remove entries from ddl log
|
||||
10) Wait until all accesses using the old frm file has completed
|
||||
11) Complete query
|
||||
8) Install the previously written shadow frm file
|
||||
9) Prepare handlers for drop of partitions
|
||||
10) Drop the partitions
|
||||
11) Remove entries from ddl log
|
||||
12) Release name lock so that all other threads can access the table
|
||||
again.
|
||||
13) Complete query
|
||||
|
||||
We insert Error injections at all places where it could be interesting
|
||||
to test if recovery is properly done.
|
||||
|
@ -5699,22 +5782,24 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
ERROR_INJECT_CRASH("crash_drop_partition_3") ||
|
||||
(not_completed= FALSE) ||
|
||||
abort_and_upgrade_lock(lpt) || /* Always returns 0 */
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_4") ||
|
||||
get_name_lock(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_5") ||
|
||||
alter_close_tables(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_6") ||
|
||||
((!thd->lex->no_write_to_binlog) &&
|
||||
(write_bin_log(thd, FALSE,
|
||||
thd->query, thd->query_length), FALSE)) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_4") ||
|
||||
(table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_5") ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_7") ||
|
||||
((frm_install= TRUE), FALSE) ||
|
||||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
|
||||
((frm_install= FALSE), FALSE) ||
|
||||
(close_open_tables_and_downgrade(lpt), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_6") ||
|
||||
mysql_drop_partitions(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_7") ||
|
||||
(write_log_completed(lpt, FALSE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_8") ||
|
||||
(mysql_wait_completed_table(lpt, table), FALSE))
|
||||
mysql_drop_partitions(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_9") ||
|
||||
(write_log_completed(lpt, FALSE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_drop_partition_10") ||
|
||||
(release_name_lock(lpt), FALSE))
|
||||
{
|
||||
handle_alter_part_error(lpt, not_completed, TRUE, frm_install);
|
||||
DBUG_RETURN(TRUE);
|
||||
|
@ -5740,15 +5825,24 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
3) Lock all partitions in TL_WRITE_ONLY to ensure that no users
|
||||
are still using the old partitioning scheme. Wait until all
|
||||
ongoing users have completed before progressing.
|
||||
4) Write binlog
|
||||
5) Now the change is completed except for the installation of the
|
||||
4) Get a name lock on the table. This ensures that we can release all
|
||||
locks on the table and since no one can open the table, there can
|
||||
be no new threads accessing the table. They will be hanging on the
|
||||
name lock.
|
||||
5) Close all tables that have already been opened but didn't stumble on
|
||||
the abort locked previously. This is done as part of the
|
||||
get_name_lock call.
|
||||
6) Close all table handlers and unlock all handlers but retain name lock
|
||||
7) Write binlog
|
||||
8) Now the change is completed except for the installation of the
|
||||
new frm file. We thus write an action in the log to change to
|
||||
the shadow frm file
|
||||
6) Install the new frm file of the table where the partitions are
|
||||
9) Install the new frm file of the table where the partitions are
|
||||
added to the table.
|
||||
7) Wait until all accesses using the old frm file has completed
|
||||
8) Remove entries from ddl log
|
||||
9) Complete query
|
||||
10)Wait until all accesses using the old frm file has completed
|
||||
11)Remove entries from ddl log
|
||||
12)Release name lock
|
||||
13)Complete query
|
||||
*/
|
||||
if (write_log_add_change_partition(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_1") ||
|
||||
|
@ -5757,19 +5851,24 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
mysql_change_partitions(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_3") ||
|
||||
abort_and_upgrade_lock(lpt) || /* Always returns 0 */
|
||||
ERROR_INJECT_CRASH("crash_add_partition_3") ||
|
||||
get_name_lock(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_4") ||
|
||||
alter_close_tables(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_5") ||
|
||||
((!thd->lex->no_write_to_binlog) &&
|
||||
(write_bin_log(thd, FALSE,
|
||||
thd->query, thd->query_length), FALSE)) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_4") ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_6") ||
|
||||
write_log_rename_frm(lpt) ||
|
||||
(not_completed= FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_5") ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_7") ||
|
||||
((frm_install= TRUE), FALSE) ||
|
||||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_6") ||
|
||||
(close_open_tables_and_downgrade(lpt), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_8") ||
|
||||
(write_log_completed(lpt, FALSE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_add_partition_7"))
|
||||
ERROR_INJECT_CRASH("crash_add_partition_9") ||
|
||||
(release_name_lock(lpt), FALSE))
|
||||
{
|
||||
handle_alter_part_error(lpt, not_completed, FALSE, frm_install);
|
||||
DBUG_RETURN(TRUE);
|
||||
|
@ -5819,16 +5918,20 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
5) Lock all partitions in TL_WRITE_ONLY to ensure that no users
|
||||
are still using the old partitioning scheme. Wait until all
|
||||
ongoing users have completed before progressing.
|
||||
6) Prepare MyISAM handlers for rename and delete of partitions
|
||||
7) Rename the reorged partitions such that they are no longer
|
||||
used and rename those added to their real new names.
|
||||
8) Write bin log
|
||||
9) Install the shadow frm file
|
||||
10) Wait until all accesses using the old frm file has completed
|
||||
11) Drop the reorganised partitions
|
||||
12) Remove log entry
|
||||
13)Wait until all accesses using the old frm file has completed
|
||||
14)Complete query
|
||||
6) Get a name lock of the table
|
||||
7) Close all tables opened but not yet locked, after this call we are
|
||||
certain that no other thread is in the lock wait queue or has
|
||||
opened the table. The name lock will ensure that they are blocked
|
||||
on the open call. This is achieved also by get_name_lock call.
|
||||
8) Close all partitions opened by this thread, but retain name lock.
|
||||
9) Write bin log
|
||||
10) Prepare handlers for rename and delete of partitions
|
||||
11) Rename and drop the reorged partitions such that they are no
|
||||
longer used and rename those added to their real new names.
|
||||
12) Install the shadow frm file
|
||||
13) Release the name lock to enable other threads to start using the
|
||||
table again.
|
||||
14) Complete query
|
||||
*/
|
||||
if (write_log_add_change_partition(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_1") ||
|
||||
|
@ -5840,22 +5943,25 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||
ERROR_INJECT_CRASH("crash_change_partition_4") ||
|
||||
(not_completed= FALSE) ||
|
||||
abort_and_upgrade_lock(lpt) || /* Always returns 0 */
|
||||
ERROR_INJECT_CRASH("crash_change_partition_5") ||
|
||||
get_name_lock(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_6") ||
|
||||
alter_close_tables(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_7") ||
|
||||
((!thd->lex->no_write_to_binlog) &&
|
||||
(write_bin_log(thd, FALSE,
|
||||
thd->query, thd->query_length), FALSE)) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_5") ||
|
||||
(table->file->extra(HA_EXTRA_PREPARE_FOR_DELETE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_6") ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_8") ||
|
||||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_9") ||
|
||||
mysql_drop_partitions(lpt) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_10") ||
|
||||
mysql_rename_partitions(lpt) ||
|
||||
((frm_install= TRUE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_7") ||
|
||||
mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_8") ||
|
||||
(close_open_tables_and_downgrade(lpt), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_9") ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_11") ||
|
||||
(write_log_completed(lpt, FALSE), FALSE) ||
|
||||
ERROR_INJECT_CRASH("crash_change_partition_10") ||
|
||||
(mysql_wait_completed_table(lpt, table), FALSE))
|
||||
ERROR_INJECT_CRASH("crash_change_partition_12") ||
|
||||
(release_name_lock(lpt), FALSE))
|
||||
{
|
||||
handle_alter_part_error(lpt, not_completed, FALSE, frm_install);
|
||||
DBUG_RETURN(TRUE);
|
||||
|
|
|
@ -69,7 +69,8 @@ bool check_partition_info(partition_info *part_info,handlerton **eng_type,
|
|||
bool fix_partition_func(THD *thd, const char *name, TABLE *table,
|
||||
bool create_table_ind);
|
||||
char *generate_partition_syntax(partition_info *part_info,
|
||||
uint *buf_length, bool use_sql_alloc);
|
||||
uint *buf_length, bool use_sql_alloc,
|
||||
bool show_partition_options);
|
||||
bool partition_key_modified(TABLE *table, List<Item> &fields);
|
||||
void get_partition_set(const TABLE *table, byte *buf, const uint index,
|
||||
const key_range *key_spec,
|
||||
|
|
|
@ -970,6 +970,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
|
|||
handler *file= table->file;
|
||||
TABLE_SHARE *share= table->s;
|
||||
HA_CREATE_INFO create_info;
|
||||
bool show_table_options= FALSE;
|
||||
bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
|
||||
MODE_ORACLE |
|
||||
MODE_MSSQL |
|
||||
|
@ -1195,6 +1196,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
|
|||
packet->append(STRING_WITH_LEN("\n)"));
|
||||
if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
|
||||
{
|
||||
show_table_options= TRUE;
|
||||
/*
|
||||
Get possible table space definitions and append them
|
||||
to the CREATE TABLE statement
|
||||
|
@ -1335,7 +1337,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
|
|||
(!table->part_info->is_auto_partitioned) &&
|
||||
((part_syntax= generate_partition_syntax(table->part_info,
|
||||
&part_syntax_len,
|
||||
FALSE))))
|
||||
FALSE,
|
||||
show_table_options))))
|
||||
{
|
||||
packet->append(STRING_WITH_LEN(" /*!50100"));
|
||||
packet->append(part_syntax, part_syntax_len);
|
||||
|
|
|
@ -1233,7 +1233,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
|
|||
{
|
||||
if (!(part_syntax_buf= generate_partition_syntax(part_info,
|
||||
&syntax_len,
|
||||
TRUE)))
|
||||
TRUE, TRUE)))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
@ -3155,7 +3155,7 @@ bool mysql_create_table_internal(THD *thd,
|
|||
*/
|
||||
if (!(part_syntax_buf= generate_partition_syntax(part_info,
|
||||
&syntax_len,
|
||||
TRUE)))
|
||||
TRUE, TRUE)))
|
||||
goto err;
|
||||
part_info->part_info_string= part_syntax_buf;
|
||||
part_info->part_info_len= syntax_len;
|
||||
|
|
|
@ -1933,15 +1933,16 @@ static struct Ev_t {
|
|||
enum_DEL = NdbDictionary::Event::_TE_DELETE,
|
||||
enum_UPD = NdbDictionary::Event::_TE_UPDATE,
|
||||
enum_NUL = NdbDictionary::Event::_TE_NUL,
|
||||
enum_ERR = 255
|
||||
enum_IDM = 254, // idempotent op possibly allowed on NF
|
||||
enum_ERR = 255 // always impossible
|
||||
};
|
||||
int t1, t2, t3;
|
||||
} ev_t[] = {
|
||||
{ Ev_t::enum_INS, Ev_t::enum_INS, Ev_t::enum_ERR },
|
||||
{ Ev_t::enum_INS, Ev_t::enum_INS, Ev_t::enum_IDM },
|
||||
{ Ev_t::enum_INS, Ev_t::enum_DEL, Ev_t::enum_NUL }, //ok
|
||||
{ Ev_t::enum_INS, Ev_t::enum_UPD, Ev_t::enum_INS }, //ok
|
||||
{ Ev_t::enum_DEL, Ev_t::enum_INS, Ev_t::enum_UPD }, //ok
|
||||
{ Ev_t::enum_DEL, Ev_t::enum_DEL, Ev_t::enum_ERR },
|
||||
{ Ev_t::enum_DEL, Ev_t::enum_DEL, Ev_t::enum_IDM },
|
||||
{ Ev_t::enum_DEL, Ev_t::enum_UPD, Ev_t::enum_ERR },
|
||||
{ Ev_t::enum_UPD, Ev_t::enum_INS, Ev_t::enum_ERR },
|
||||
{ Ev_t::enum_UPD, Ev_t::enum_DEL, Ev_t::enum_DEL }, //ok
|
||||
|
@ -2010,6 +2011,34 @@ NdbEventBuffer::merge_data(const SubTableData * const sdata,
|
|||
}
|
||||
assert(tp != 0 && tp->t3 != Ev_t::enum_ERR);
|
||||
|
||||
if (tp->t3 == Ev_t::enum_IDM) {
|
||||
LinearSectionPtr (&ptr1)[3] = data->ptr;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* - can get data in INS ptr2[2] which is supposed to be empty
|
||||
* - can get extra data in DEL ptr2[2]
|
||||
* - why does DBUG_PRINT not work in this file ???
|
||||
*
|
||||
* replication + bug#19872 can ignore this since merge is on
|
||||
* only for tables with explicit PK and before data is not used
|
||||
*/
|
||||
const int maxsec = 1; // ignore section 2
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= maxsec; i++) {
|
||||
if (ptr1[i].sz != ptr2[i].sz ||
|
||||
memcmp(ptr1[i].p, ptr2[i].p, ptr1[i].sz << 2) != 0) {
|
||||
DBUG_PRINT("info", ("idempotent op %d*%d data differs in sec %d",
|
||||
tp->t1, tp->t2, i));
|
||||
assert(false);
|
||||
DBUG_RETURN_EVENT(-1);
|
||||
}
|
||||
}
|
||||
DBUG_PRINT("info", ("idempotent op %d*%d data ok", tp->t1, tp->t2));
|
||||
DBUG_RETURN_EVENT(0);
|
||||
}
|
||||
|
||||
// save old data
|
||||
EventBufData olddata = *data;
|
||||
data->memory = 0;
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
|
||||
|
||||
static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab)
|
||||
static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab,
|
||||
bool merge_events = false)
|
||||
{
|
||||
char eventName[1024];
|
||||
sprintf(eventName,"%s_EVENT",tab.getName());
|
||||
|
@ -45,6 +46,7 @@ static int createEvent(Ndb *pNdb, const NdbDictionary::Table &tab)
|
|||
for(int a = 0; a < tab.getNoOfColumns(); a++){
|
||||
myEvent.addEventColumn(a);
|
||||
}
|
||||
myEvent.mergeEvents(merge_events);
|
||||
|
||||
int res = myDict->createEvent(myEvent); // Add event to database
|
||||
|
||||
|
@ -137,7 +139,8 @@ NdbEventOperation *createEventOperation(Ndb *ndb,
|
|||
|
||||
static int runCreateEvent(NDBT_Context* ctx, NDBT_Step* step)
|
||||
{
|
||||
if (createEvent(GETNDB(step),* ctx->getTab()) != 0){
|
||||
bool merge_events = ctx->getProperty("MergeEvents");
|
||||
if (createEvent(GETNDB(step),* ctx->getTab(), merge_events) != 0){
|
||||
return NDBT_FAILED;
|
||||
}
|
||||
return NDBT_OK;
|
||||
|
@ -584,6 +587,8 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
|
|||
g_err << "Event operation creation failed on %s" << buf << endl;
|
||||
DBUG_RETURN(NDBT_FAILED);
|
||||
}
|
||||
bool merge_events = ctx->getProperty("MergeEvents");
|
||||
pOp->mergeEvents(merge_events);
|
||||
|
||||
int i;
|
||||
int n_columns= table->getNoOfColumns();
|
||||
|
@ -616,6 +621,11 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
|
|||
while ((pOp= ndb->nextEvent()) != 0)
|
||||
{
|
||||
assert(pOp == pCreate);
|
||||
|
||||
if (pOp->getEventType() >=
|
||||
NdbDictionary::Event::TE_FIRST_NON_DATA_EVENT)
|
||||
continue;
|
||||
|
||||
int noRetries= 0;
|
||||
do
|
||||
{
|
||||
|
@ -640,7 +650,7 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
|
|||
goto end;
|
||||
|
||||
}
|
||||
|
||||
|
||||
switch (pOp->getEventType()) {
|
||||
case NdbDictionary::Event::TE_INSERT:
|
||||
if (op->writeTuple())
|
||||
|
@ -1607,6 +1617,33 @@ TESTCASE("EventOperationApplier_NR",
|
|||
FINALIZER(runVerify);
|
||||
FINALIZER(runDropShadowTable);
|
||||
}
|
||||
TESTCASE("MergeEventOperationApplier",
|
||||
"Verify that if we apply the data we get from merged event "
|
||||
"operation is the same as the original table"
|
||||
"NOTE! No errors are allowed!" ){
|
||||
TC_PROPERTY("MergeEvents", 1);
|
||||
INITIALIZER(runCreateEvent);
|
||||
INITIALIZER(runCreateShadowTable);
|
||||
STEP(runEventApplier);
|
||||
STEP(runEventMixedLoad);
|
||||
FINALIZER(runDropEvent);
|
||||
FINALIZER(runVerify);
|
||||
FINALIZER(runDropShadowTable);
|
||||
}
|
||||
TESTCASE("MergeEventOperationApplier_NR",
|
||||
"Verify that if we apply the data we get from merged event "
|
||||
"operation is the same as the original table"
|
||||
"NOTE! No errors are allowed!" ){
|
||||
TC_PROPERTY("MergeEvents", 1);
|
||||
INITIALIZER(runCreateEvent);
|
||||
INITIALIZER(runCreateShadowTable);
|
||||
STEP(runEventApplier);
|
||||
STEP(runEventMixedLoad);
|
||||
STEP(runRestarter);
|
||||
FINALIZER(runDropEvent);
|
||||
FINALIZER(runVerify);
|
||||
FINALIZER(runDropShadowTable);
|
||||
}
|
||||
TESTCASE("Multi",
|
||||
"Verify that we can work with all tables in parallell"
|
||||
"NOTE! HugoOperations::startTransaction, pTrans != NULL errors, "
|
||||
|
|
|
@ -213,6 +213,11 @@ max-time: 2500
|
|||
cmd: test_event
|
||||
args: -n EventOperationApplier_NR -l 2
|
||||
|
||||
#
|
||||
max-time: 2500
|
||||
cmd: test_event
|
||||
args: -n MergeEventOperationApplier_NR -l 2
|
||||
|
||||
#
|
||||
max-time: 2500
|
||||
cmd: test_event
|
||||
|
|
Loading…
Reference in a new issue