mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00

parent
e9ce46a0bc
commit
5e91e260e6
109
mysql-test/r/partition_mgm_err.result
Normal file
109
mysql-test/r/partition_mgm_err.result
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
CREATE TABLE t1 (a int, b int)
|
||||||
|
PARTITION BY RANGE (a)
|
||||||
|
(PARTITION x0 VALUES LESS THAN (2),
|
||||||
|
PARTITION x1 VALUES LESS THAN (4),
|
||||||
|
PARTITION x2 VALUES LESS THAN (6),
|
||||||
|
PARTITION x3 VALUES LESS THAN (8),
|
||||||
|
PARTITION x4 VALUES LESS THAN (10),
|
||||||
|
PARTITION x5 VALUES LESS THAN (12),
|
||||||
|
PARTITION x6 VALUES LESS THAN (14),
|
||||||
|
PARTITION x7 VALUES LESS THAN (16),
|
||||||
|
PARTITION x8 VALUES LESS THAN (18),
|
||||||
|
PARTITION x9 VALUES LESS THAN (20));
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1 INTO
|
||||||
|
(PARTITION x01 VALUES LESS THAN (2),
|
||||||
|
PARTITION x11 VALUES LESS THAN (5));
|
||||||
|
ERROR HY000: The new partitions cover a bigger range then the reorganised partitions do
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0, x1, x2, x3, x3;
|
||||||
|
ERROR HY000: Error in list of partitions to change
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0, x1, x2, x10;
|
||||||
|
ERROR HY000: Error in list of partitions to change
|
||||||
|
ALTER TABLE t1 DROP PARTITION x10, x1, x2, x1;
|
||||||
|
ERROR HY000: Error in list of partitions to change
|
||||||
|
ALTER TABLE t1 DROP PARTITION x10, x1, x2, x3;
|
||||||
|
ERROR HY000: Error in list of partitions to change
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 INTO
|
||||||
|
(PARTITION x11 VALUES LESS THAN (22));
|
||||||
|
ERROR HY000: More partitions to reorganise than there are partitions
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2 INTO
|
||||||
|
(PARTITION x1 VALUES LESS THAN (6));
|
||||||
|
ERROR HY000: All partitions must have unique names in the table
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0, x2 INTO
|
||||||
|
(PARTITION x11 VALUES LESS THAN (2));
|
||||||
|
ERROR HY000: When reorganising a set of partitions they must be in consecutive order
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0, x1, x1 INTO
|
||||||
|
(PARTITION x11 VALUES LESS THAN (4));
|
||||||
|
ERROR HY000: Error in list of partitions to change
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1 INTO
|
||||||
|
(PARTITION x01 VALUES LESS THAN (5));
|
||||||
|
ERROR HY000: The new partitions cover a bigger range then the reorganised partitions do
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1 INTO
|
||||||
|
(PARTITION x01 VALUES LESS THAN (4),
|
||||||
|
PARTITION x11 VALUES LESS THAN (2));
|
||||||
|
ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY KEY (a)
|
||||||
|
PARTITIONS 2;
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION p1);
|
||||||
|
ERROR HY000: All partitions must have unique names in the table
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY KEY (a)
|
||||||
|
(PARTITION x0, PARTITION x1, PARTITION x2, PARTITION x3, PARTITION x3);
|
||||||
|
ERROR HY000: All partitions must have unique names in the table
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY RANGE (a)
|
||||||
|
SUBPARTITION BY KEY (a)
|
||||||
|
SUBPARTITIONS 2
|
||||||
|
(PARTITION x0 VALUES LESS THAN (4),
|
||||||
|
PARTITION x1 VALUES LESS THAN (8));
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION x2 VALUES LESS THAN (5)
|
||||||
|
(SUBPARTITION sp0, SUBPARTITION sp1));
|
||||||
|
ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION x2 VALUES LESS THAN (12)
|
||||||
|
(SUBPARTITION sp0, SUBPARTITION sp1, SUBPARTITION sp2));
|
||||||
|
ERROR HY000: Trying to Add partition(s) with wrong number of subpartitions
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY LIST (a)
|
||||||
|
(PARTITION x0 VALUES IN (1,2,3),
|
||||||
|
PARTITION x1 VALUES IN (4,5,6));
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION x2 VALUES IN (3,4));
|
||||||
|
ERROR HY000: Multiple definition of same constant in list partitioning
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int);
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
|
||||||
|
ERROR HY000: Partition management on a not partitioned table is not possible
|
||||||
|
ALTER TABLE t1 DROP PARTITION x1;
|
||||||
|
ERROR HY000: Partition management on a not partitioned table is not possible
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
ERROR HY000: Partition management on a not partitioned table is not possible
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY KEY (a)
|
||||||
|
(PARTITION x0, PARTITION x1);
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 0;
|
||||||
|
ERROR HY000: At least one partition must be added
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 1024;
|
||||||
|
ERROR HY000: Too many partitions were defined
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0;
|
||||||
|
ERROR HY000: DROP PARTITION can only be used on RANGE/LIST partitions
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
ERROR HY000: Cannot remove all partitions, use DROP TABLE instead
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY RANGE (a)
|
||||||
|
(PARTITION x0 VALUES LESS THAN (4),
|
||||||
|
PARTITION x1 VALUES LESS THAN (8));
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
|
||||||
|
ERROR HY000: For RANGE partitions each partition must be defined
|
||||||
|
ALTER TABLE t1 DROP PARTITION x2;
|
||||||
|
ERROR HY000: Error in list of partitions to change
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
ERROR HY000: COALESCE PARTITION can only be used on HASH/KEY partitions
|
||||||
|
ALTER TABLE t1 DROP PARTITION x1;
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0;
|
||||||
|
ERROR HY000: Cannot remove all partitions, use DROP TABLE instead
|
||||||
|
DROP TABLE t1;
|
@ -726,3 +726,4 @@ partition by list (a)
|
|||||||
partitions 2
|
partitions 2
|
||||||
(partition x1 values in 4,
|
(partition x1 values in 4,
|
||||||
partition x2 values in (5));
|
partition x2 values in (5));
|
||||||
|
|
||||||
|
160
mysql-test/t/partition_mgm_err.test
Normal file
160
mysql-test/t/partition_mgm_err.test
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#
|
||||||
|
# Simple test for the erroneos create statements using the
|
||||||
|
# partition storage engine
|
||||||
|
#
|
||||||
|
-- source include/have_partition.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Try faulty DROP PARTITION and COALESCE PARTITION
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a int, b int)
|
||||||
|
PARTITION BY RANGE (a)
|
||||||
|
(PARTITION x0 VALUES LESS THAN (2),
|
||||||
|
PARTITION x1 VALUES LESS THAN (4),
|
||||||
|
PARTITION x2 VALUES LESS THAN (6),
|
||||||
|
PARTITION x3 VALUES LESS THAN (8),
|
||||||
|
PARTITION x4 VALUES LESS THAN (10),
|
||||||
|
PARTITION x5 VALUES LESS THAN (12),
|
||||||
|
PARTITION x6 VALUES LESS THAN (14),
|
||||||
|
PARTITION x7 VALUES LESS THAN (16),
|
||||||
|
PARTITION x8 VALUES LESS THAN (18),
|
||||||
|
PARTITION x9 VALUES LESS THAN (20));
|
||||||
|
|
||||||
|
--error ER_REORG_OUTSIDE_RANGE
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1 INTO
|
||||||
|
(PARTITION x01 VALUES LESS THAN (2),
|
||||||
|
PARTITION x11 VALUES LESS THAN (5));
|
||||||
|
|
||||||
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0, x1, x2, x3, x3;
|
||||||
|
|
||||||
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0, x1, x2, x10;
|
||||||
|
|
||||||
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
ALTER TABLE t1 DROP PARTITION x10, x1, x2, x1;
|
||||||
|
|
||||||
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
ALTER TABLE t1 DROP PARTITION x10, x1, x2, x3;
|
||||||
|
|
||||||
|
--error ER_REORG_PARTITION_NOT_EXIST
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 INTO
|
||||||
|
(PARTITION x11 VALUES LESS THAN (22));
|
||||||
|
|
||||||
|
--error ER_SAME_NAME_PARTITION
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2 INTO
|
||||||
|
(PARTITION x1 VALUES LESS THAN (6));
|
||||||
|
|
||||||
|
--error ER_CONSECUTIVE_REORG_PARTITIONS
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0, x2 INTO
|
||||||
|
(PARTITION x11 VALUES LESS THAN (2));
|
||||||
|
|
||||||
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0, x1, x1 INTO
|
||||||
|
(PARTITION x11 VALUES LESS THAN (4));
|
||||||
|
|
||||||
|
--error ER_REORG_OUTSIDE_RANGE
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1 INTO
|
||||||
|
(PARTITION x01 VALUES LESS THAN (5));
|
||||||
|
|
||||||
|
--error ER_RANGE_NOT_INCREASING_ERROR
|
||||||
|
ALTER TABLE t1 REORGANISE PARTITION x0,x1 INTO
|
||||||
|
(PARTITION x01 VALUES LESS THAN (4),
|
||||||
|
PARTITION x11 VALUES LESS THAN (2));
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY KEY (a)
|
||||||
|
PARTITIONS 2;
|
||||||
|
|
||||||
|
--error ER_SAME_NAME_PARTITION
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION p1);
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--error ER_SAME_NAME_PARTITION
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY KEY (a)
|
||||||
|
(PARTITION x0, PARTITION x1, PARTITION x2, PARTITION x3, PARTITION x3);
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY RANGE (a)
|
||||||
|
SUBPARTITION BY KEY (a)
|
||||||
|
SUBPARTITIONS 2
|
||||||
|
(PARTITION x0 VALUES LESS THAN (4),
|
||||||
|
PARTITION x1 VALUES LESS THAN (8));
|
||||||
|
|
||||||
|
--error ER_RANGE_NOT_INCREASING_ERROR
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION x2 VALUES LESS THAN (5)
|
||||||
|
(SUBPARTITION sp0, SUBPARTITION sp1));
|
||||||
|
|
||||||
|
--error ER_ADD_PARTITION_SUBPART_ERROR
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION x2 VALUES LESS THAN (12)
|
||||||
|
(SUBPARTITION sp0, SUBPARTITION sp1, SUBPARTITION sp2));
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY LIST (a)
|
||||||
|
(PARTITION x0 VALUES IN (1,2,3),
|
||||||
|
PARTITION x1 VALUES IN (4,5,6));
|
||||||
|
|
||||||
|
--error ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR
|
||||||
|
ALTER TABLE t1 ADD PARTITION (PARTITION x2 VALUES IN (3,4));
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int);
|
||||||
|
|
||||||
|
--error ER_PARTITION_MGMT_ON_NONPARTITIONED
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
|
||||||
|
|
||||||
|
--error ER_PARTITION_MGMT_ON_NONPARTITIONED
|
||||||
|
ALTER TABLE t1 DROP PARTITION x1;
|
||||||
|
|
||||||
|
--error ER_PARTITION_MGMT_ON_NONPARTITIONED
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY KEY (a)
|
||||||
|
(PARTITION x0, PARTITION x1);
|
||||||
|
|
||||||
|
--error ER_ADD_PARTITION_NO_NEW_PARTITION
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 0;
|
||||||
|
|
||||||
|
--error ER_TOO_MANY_PARTITIONS_ERROR
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 1024;
|
||||||
|
|
||||||
|
--error ER_ONLY_ON_RANGE_LIST_PARTITION
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0;
|
||||||
|
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
|
||||||
|
--error ER_DROP_LAST_PARTITION
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int)
|
||||||
|
PARTITION BY RANGE (a)
|
||||||
|
(PARTITION x0 VALUES LESS THAN (4),
|
||||||
|
PARTITION x1 VALUES LESS THAN (8));
|
||||||
|
|
||||||
|
--error ER_PARTITIONS_MUST_BE_DEFINED_ERROR
|
||||||
|
ALTER TABLE t1 ADD PARTITION PARTITIONS 1;
|
||||||
|
|
||||||
|
--error ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
ALTER TABLE t1 DROP PARTITION x2;
|
||||||
|
|
||||||
|
--error ER_COALESCE_ONLY_ON_HASH_PARTITION
|
||||||
|
ALTER TABLE t1 COALESCE PARTITION 1;
|
||||||
|
|
||||||
|
ALTER TABLE t1 DROP PARTITION x1;
|
||||||
|
|
||||||
|
--error ER_DROP_LAST_PARTITION
|
||||||
|
ALTER TABLE t1 DROP PARTITION x0;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
@ -269,6 +269,28 @@ int ha_partition::ha_initialise()
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
MODULE meta data changes
|
MODULE meta data changes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
/*
|
||||||
|
This method is used to calculate the partition name, service routine to
|
||||||
|
the del_ren_cre_table method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void create_partition_name(char *out, const char *in1, const char *in2)
|
||||||
|
{
|
||||||
|
strxmov(out, in1, "_", in2, NullS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This method is used to calculate the partition name, service routine to
|
||||||
|
the del_ren_cre_table method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void create_subpartition_name(char *out, const char *in1,
|
||||||
|
const char *in2, const char *in3)
|
||||||
|
{
|
||||||
|
strxmov(out, in1, "_", in2, "_", in3, NullS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Used to delete a table. By the time delete_table() has been called all
|
Used to delete a table. By the time delete_table() has been called all
|
||||||
opened references to this table will have been closed (and your globally
|
opened references to this table will have been closed (and your globally
|
||||||
@ -326,6 +348,12 @@ int ha_partition::rename_table(const char *from, const char *to)
|
|||||||
int ha_partition::create_handler_files(const char *name)
|
int ha_partition::create_handler_files(const char *name)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("ha_partition::create_handler_files()");
|
DBUG_ENTER("ha_partition::create_handler_files()");
|
||||||
|
|
||||||
|
/*
|
||||||
|
We need to update total number of parts since we might write the handler
|
||||||
|
file as part of a partition management command
|
||||||
|
*/
|
||||||
|
m_tot_parts= get_tot_partitions(m_part_info);
|
||||||
if (create_handler_file(name))
|
if (create_handler_file(name))
|
||||||
{
|
{
|
||||||
my_error(ER_CANT_CREATE_HANDLER_FILE, MYF(0));
|
my_error(ER_CANT_CREATE_HANDLER_FILE, MYF(0));
|
||||||
@ -362,6 +390,49 @@ int ha_partition::create(const char *name, TABLE *table_arg,
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ha_partition::drop_partitions(const char *path)
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> part_it(m_part_info->partitions);
|
||||||
|
char part_name_buff[FN_REFLEN];
|
||||||
|
uint no_parts= m_part_info->no_parts;
|
||||||
|
uint no_subparts= m_part_info->no_subparts, i= 0;
|
||||||
|
int error= 1;
|
||||||
|
DBUG_ENTER("ha_partition::drop_partitions()");
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *part_elem= part_it++;
|
||||||
|
if (part_elem->part_state == PART_IS_DROPPED)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This part is to be dropped, meaning the part or all its subparts.
|
||||||
|
*/
|
||||||
|
if (is_sub_partitioned(m_part_info))
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> sub_it(part_elem->subpartitions);
|
||||||
|
uint j= 0, part;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *sub_elem= sub_it++;
|
||||||
|
create_subpartition_name(part_name_buff, path,
|
||||||
|
part_elem->partition_name,
|
||||||
|
sub_elem->partition_name);
|
||||||
|
part= i * no_subparts + j;
|
||||||
|
DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff));
|
||||||
|
error= m_file[part]->delete_table((const char *) part_name_buff);
|
||||||
|
} while (++j < no_subparts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
create_partition_name(part_name_buff, path,
|
||||||
|
part_elem->partition_name);
|
||||||
|
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
|
||||||
|
error= m_file[i]->delete_table((const char *) part_name_buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (++i < no_parts);
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
}
|
||||||
|
|
||||||
void ha_partition::update_create_info(HA_CREATE_INFO *create_info)
|
void ha_partition::update_create_info(HA_CREATE_INFO *create_info)
|
||||||
{
|
{
|
||||||
@ -375,16 +446,6 @@ char *ha_partition::update_table_comment(const char *comment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
This method is used to calculate the partition name, service routine to
|
|
||||||
the del_ren_cre_table method.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void create_partition_name(char *out, const char *in1, const char *in2)
|
|
||||||
{
|
|
||||||
strxmov(out, in1, "_", in2, NullS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Common routine to handle delete_table and rename_table.
|
Common routine to handle delete_table and rename_table.
|
||||||
|
@ -166,6 +166,7 @@ public:
|
|||||||
virtual int create_handler_files(const char *name);
|
virtual int create_handler_files(const char *name);
|
||||||
virtual void update_create_info(HA_CREATE_INFO * create_info);
|
virtual void update_create_info(HA_CREATE_INFO * create_info);
|
||||||
virtual char *update_table_comment(const char *comment);
|
virtual char *update_table_comment(const char *comment);
|
||||||
|
virtual int drop_partitions(const char *path);
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
delete_table, rename_table and create uses very similar logic which
|
delete_table, rename_table and create uses very similar logic which
|
||||||
@ -633,6 +634,11 @@ public:
|
|||||||
index scan module.
|
index scan module.
|
||||||
(NDB)
|
(NDB)
|
||||||
*/
|
*/
|
||||||
|
virtual ulong alter_table_flags(void) const
|
||||||
|
{
|
||||||
|
//return HA_ONLINE_ADD_EMPTY_PARTITION + HA_ONLINE_DROP_PARTITION;
|
||||||
|
return HA_ONLINE_DROP_PARTITION;
|
||||||
|
}
|
||||||
virtual ulong table_flags() const
|
virtual ulong table_flags() const
|
||||||
{ return m_table_flags; }
|
{ return m_table_flags; }
|
||||||
/*
|
/*
|
||||||
|
@ -103,6 +103,10 @@
|
|||||||
#define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
|
#define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
|
||||||
#define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
|
#define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
|
||||||
|
|
||||||
|
/* bits in alter_table_flags */
|
||||||
|
#define HA_ONLINE_ADD_EMPTY_PARTITION 1
|
||||||
|
#define HA_ONLINE_DROP_PARTITION 2
|
||||||
|
|
||||||
/* operations for disable/enable indexes */
|
/* operations for disable/enable indexes */
|
||||||
#define HA_KEY_SWITCH_NONUNIQ 0
|
#define HA_KEY_SWITCH_NONUNIQ 0
|
||||||
#define HA_KEY_SWITCH_ALL 1
|
#define HA_KEY_SWITCH_ALL 1
|
||||||
@ -399,6 +403,16 @@ enum partition_type {
|
|||||||
LIST_PARTITION
|
LIST_PARTITION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum partition_state {
|
||||||
|
PART_NORMAL= 0,
|
||||||
|
PART_IS_DROPPED= 1,
|
||||||
|
PART_TO_BE_DROPPED= 2,
|
||||||
|
PART_DROPPING= 3,
|
||||||
|
PART_IS_ADDED= 4,
|
||||||
|
PART_ADDING= 5,
|
||||||
|
PART_ADDED= 6
|
||||||
|
};
|
||||||
|
|
||||||
#define UNDEF_NODEGROUP 65535
|
#define UNDEF_NODEGROUP 65535
|
||||||
class Item;
|
class Item;
|
||||||
|
|
||||||
@ -415,13 +429,15 @@ public:
|
|||||||
char* data_file_name;
|
char* data_file_name;
|
||||||
char* index_file_name;
|
char* index_file_name;
|
||||||
enum db_type engine_type;
|
enum db_type engine_type;
|
||||||
|
enum partition_state part_state;
|
||||||
uint16 nodegroup_id;
|
uint16 nodegroup_id;
|
||||||
|
|
||||||
partition_element()
|
partition_element()
|
||||||
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
|
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
|
||||||
tablespace_name(NULL), range_value(0), part_comment(NULL),
|
tablespace_name(NULL), range_value(0), part_comment(NULL),
|
||||||
data_file_name(NULL), index_file_name(NULL),
|
data_file_name(NULL), index_file_name(NULL),
|
||||||
engine_type(DB_TYPE_UNKNOWN), nodegroup_id(UNDEF_NODEGROUP)
|
engine_type(DB_TYPE_UNKNOWN),part_state(PART_NORMAL),
|
||||||
|
nodegroup_id(UNDEF_NODEGROUP)
|
||||||
{
|
{
|
||||||
subpartitions.empty();
|
subpartitions.empty();
|
||||||
list_val_list.empty();
|
list_val_list.empty();
|
||||||
@ -447,6 +463,7 @@ public:
|
|||||||
* Here comes a set of definitions needed for partitioned table handlers.
|
* Here comes a set of definitions needed for partitioned table handlers.
|
||||||
*/
|
*/
|
||||||
List<partition_element> partitions;
|
List<partition_element> partitions;
|
||||||
|
List<partition_element> temp_partitions;
|
||||||
|
|
||||||
List<char> part_field_list;
|
List<char> part_field_list;
|
||||||
List<char> subpart_field_list;
|
List<char> subpart_field_list;
|
||||||
@ -492,7 +509,6 @@ public:
|
|||||||
uint part_func_len;
|
uint part_func_len;
|
||||||
uint subpart_func_len;
|
uint subpart_func_len;
|
||||||
|
|
||||||
uint no_full_parts;
|
|
||||||
uint no_parts;
|
uint no_parts;
|
||||||
uint no_subparts;
|
uint no_subparts;
|
||||||
uint count_curr_parts;
|
uint count_curr_parts;
|
||||||
@ -529,7 +545,7 @@ public:
|
|||||||
part_result_type(INT_RESULT),
|
part_result_type(INT_RESULT),
|
||||||
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
|
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
|
||||||
part_info_len(0), part_func_len(0), subpart_func_len(0),
|
part_info_len(0), part_func_len(0), subpart_func_len(0),
|
||||||
no_full_parts(0), no_parts(0), no_subparts(0),
|
no_parts(0), no_subparts(0),
|
||||||
count_curr_parts(0), count_curr_subparts(0), part_error_code(0),
|
count_curr_parts(0), count_curr_subparts(0), part_error_code(0),
|
||||||
no_list_values(0), no_part_fields(0), no_subpart_fields(0),
|
no_list_values(0), no_part_fields(0), no_subpart_fields(0),
|
||||||
no_full_part_fields(0), linear_hash_mask(0),
|
no_full_part_fields(0), linear_hash_mask(0),
|
||||||
@ -543,6 +559,7 @@ public:
|
|||||||
all_fields_in_SPF.clear_all();
|
all_fields_in_SPF.clear_all();
|
||||||
some_fields_in_PF.clear_all();
|
some_fields_in_PF.clear_all();
|
||||||
partitions.empty();
|
partitions.empty();
|
||||||
|
temp_partitions.empty();
|
||||||
part_field_list.empty();
|
part_field_list.empty();
|
||||||
subpart_field_list.empty();
|
subpart_field_list.empty();
|
||||||
}
|
}
|
||||||
@ -634,6 +651,13 @@ typedef struct st_ha_check_opt
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_PARTITION_DB
|
#ifdef HAVE_PARTITION_DB
|
||||||
|
bool is_partition_in_list(char *part_name, List<char> list_part_names);
|
||||||
|
bool is_partitions_in_table(partition_info *new_part_info,
|
||||||
|
partition_info *old_part_info);
|
||||||
|
bool set_up_defaults_for_partitioning(partition_info *part_info,
|
||||||
|
handler *file,
|
||||||
|
ulonglong max_rows,
|
||||||
|
uint start_no);
|
||||||
handler *get_ha_partition(partition_info *part_info);
|
handler *get_ha_partition(partition_info *part_info);
|
||||||
int get_parts_for_update(const byte *old_data, byte *new_data,
|
int get_parts_for_update(const byte *old_data, byte *new_data,
|
||||||
const byte *rec0, partition_info *part_info,
|
const byte *rec0, partition_info *part_info,
|
||||||
@ -1138,6 +1162,20 @@ public:
|
|||||||
virtual char *update_table_comment(const char * comment)
|
virtual char *update_table_comment(const char * comment)
|
||||||
{ return (char*) comment;}
|
{ return (char*) comment;}
|
||||||
virtual void append_create_info(String *packet) {}
|
virtual void append_create_info(String *packet) {}
|
||||||
|
/*
|
||||||
|
SYNOPSIS
|
||||||
|
is_fk_defined_on_table_or_index()
|
||||||
|
index Index to check if foreign key uses it
|
||||||
|
RETURN VALUE
|
||||||
|
TRUE Foreign key defined on table or index
|
||||||
|
FALSE No foreign key defined
|
||||||
|
DESCRIPTION
|
||||||
|
If index == MAX_KEY then a check for table is made and if index <
|
||||||
|
MAX_KEY then a check is made if the table has foreign keys and if
|
||||||
|
a foreign key uses this index (and thus the index cannot be dropped).
|
||||||
|
*/
|
||||||
|
virtual bool is_fk_defined_on_table_or_index(uint index)
|
||||||
|
{ return FALSE; }
|
||||||
virtual char* get_foreign_key_create_info()
|
virtual char* get_foreign_key_create_info()
|
||||||
{ return(NULL);} /* gets foreign key create string from InnoDB */
|
{ return(NULL);} /* gets foreign key create string from InnoDB */
|
||||||
/* used in ALTER TABLE; 1 if changing storage engine is allowed */
|
/* used in ALTER TABLE; 1 if changing storage engine is allowed */
|
||||||
@ -1153,6 +1191,7 @@ public:
|
|||||||
virtual const char *table_type() const =0;
|
virtual const char *table_type() const =0;
|
||||||
virtual const char **bas_ext() const =0;
|
virtual const char **bas_ext() const =0;
|
||||||
virtual ulong table_flags(void) const =0;
|
virtual ulong table_flags(void) const =0;
|
||||||
|
virtual ulong alter_table_flags(void) const { return 0; }
|
||||||
#ifdef HAVE_PARTITION_DB
|
#ifdef HAVE_PARTITION_DB
|
||||||
virtual ulong partition_flags(void) const { return 0;}
|
virtual ulong partition_flags(void) const { return 0;}
|
||||||
virtual int get_default_no_partitions(ulonglong max_rows) { return 1;}
|
virtual int get_default_no_partitions(ulonglong max_rows) { return 1;}
|
||||||
@ -1198,6 +1237,19 @@ public:
|
|||||||
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
|
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
|
||||||
virtual int create_handler_files(const char *name) { return FALSE;}
|
virtual int create_handler_files(const char *name) { return FALSE;}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SYNOPSIS
|
||||||
|
drop_partitions()
|
||||||
|
path Complete path of db and table name
|
||||||
|
RETURN VALUE
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
DESCRIPTION
|
||||||
|
Drop a partition, during this operation no other activity is ongoing
|
||||||
|
in this server on the table.
|
||||||
|
*/
|
||||||
|
virtual int drop_partitions(const char *path)
|
||||||
|
{ return HA_ERR_WRONG_COMMAND; }
|
||||||
/* lock_count() can be more than one if the table is a MERGE */
|
/* lock_count() can be more than one if the table is a MERGE */
|
||||||
virtual uint lock_count(void) const { return 1; }
|
virtual uint lock_count(void) const { return 1; }
|
||||||
virtual THR_LOCK_DATA **store_lock(THD *thd,
|
virtual THR_LOCK_DATA **store_lock(THD *thd,
|
||||||
|
@ -110,6 +110,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "CIPHER", SYM(CIPHER_SYM)},
|
{ "CIPHER", SYM(CIPHER_SYM)},
|
||||||
{ "CLIENT", SYM(CLIENT_SYM)},
|
{ "CLIENT", SYM(CLIENT_SYM)},
|
||||||
{ "CLOSE", SYM(CLOSE_SYM)},
|
{ "CLOSE", SYM(CLOSE_SYM)},
|
||||||
|
{ "COALESCE", SYM(COALESCE)},
|
||||||
{ "COLLATE", SYM(COLLATE_SYM)},
|
{ "COLLATE", SYM(COLLATE_SYM)},
|
||||||
{ "COLLATION", SYM(COLLATION_SYM)},
|
{ "COLLATION", SYM(COLLATION_SYM)},
|
||||||
{ "COLUMN", SYM(COLUMN_SYM)},
|
{ "COLUMN", SYM(COLUMN_SYM)},
|
||||||
@ -408,6 +409,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "RELEASE", SYM(RELEASE_SYM)},
|
{ "RELEASE", SYM(RELEASE_SYM)},
|
||||||
{ "RELOAD", SYM(RELOAD)},
|
{ "RELOAD", SYM(RELOAD)},
|
||||||
{ "RENAME", SYM(RENAME)},
|
{ "RENAME", SYM(RENAME)},
|
||||||
|
{ "REORGANISE", SYM(REORGANISE_SYM)},
|
||||||
{ "REPAIR", SYM(REPAIR)},
|
{ "REPAIR", SYM(REPAIR)},
|
||||||
{ "REPEATABLE", SYM(REPEATABLE_SYM)},
|
{ "REPEATABLE", SYM(REPEATABLE_SYM)},
|
||||||
{ "REPLACE", SYM(REPLACE)},
|
{ "REPLACE", SYM(REPLACE)},
|
||||||
@ -589,7 +591,6 @@ static SYMBOL sql_functions[] = {
|
|||||||
{ "CENTROID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)},
|
{ "CENTROID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)},
|
||||||
{ "CHAR_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
|
{ "CHAR_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
|
||||||
{ "CHARACTER_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
|
{ "CHARACTER_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
|
||||||
{ "COALESCE", SYM(COALESCE)},
|
|
||||||
{ "COERCIBILITY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)},
|
{ "COERCIBILITY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)},
|
||||||
{ "COMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)},
|
{ "COMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)},
|
||||||
{ "CONCAT", SYM(CONCAT)},
|
{ "CONCAT", SYM(CONCAT)},
|
||||||
|
@ -627,6 +627,10 @@ bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
bool no_errors);
|
bool no_errors);
|
||||||
bool check_global_access(THD *thd, ulong want_access);
|
bool check_global_access(THD *thd, ulong want_access);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Support routine for SQL parser on partitioning syntax
|
||||||
|
*/
|
||||||
|
my_bool is_partition_management(LEX *lex);
|
||||||
/*
|
/*
|
||||||
General routine to change field->ptr of a NULL-terminated array of Field
|
General routine to change field->ptr of a NULL-terminated array of Field
|
||||||
objects. Useful when needed to call val_int, val_str or similar and the
|
objects. Useful when needed to call val_int, val_str or similar and the
|
||||||
|
@ -5440,7 +5440,7 @@ ER_PARTITION_ENTRY_ERROR
|
|||||||
eng "Partitioning can not be used stand-alone in query"
|
eng "Partitioning can not be used stand-alone in query"
|
||||||
swe "Partitioneringssyntax kan inte anv<6E>ndas p<> egen hand i en SQL-fr<66>ga"
|
swe "Partitioneringssyntax kan inte anv<6E>ndas p<> egen hand i en SQL-fr<66>ga"
|
||||||
ER_MIX_HANDLER_ERROR
|
ER_MIX_HANDLER_ERROR
|
||||||
eng "The mix of handlers in the partitions is not allowed in this version in MySQL"
|
eng "The mix of handlers in the partitions is not allowed in this version of MySQL"
|
||||||
swe "Denna mix av lagringsmotorer <20>r inte till<6C>ten i denna version av MySQL"
|
swe "Denna mix av lagringsmotorer <20>r inte till<6C>ten i denna version av MySQL"
|
||||||
ER_PARTITION_NOT_DEFINED_ERROR
|
ER_PARTITION_NOT_DEFINED_ERROR
|
||||||
eng "For the partitioned engine it is necessary to define all %s"
|
eng "For the partitioned engine it is necessary to define all %s"
|
||||||
@ -5466,3 +5466,44 @@ ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF
|
|||||||
ER_NO_PARTS_ERROR
|
ER_NO_PARTS_ERROR
|
||||||
eng "Number of %s = 0 is not an allowed value"
|
eng "Number of %s = 0 is not an allowed value"
|
||||||
swe "Antal %s = 0 <20>r inte ett till<6C>ten v<>rde"
|
swe "Antal %s = 0 <20>r inte ett till<6C>ten v<>rde"
|
||||||
|
ER_PARTITION_MGMT_ON_NONPARTITIONED
|
||||||
|
eng "Partition management on a not partitioned table is not possible"
|
||||||
|
swe "Partitioneringskommando p<> en opartitionerad tabell <20>r inte m<>jligt"
|
||||||
|
ER_DROP_PARTITION_NON_EXISTENT
|
||||||
|
eng "Error in list of partitions to change"
|
||||||
|
swe "Fel i listan av partitioner att f<>r<EFBFBD>ndra"
|
||||||
|
ER_DROP_LAST_PARTITION
|
||||||
|
eng "Cannot remove all partitions, use DROP TABLE instead"
|
||||||
|
swe "Det <20>r inte till<6C>tet att ta bort alla partitioner, anv<6E>nd DROP TABLE ist<73>llet"
|
||||||
|
ER_COALESCE_ONLY_ON_HASH_PARTITION
|
||||||
|
eng "COALESCE PARTITION can only be used on HASH/KEY partitions"
|
||||||
|
swe "COALESCE PARTITION kan bara anv<6E>ndas p<> HASH/KEY partitioner"
|
||||||
|
ER_ONLY_ON_RANGE_LIST_PARTITION
|
||||||
|
eng "%s PARTITION can only be used on RANGE/LIST partitions"
|
||||||
|
eng "%s PARTITION kan bara anv<6E>ndas p<> RANGE/LIST partitioner"
|
||||||
|
ER_ADD_PARTITION_SUBPART_ERROR
|
||||||
|
eng "Trying to Add partition(s) with wrong number of subpartitions"
|
||||||
|
swe "ADD PARTITION med fel antal subpartitioner"
|
||||||
|
ER_ADD_PARTITION_NO_NEW_PARTITION
|
||||||
|
eng "At least one partition must be added"
|
||||||
|
swe "<22>tminstone en partition m<>ste l<>ggas till vid ADD PARTITION"
|
||||||
|
ER_COALESCE_PARTITION_NO_PARTITION
|
||||||
|
eng "At least one partition must be coalesced"
|
||||||
|
swe "<22>tminstone en partition m<>ste sl<73>s ihop vid COALESCE PARTITION"
|
||||||
|
ER_REORG_PARTITION_NOT_EXIST
|
||||||
|
eng "More partitions to reorganise than there are partitions"
|
||||||
|
swe "Fler partitioner att reorganisera <20>n det finns partitioner"
|
||||||
|
ER_SAME_NAME_PARTITION
|
||||||
|
eng "All partitions must have unique names in the table"
|
||||||
|
swe "Alla partitioner i tabellen m<>ste ha unika namn"
|
||||||
|
ER_CONSECUTIVE_REORG_PARTITIONS
|
||||||
|
eng "When reorganising a set of partitions they must be in consecutive order"
|
||||||
|
swe "N<>r ett antal partitioner omorganiseras m<>ste de vara i konsekutiv ordning"
|
||||||
|
ER_REORG_OUTSIDE_RANGE
|
||||||
|
eng "The new partitions cover a bigger range then the reorganised partitions do"
|
||||||
|
swe "De nya partitionerna t<>cker ett st<73>rre intervall <20>n de omorganiserade partitionerna"
|
||||||
|
ER_DROP_PARTITION_FAILURE
|
||||||
|
eng "Drop partition not supported in this version for this handler"
|
||||||
|
ER_DROP_PARTITION_WHEN_FK_DEFINED
|
||||||
|
eng "Cannot drop a partition when a foreign key constraint is defined on the table"
|
||||||
|
swe "Kan inte ta bort en partition n<>r en fr<66>mmande nyckel <20>r definierad p<> tabellen"
|
||||||
|
@ -650,6 +650,10 @@ typedef class st_select_lex SELECT_LEX;
|
|||||||
#define ALTER_CONVERT 1024
|
#define ALTER_CONVERT 1024
|
||||||
#define ALTER_FORCE 2048
|
#define ALTER_FORCE 2048
|
||||||
#define ALTER_RECREATE 4096
|
#define ALTER_RECREATE 4096
|
||||||
|
#define ALTER_ADD_PARTITION 8192
|
||||||
|
#define ALTER_DROP_PARTITION 16384
|
||||||
|
#define ALTER_COALESCE_PARTITION 32768
|
||||||
|
#define ALTER_REORGANISE_PARTITION 65536
|
||||||
|
|
||||||
typedef struct st_alter_info
|
typedef struct st_alter_info
|
||||||
{
|
{
|
||||||
@ -658,9 +662,17 @@ typedef struct st_alter_info
|
|||||||
uint flags;
|
uint flags;
|
||||||
enum enum_enable_or_disable keys_onoff;
|
enum enum_enable_or_disable keys_onoff;
|
||||||
enum tablespace_op_type tablespace_op;
|
enum tablespace_op_type tablespace_op;
|
||||||
|
List<char> partition_names;
|
||||||
|
uint no_parts;
|
||||||
|
|
||||||
st_alter_info(){clear();}
|
st_alter_info(){clear();}
|
||||||
void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
|
void clear()
|
||||||
|
{
|
||||||
|
keys_onoff= LEAVE_AS_IS;
|
||||||
|
tablespace_op= NO_TABLESPACE_OP;
|
||||||
|
no_parts= 0;
|
||||||
|
partition_names.empty();
|
||||||
|
}
|
||||||
void reset(){drop_list.empty();alter_list.empty();clear();}
|
void reset(){drop_list.empty();alter_list.empty();clear();}
|
||||||
} ALTER_INFO;
|
} ALTER_INFO;
|
||||||
|
|
||||||
|
@ -89,6 +89,105 @@ uint32 get_partition_id_hash_sub(partition_info *part_info);
|
|||||||
uint32 get_partition_id_key_sub(partition_info *part_info);
|
uint32 get_partition_id_key_sub(partition_info *part_info);
|
||||||
uint32 get_partition_id_linear_hash_sub(partition_info *part_info);
|
uint32 get_partition_id_linear_hash_sub(partition_info *part_info);
|
||||||
uint32 get_partition_id_linear_key_sub(partition_info *part_info);
|
uint32 get_partition_id_linear_key_sub(partition_info *part_info);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
A routine used by the parser to decide whether we are specifying a full
|
||||||
|
partitioning or if only partitions to add or to split.
|
||||||
|
SYNOPSIS
|
||||||
|
is_partition_management()
|
||||||
|
lex Reference to the lex object
|
||||||
|
RETURN VALUE
|
||||||
|
TRUE Yes, it is part of a management partition command
|
||||||
|
FALSE No, not a management partition command
|
||||||
|
DESCRIPTION
|
||||||
|
This needs to be outside of HAVE_PARTITION_DB since it is used from the
|
||||||
|
sql parser that doesn't have any #ifdef's
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool is_partition_management(LEX *lex)
|
||||||
|
{
|
||||||
|
return (lex->sql_command == SQLCOM_ALTER_TABLE &&
|
||||||
|
(lex->alter_info.flags == ALTER_ADD_PARTITION ||
|
||||||
|
lex->alter_info.flags == ALTER_REORGANISE_PARTITION));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PARTITION_DB
|
||||||
|
/*
|
||||||
|
A support function to check if a partition name is in a list of strings
|
||||||
|
SYNOPSIS
|
||||||
|
is_partition_in_list()
|
||||||
|
part_name String searched for
|
||||||
|
list_part_names A list of names searched in
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE String found
|
||||||
|
FALSE String not found
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool is_partition_in_list(char *part_name,
|
||||||
|
List<char> list_part_names)
|
||||||
|
{
|
||||||
|
List_iterator<char> part_names_it(list_part_names);
|
||||||
|
uint no_names= list_part_names.elements;
|
||||||
|
uint i= 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char *list_name= part_names_it++;
|
||||||
|
if (!(my_strcasecmp(system_charset_info, part_name, list_name)))
|
||||||
|
return TRUE;
|
||||||
|
} while (++i < no_names);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
A support function to check partition names for duplication in a
|
||||||
|
partitioned table
|
||||||
|
SYNOPSIS
|
||||||
|
is_partitions_in_table()
|
||||||
|
new_part_info New partition info
|
||||||
|
old_part_info Old partition info
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Duplicate names found
|
||||||
|
FALSE Duplicate names not found
|
||||||
|
DESCRIPTION
|
||||||
|
Can handle that the new and old parts are the same in which case it
|
||||||
|
checks that the list of names in the partitions doesn't contain any
|
||||||
|
duplicated names.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool is_partitions_in_table(partition_info *new_part_info,
|
||||||
|
partition_info *old_part_info)
|
||||||
|
{
|
||||||
|
uint no_new_parts= new_part_info->partitions.elements, new_count;
|
||||||
|
uint no_old_parts= old_part_info->partitions.elements, old_count;
|
||||||
|
List_iterator<partition_element> new_parts_it(new_part_info->partitions);
|
||||||
|
bool same_part_info= (new_part_info == old_part_info);
|
||||||
|
DBUG_ENTER("is_partitions_in_table");
|
||||||
|
|
||||||
|
new_count= 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> old_parts_it(old_part_info->partitions);
|
||||||
|
char *new_name= (new_parts_it++)->partition_name;
|
||||||
|
new_count++;
|
||||||
|
old_count= 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char *old_name= (old_parts_it++)->partition_name;
|
||||||
|
old_count++;
|
||||||
|
if (same_part_info && old_count == new_count)
|
||||||
|
break;
|
||||||
|
if (!(my_strcasecmp(system_charset_info, old_name, new_name)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
} while (old_count < no_old_parts);
|
||||||
|
} while (new_count < no_new_parts);
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A useful routine used by update_row for partition handlers to calculate
|
A useful routine used by update_row for partition handlers to calculate
|
||||||
@ -415,7 +514,8 @@ end:
|
|||||||
|
|
||||||
#define MAX_PART_NAME_SIZE 8
|
#define MAX_PART_NAME_SIZE 8
|
||||||
|
|
||||||
static char *create_default_partition_names(uint no_parts, bool subpart)
|
static char *create_default_partition_names(uint no_parts, uint start_no,
|
||||||
|
bool subpart)
|
||||||
{
|
{
|
||||||
char *ptr= sql_calloc(no_parts*MAX_PART_NAME_SIZE);
|
char *ptr= sql_calloc(no_parts*MAX_PART_NAME_SIZE);
|
||||||
char *move_ptr= ptr;
|
char *move_ptr= ptr;
|
||||||
@ -426,9 +526,9 @@ static char *create_default_partition_names(uint no_parts, bool subpart)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (subpart)
|
if (subpart)
|
||||||
my_sprintf(move_ptr, (move_ptr,"sp%u", i));
|
my_sprintf(move_ptr, (move_ptr,"sp%u", (start_no + i)));
|
||||||
else
|
else
|
||||||
my_sprintf(move_ptr, (move_ptr,"p%u", i));
|
my_sprintf(move_ptr, (move_ptr,"p%u", (start_no + i)));
|
||||||
move_ptr+=MAX_PART_NAME_SIZE;
|
move_ptr+=MAX_PART_NAME_SIZE;
|
||||||
} while (++i < no_parts);
|
} while (++i < no_parts);
|
||||||
}
|
}
|
||||||
@ -462,7 +562,8 @@ static char *create_default_partition_names(uint no_parts, bool subpart)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static bool set_up_default_partitions(partition_info *part_info,
|
static bool set_up_default_partitions(partition_info *part_info,
|
||||||
handler *file, ulonglong max_rows)
|
handler *file, ulonglong max_rows,
|
||||||
|
uint start_no)
|
||||||
{
|
{
|
||||||
uint no_parts, i;
|
uint no_parts, i;
|
||||||
char *default_name;
|
char *default_name;
|
||||||
@ -482,12 +583,14 @@ static bool set_up_default_partitions(partition_info *part_info,
|
|||||||
if (part_info->no_parts == 0)
|
if (part_info->no_parts == 0)
|
||||||
part_info->no_parts= file->get_default_no_partitions(max_rows);
|
part_info->no_parts= file->get_default_no_partitions(max_rows);
|
||||||
no_parts= part_info->no_parts;
|
no_parts= part_info->no_parts;
|
||||||
|
part_info->use_default_partitions= FALSE;
|
||||||
if (unlikely(no_parts > MAX_PARTITIONS))
|
if (unlikely(no_parts > MAX_PARTITIONS))
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (unlikely((!(default_name= create_default_partition_names(no_parts,
|
if (unlikely((!(default_name= create_default_partition_names(no_parts,
|
||||||
|
start_no,
|
||||||
FALSE)))))
|
FALSE)))))
|
||||||
goto end;
|
goto end;
|
||||||
i= 0;
|
i= 0;
|
||||||
@ -537,8 +640,8 @@ end:
|
|||||||
static bool set_up_default_subpartitions(partition_info *part_info,
|
static bool set_up_default_subpartitions(partition_info *part_info,
|
||||||
handler *file, ulonglong max_rows)
|
handler *file, ulonglong max_rows)
|
||||||
{
|
{
|
||||||
uint i, j= 0, no_parts, no_subparts;
|
uint i, j, no_parts, no_subparts;
|
||||||
char *default_name;
|
char *default_name, *name_ptr;
|
||||||
bool result= TRUE;
|
bool result= TRUE;
|
||||||
partition_element *part_elem;
|
partition_element *part_elem;
|
||||||
List_iterator<partition_element> part_it(part_info->partitions);
|
List_iterator<partition_element> part_it(part_info->partitions);
|
||||||
@ -548,26 +651,29 @@ static bool set_up_default_subpartitions(partition_info *part_info,
|
|||||||
part_info->no_subparts= file->get_default_no_partitions(max_rows);
|
part_info->no_subparts= file->get_default_no_partitions(max_rows);
|
||||||
no_parts= part_info->no_parts;
|
no_parts= part_info->no_parts;
|
||||||
no_subparts= part_info->no_subparts;
|
no_subparts= part_info->no_subparts;
|
||||||
|
part_info->use_default_subpartitions= FALSE;
|
||||||
if (unlikely((no_parts * no_subparts) > MAX_PARTITIONS))
|
if (unlikely((no_parts * no_subparts) > MAX_PARTITIONS))
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (unlikely((!(default_name=
|
if (unlikely((!(default_name=
|
||||||
create_default_partition_names(no_subparts, TRUE)))))
|
create_default_partition_names(no_subparts, (uint)0, TRUE)))))
|
||||||
goto end;
|
goto end;
|
||||||
i= 0;
|
i= 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
part_elem= part_it++;
|
part_elem= part_it++;
|
||||||
|
j= 0;
|
||||||
|
name_ptr= default_name;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
partition_element *subpart_elem= new partition_element();
|
partition_element *subpart_elem= new partition_element();
|
||||||
if (likely(subpart_elem != 0))
|
if (likely(subpart_elem != 0))
|
||||||
{
|
{
|
||||||
subpart_elem->engine_type= DB_TYPE_UNKNOWN;
|
subpart_elem->engine_type= DB_TYPE_UNKNOWN;
|
||||||
subpart_elem->partition_name= default_name;
|
subpart_elem->partition_name= name_ptr;
|
||||||
default_name+= MAX_PART_NAME_SIZE;
|
name_ptr+= MAX_PART_NAME_SIZE;
|
||||||
part_elem->subpartitions.push_back(subpart_elem);
|
part_elem->subpartitions.push_back(subpart_elem);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -598,14 +704,15 @@ end:
|
|||||||
Support routine for check_partition_info
|
Support routine for check_partition_info
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool set_up_defaults_for_partitioning(partition_info *part_info,
|
bool set_up_defaults_for_partitioning(partition_info *part_info,
|
||||||
handler *file,
|
handler *file,
|
||||||
ulonglong max_rows)
|
ulonglong max_rows, uint start_no)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("set_up_defaults_for_partitioning");
|
DBUG_ENTER("set_up_defaults_for_partitioning");
|
||||||
|
|
||||||
if (part_info->use_default_partitions)
|
if (part_info->use_default_partitions)
|
||||||
DBUG_RETURN(set_up_default_partitions(part_info, file, max_rows));
|
DBUG_RETURN(set_up_default_partitions(part_info, file, max_rows,
|
||||||
|
start_no));
|
||||||
if (is_sub_partitioned(part_info) && part_info->use_default_subpartitions)
|
if (is_sub_partitioned(part_info) && part_info->use_default_subpartitions)
|
||||||
DBUG_RETURN(set_up_default_subpartitions(part_info, file, max_rows));
|
DBUG_RETURN(set_up_default_subpartitions(part_info, file, max_rows));
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
@ -682,7 +789,8 @@ bool check_partition_info(partition_info *part_info,enum db_type eng_type,
|
|||||||
my_error(ER_SUBPARTITION_ERROR, MYF(0));
|
my_error(ER_SUBPARTITION_ERROR, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (unlikely(set_up_defaults_for_partitioning(part_info, file, max_rows)))
|
if (unlikely(set_up_defaults_for_partitioning(part_info, file,
|
||||||
|
max_rows, (uint)0)))
|
||||||
goto end;
|
goto end;
|
||||||
tot_partitions= get_tot_partitions(part_info);
|
tot_partitions= get_tot_partitions(part_info);
|
||||||
if (unlikely(tot_partitions > MAX_PARTITIONS))
|
if (unlikely(tot_partitions > MAX_PARTITIONS))
|
||||||
@ -690,6 +798,11 @@ bool check_partition_info(partition_info *part_info,enum db_type eng_type,
|
|||||||
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
if (unlikely(is_partitions_in_table(part_info, part_info)))
|
||||||
|
{
|
||||||
|
my_error(ER_SAME_NAME_PARTITION, MYF(0));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
engine_array= (u_char*)my_malloc(tot_partitions, MYF(MY_WME));
|
engine_array= (u_char*)my_malloc(tot_partitions, MYF(MY_WME));
|
||||||
if (unlikely(!engine_array))
|
if (unlikely(!engine_array))
|
||||||
goto end;
|
goto end;
|
||||||
@ -1524,11 +1637,9 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table)
|
|||||||
db_name= &db_name_string[home_dir_length];
|
db_name= &db_name_string[home_dir_length];
|
||||||
tables.db= db_name;
|
tables.db= db_name;
|
||||||
|
|
||||||
part_info->no_full_parts= part_info->no_parts;
|
|
||||||
if (is_sub_partitioned(part_info))
|
if (is_sub_partitioned(part_info))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(part_info->subpart_type == HASH_PARTITION);
|
DBUG_ASSERT(part_info->subpart_type == HASH_PARTITION);
|
||||||
part_info->no_full_parts= part_info->no_parts*part_info->no_subparts;
|
|
||||||
/*
|
/*
|
||||||
Subpartition is defined. We need to verify that subpartitioning
|
Subpartition is defined. We need to verify that subpartitioning
|
||||||
function is correct.
|
function is correct.
|
||||||
@ -2768,7 +2879,7 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
|
|||||||
const key_range *key_spec, part_id_range *part_spec)
|
const key_range *key_spec, part_id_range *part_spec)
|
||||||
{
|
{
|
||||||
partition_info *part_info= table->s->part_info;
|
partition_info *part_info= table->s->part_info;
|
||||||
uint no_parts= part_info->no_full_parts, i, part_id;
|
uint no_parts= get_tot_partitions(part_info), i, part_id;
|
||||||
uint sub_part= no_parts, part_part= no_parts;
|
uint sub_part= no_parts, part_part= no_parts;
|
||||||
KEY *key_info= NULL;
|
KEY *key_info= NULL;
|
||||||
bool found_part_field= FALSE;
|
bool found_part_field= FALSE;
|
||||||
|
671
sql/sql_table.cc
671
sql/sql_table.cc
@ -45,6 +45,64 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field);
|
|||||||
static bool check_engine(THD *thd, const char *table_name,
|
static bool check_engine(THD *thd, const char *table_name,
|
||||||
enum db_type *new_engine);
|
enum db_type *new_engine);
|
||||||
|
|
||||||
|
/*
|
||||||
|
SYNOPSIS
|
||||||
|
write_bin_log()
|
||||||
|
thd Thread object
|
||||||
|
clear_error is clear_error to be called
|
||||||
|
RETURN VALUES
|
||||||
|
NONE
|
||||||
|
DESCRIPTION
|
||||||
|
Write the binlog if open, routine used in multiple places in this
|
||||||
|
file
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void write_bin_log(THD *thd, bool clear_error)
|
||||||
|
{
|
||||||
|
if (mysql_bin_log.is_open())
|
||||||
|
{
|
||||||
|
if (clear_error)
|
||||||
|
thd->clear_error();
|
||||||
|
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||||
|
mysql_bin_log.write(&qinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SYNOPSIS
|
||||||
|
abort_and_upgrade_lock()
|
||||||
|
thd Thread object
|
||||||
|
table Table object
|
||||||
|
db Database name
|
||||||
|
table_name Table name
|
||||||
|
old_lock_level Old lock level
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
DESCRIPTION
|
||||||
|
Remember old lock level (for possible downgrade later on), abort all
|
||||||
|
waiting threads and ensure that all keeping locks currently are
|
||||||
|
completed such that we own the lock exclusively and no other interaction
|
||||||
|
is ongoing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool abort_and_upgrade_lock(THD *thd, TABLE *table, const char *db,
|
||||||
|
const char *table_name,
|
||||||
|
uint *old_lock_level)
|
||||||
|
{
|
||||||
|
uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
|
||||||
|
DBUG_ENTER("abort_and_upgrade_locks");
|
||||||
|
|
||||||
|
*old_lock_level= table->reginfo.lock_type;
|
||||||
|
mysql_lock_abort(thd, table);
|
||||||
|
VOID(remove_table_from_cache(thd, db, table_name, flags));
|
||||||
|
if (thd->killed)
|
||||||
|
{
|
||||||
|
thd->no_warnings_for_error= 0;
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Build the path to a file for a table (or the base path that can
|
Build the path to a file for a table (or the base path that can
|
||||||
@ -317,13 +375,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
if (some_tables_deleted || tmp_table_deleted || !error)
|
if (some_tables_deleted || tmp_table_deleted || !error)
|
||||||
{
|
{
|
||||||
query_cache_invalidate3(thd, tables, 0);
|
query_cache_invalidate3(thd, tables, 0);
|
||||||
if (!dont_log_query && mysql_bin_log.is_open())
|
if (!dont_log_query)
|
||||||
{
|
write_bin_log(thd, !error);
|
||||||
if (!error)
|
|
||||||
thd->clear_error();
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_table_names(thd, tables, (TABLE_LIST*) 0);
|
unlock_table_names(thd, tables, (TABLE_LIST*) 0);
|
||||||
@ -1709,12 +1762,8 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||||||
}
|
}
|
||||||
thd->tmp_table_used= 1;
|
thd->tmp_table_used= 1;
|
||||||
}
|
}
|
||||||
if (!internal_tmp_table && mysql_bin_log.is_open())
|
if (!internal_tmp_table)
|
||||||
{
|
write_bin_log(thd, TRUE);
|
||||||
thd->clear_error();
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -2784,12 +2833,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Must be written before unlock
|
// Must be written before unlock
|
||||||
if (mysql_bin_log.is_open())
|
write_bin_log(thd, TRUE);
|
||||||
{
|
|
||||||
thd->clear_error();
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
res= FALSE;
|
res= FALSE;
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -2895,11 +2939,7 @@ mysql_discard_or_import_tablespace(THD *thd,
|
|||||||
error=1;
|
error=1;
|
||||||
if (error)
|
if (error)
|
||||||
goto err;
|
goto err;
|
||||||
if (mysql_bin_log.is_open())
|
write_bin_log(thd, FALSE);
|
||||||
{
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
err:
|
err:
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
thd->tablespace_op=FALSE;
|
thd->tablespace_op=FALSE;
|
||||||
@ -3301,7 +3341,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
enum db_type old_db_type,new_db_type;
|
enum db_type old_db_type,new_db_type;
|
||||||
uint need_copy_table= 0;
|
uint need_copy_table= 0;
|
||||||
#ifdef HAVE_PARTITION_DB
|
#ifdef HAVE_PARTITION_DB
|
||||||
|
bool online_add_empty_partition= FALSE;
|
||||||
|
bool online_drop_partition= FALSE;
|
||||||
bool partition_changed= FALSE;
|
bool partition_changed= FALSE;
|
||||||
|
enum db_type default_engine_type;
|
||||||
#endif
|
#endif
|
||||||
DBUG_ENTER("mysql_alter_table");
|
DBUG_ENTER("mysql_alter_table");
|
||||||
|
|
||||||
@ -3378,66 +3421,421 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
old_db_type= table->s->db_type;
|
old_db_type= table->s->db_type;
|
||||||
if (create_info->db_type == DB_TYPE_DEFAULT)
|
if (create_info->db_type == DB_TYPE_DEFAULT)
|
||||||
create_info->db_type= old_db_type;
|
create_info->db_type= old_db_type;
|
||||||
|
|
||||||
#ifdef HAVE_PARTITION_DB
|
#ifdef HAVE_PARTITION_DB
|
||||||
/*
|
/*
|
||||||
When thd->lex->part_info has a reference to a partition_info the
|
We need to handle both partition management command such as Add Partition
|
||||||
ALTER TABLE contained a definition of a partitioning.
|
and others here as well as an ALTER TABLE that completely changes the
|
||||||
|
partitioning and yet others that don't change anything at all. We start
|
||||||
Case I:
|
by checking the partition management variants and then check the general
|
||||||
If there was a partition before and there is a new one defined.
|
change patterns.
|
||||||
We use the new partitioning. The new partitioning is already
|
*/
|
||||||
defined in the correct variable so no work is needed to
|
if (alter_info->flags & (ALTER_ADD_PARTITION +
|
||||||
accomplish this.
|
ALTER_DROP_PARTITION + ALTER_COALESCE_PARTITION +
|
||||||
We do however need to update partition_changed to ensure that not
|
ALTER_REORGANISE_PARTITION))
|
||||||
only the frm file is changed in the ALTER TABLE command.
|
|
||||||
|
|
||||||
Case IIa:
|
|
||||||
There was a partitioning before and there is no new one defined.
|
|
||||||
Also the user has not specified an explicit engine to use.
|
|
||||||
|
|
||||||
We use the old partitioning also for the new table. We do this
|
|
||||||
by assigning the partition_info from the table loaded in
|
|
||||||
open_ltable to the partition_info struct used by mysql_create_table
|
|
||||||
later in this method.
|
|
||||||
|
|
||||||
Case IIb:
|
|
||||||
There was a partitioning before and there is no new one defined.
|
|
||||||
The user has specified an explicit engine to use.
|
|
||||||
|
|
||||||
Since the user has specified an explicit engine to use we override
|
|
||||||
the old partitioning info and create a new table using the specified
|
|
||||||
engine. This is the reason for the extra check if old and new engine
|
|
||||||
is equal.
|
|
||||||
In this case the partition also is changed.
|
|
||||||
|
|
||||||
Case III:
|
|
||||||
There was no partitioning before altering the table, there is
|
|
||||||
partitioning defined in the altered table. Use the new partitioning.
|
|
||||||
No work needed since the partitioning info is already in the
|
|
||||||
correct variable.
|
|
||||||
Also here partition has changed and thus a new table must be
|
|
||||||
created.
|
|
||||||
|
|
||||||
Case IV:
|
|
||||||
There was no partitioning before and no partitioning defined. Obviously
|
|
||||||
no work needed.
|
|
||||||
*/
|
|
||||||
if (table->s->part_info)
|
|
||||||
{
|
{
|
||||||
if (!thd->lex->part_info &&
|
partition_info *tab_part_info= table->s->part_info;
|
||||||
create_info->db_type == old_db_type)
|
if (!tab_part_info)
|
||||||
thd->lex->part_info= table->s->part_info;
|
{
|
||||||
|
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> t_it(tab_part_info->partitions);
|
||||||
|
partition_element *t_part_elem= t_it++;
|
||||||
|
if (is_sub_partitioned(tab_part_info))
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> s_it(t_part_elem->subpartitions);
|
||||||
|
t_part_elem= s_it++;
|
||||||
|
}
|
||||||
|
default_engine_type= t_part_elem->engine_type;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
We are going to manipulate the partition info on the table object
|
||||||
|
so we need to ensure that the data structure of the table object
|
||||||
|
is freed by setting version to 0.
|
||||||
|
*/
|
||||||
|
table->s->version= 0L;
|
||||||
|
if (alter_info->flags == ALTER_ADD_PARTITION)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We start by moving the new partitions to the list of temporary
|
||||||
|
partitions. We will then check that the new partitions fit in the
|
||||||
|
partitioning scheme as currently set-up.
|
||||||
|
Partitions are always added at the end in ADD PARTITION.
|
||||||
|
*/
|
||||||
|
partition_info *alt_part_info= thd->lex->part_info;
|
||||||
|
uint no_new_partitions= alt_part_info->no_parts;
|
||||||
|
uint no_orig_partitions= tab_part_info->no_parts;
|
||||||
|
uint check_total_partitions= no_new_partitions + no_orig_partitions;
|
||||||
|
uint new_total_partitions= check_total_partitions;
|
||||||
|
/*
|
||||||
|
We allow quite a lot of values to be supplied by defaults, however we
|
||||||
|
must know the number of new partitions in this case.
|
||||||
|
*/
|
||||||
|
if (no_new_partitions == 0)
|
||||||
|
{
|
||||||
|
my_error(ER_ADD_PARTITION_NO_NEW_PARTITION, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (is_sub_partitioned(tab_part_info))
|
||||||
|
{
|
||||||
|
if (alt_part_info->no_subparts == 0)
|
||||||
|
alt_part_info->no_subparts= tab_part_info->no_subparts;
|
||||||
|
else if (alt_part_info->no_subparts != tab_part_info->no_subparts)
|
||||||
|
{
|
||||||
|
my_error(ER_ADD_PARTITION_SUBPART_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
check_total_partitions= new_total_partitions*
|
||||||
|
alt_part_info->no_subparts;
|
||||||
|
}
|
||||||
|
if (check_total_partitions > MAX_PARTITIONS)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
alt_part_info->part_type= tab_part_info->part_type;
|
||||||
|
if (set_up_defaults_for_partitioning(alt_part_info,
|
||||||
|
table->file,
|
||||||
|
(ulonglong)0ULL,
|
||||||
|
tab_part_info->no_parts))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Need to concatenate the lists here to make it possible to check the
|
||||||
|
partition info for correctness using check_partition_info
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> alt_it(alt_part_info->partitions);
|
||||||
|
uint part_count= 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *part_elem= alt_it++;
|
||||||
|
tab_part_info->partitions.push_back(part_elem);
|
||||||
|
tab_part_info->temp_partitions.push_back(part_elem);
|
||||||
|
} while (++part_count < no_new_partitions);
|
||||||
|
tab_part_info->no_parts+= no_new_partitions;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> tab_it(tab_part_info->partitions);
|
||||||
|
partition_element *part_elem= tab_it++;
|
||||||
|
if (is_sub_partitioned(tab_part_info))
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> sub_it(part_elem->subpartitions);
|
||||||
|
part_elem= sub_it++;
|
||||||
|
}
|
||||||
|
if (check_partition_info(tab_part_info, part_elem->engine_type,
|
||||||
|
table->file, (ulonglong)0ULL))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
create_info->db_type= DB_TYPE_PARTITION_DB;
|
||||||
|
thd->lex->part_info= tab_part_info;
|
||||||
|
if (table->file->alter_table_flags() & HA_ONLINE_ADD_EMPTY_PARTITION &&
|
||||||
|
(tab_part_info->part_type == RANGE_PARTITION ||
|
||||||
|
tab_part_info->part_type == LIST_PARTITION))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
For range and list partitions add partition is simply adding a new
|
||||||
|
empty partition to the table. If the handler support this we will
|
||||||
|
use the simple method of doing this. In this case we need to break
|
||||||
|
out the new partitions from the list again and only keep them in the
|
||||||
|
temporary list. Added partitions are always added at the end.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> tab_it(tab_part_info->partitions);
|
||||||
|
uint part_count= 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tab_it++;
|
||||||
|
} while (++part_count < no_orig_partitions);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tab_it++;
|
||||||
|
tab_it.remove();
|
||||||
|
} while (++part_count < new_total_partitions);
|
||||||
|
}
|
||||||
|
tab_part_info->no_parts-= no_new_partitions;
|
||||||
|
online_add_empty_partition= TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tab_part_info->temp_partitions.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (alter_info->flags == ALTER_DROP_PARTITION)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Drop a partition from a range partition and list partitioning is
|
||||||
|
always safe and can be made more or less immediate. It is necessary
|
||||||
|
however to ensure that the partition to be removed is safely removed
|
||||||
|
and that REPAIR TABLE can remove the partition if for some reason the
|
||||||
|
command to drop the partition failed in the middle.
|
||||||
|
*/
|
||||||
|
uint part_count= 0;
|
||||||
|
uint no_parts_dropped= alter_info->partition_names.elements;
|
||||||
|
uint no_parts_found= 0;
|
||||||
|
List_iterator<partition_element> part_it(tab_part_info->partitions);
|
||||||
|
if (!(tab_part_info->part_type == RANGE_PARTITION ||
|
||||||
|
tab_part_info->part_type == LIST_PARTITION))
|
||||||
|
{
|
||||||
|
my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP");
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (no_parts_dropped >= tab_part_info->no_parts)
|
||||||
|
{
|
||||||
|
my_error(ER_DROP_LAST_PARTITION, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *part_elem= part_it++;
|
||||||
|
if (is_partition_in_list(part_elem->partition_name,
|
||||||
|
alter_info->partition_names))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Remove the partition from the list and put it instead in the
|
||||||
|
list of temporary partitions with a new state.
|
||||||
|
*/
|
||||||
|
no_parts_found++;
|
||||||
|
part_elem->part_state= PART_IS_DROPPED;
|
||||||
|
}
|
||||||
|
} while (++part_count < tab_part_info->no_parts);
|
||||||
|
if (no_parts_found != no_parts_dropped)
|
||||||
|
{
|
||||||
|
my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (!(table->file->alter_table_flags() & HA_ONLINE_DROP_PARTITION))
|
||||||
|
{
|
||||||
|
my_error(ER_DROP_PARTITION_FAILURE, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (table->file->is_fk_defined_on_table_or_index(MAX_KEY))
|
||||||
|
{
|
||||||
|
my_error(ER_DROP_PARTITION_WHEN_FK_DEFINED, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
This code needs set-up of structures needed by mysql_create_table
|
||||||
|
before it is called and thus we only set a boolean variable to be
|
||||||
|
checked later down in the code when all needed data structures are
|
||||||
|
prepared.
|
||||||
|
*/
|
||||||
|
online_drop_partition= TRUE;
|
||||||
|
}
|
||||||
|
else if (alter_info->flags == ALTER_COALESCE_PARTITION)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
In this version COALESCE PARTITION is implemented by simply removing
|
||||||
|
a partition from the table and using the normal ALTER TABLE code
|
||||||
|
and ensuring that copy to a new table occurs. Later on we can optimise
|
||||||
|
this function for Linear Hash partitions. In that case we can avoid
|
||||||
|
reorganising the entire table. For normal hash partitions it will
|
||||||
|
be a complete reorganise anyways so that can only be made on-line
|
||||||
|
if it still uses a copy table.
|
||||||
|
*/
|
||||||
|
uint part_count= 0;
|
||||||
|
uint no_parts_coalesced= alter_info->no_parts;
|
||||||
|
uint no_parts_remain= tab_part_info->no_parts - no_parts_coalesced;
|
||||||
|
List_iterator<partition_element> part_it(tab_part_info->partitions);
|
||||||
|
if (tab_part_info->part_type != HASH_PARTITION)
|
||||||
|
{
|
||||||
|
my_error(ER_COALESCE_ONLY_ON_HASH_PARTITION, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (no_parts_coalesced == 0)
|
||||||
|
{
|
||||||
|
my_error(ER_COALESCE_PARTITION_NO_PARTITION, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (no_parts_coalesced >= tab_part_info->no_parts)
|
||||||
|
{
|
||||||
|
my_error(ER_DROP_LAST_PARTITION, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
part_it++;
|
||||||
|
if (++part_count > no_parts_remain)
|
||||||
|
part_it.remove();
|
||||||
|
} while (part_count < tab_part_info->no_parts);
|
||||||
|
tab_part_info->no_parts= no_parts_remain;
|
||||||
|
}
|
||||||
|
else if (alter_info->flags == ALTER_REORGANISE_PARTITION)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Reorganise partitions takes a number of partitions that are next
|
||||||
|
to each other (at least for RANGE PARTITIONS) and then uses those
|
||||||
|
to create a set of new partitions. So data is copied from those
|
||||||
|
partitions into the new set of partitions. Those new partitions
|
||||||
|
can have more values in the LIST value specifications or less both
|
||||||
|
are allowed. The ranges can be different but since they are
|
||||||
|
changing a set of consecutive partitions they must cover the same
|
||||||
|
range as those changed from.
|
||||||
|
This command can be used on RANGE and LIST partitions.
|
||||||
|
*/
|
||||||
|
uint no_parts_reorged= alter_info->partition_names.elements;
|
||||||
|
uint no_parts_new= thd->lex->part_info->partitions.elements;
|
||||||
|
partition_info *alt_part_info= thd->lex->part_info;
|
||||||
|
uint check_total_partitions;
|
||||||
|
if (no_parts_reorged > tab_part_info->no_parts)
|
||||||
|
{
|
||||||
|
my_error(ER_REORG_PARTITION_NOT_EXIST, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (!(tab_part_info->part_type == RANGE_PARTITION ||
|
||||||
|
tab_part_info->part_type == LIST_PARTITION))
|
||||||
|
{
|
||||||
|
my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "REORGANISE");
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (is_partitions_in_table(alt_part_info, tab_part_info))
|
||||||
|
{
|
||||||
|
my_error(ER_SAME_NAME_PARTITION, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
check_total_partitions= tab_part_info->no_parts + no_parts_new;
|
||||||
|
check_total_partitions-= no_parts_reorged;
|
||||||
|
if (check_total_partitions > MAX_PARTITIONS)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> tab_it(tab_part_info->partitions);
|
||||||
|
uint part_count= 0;
|
||||||
|
bool found_first= FALSE, found_last= FALSE;
|
||||||
|
uint drop_count= 0;
|
||||||
|
longlong tab_max_range, alt_max_range;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *part_elem= tab_it++;
|
||||||
|
if (is_partition_in_list(part_elem->partition_name,
|
||||||
|
alter_info->partition_names))
|
||||||
|
{
|
||||||
|
drop_count++;
|
||||||
|
tab_max_range= part_elem->range_value;
|
||||||
|
if (!found_first)
|
||||||
|
{
|
||||||
|
uint alt_part_count= 0;
|
||||||
|
found_first= TRUE;
|
||||||
|
List_iterator<partition_element> alt_it(alt_part_info->partitions);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *alt_part_elem= alt_it++;
|
||||||
|
alt_max_range= alt_part_elem->range_value;
|
||||||
|
if (alt_part_count == 0)
|
||||||
|
tab_it.replace(alt_part_elem);
|
||||||
|
else
|
||||||
|
tab_it.after(alt_part_elem);
|
||||||
|
} while (++alt_part_count < no_parts_new);
|
||||||
|
}
|
||||||
|
else if (found_last)
|
||||||
|
{
|
||||||
|
my_error(ER_CONSECUTIVE_REORG_PARTITIONS, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tab_it.remove();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (found_first)
|
||||||
|
found_last= TRUE;
|
||||||
|
}
|
||||||
|
} while (++part_count < tab_part_info->no_parts);
|
||||||
|
if (drop_count != no_parts_reorged)
|
||||||
|
{
|
||||||
|
my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (tab_part_info->part_type == RANGE_PARTITION &&
|
||||||
|
alt_max_range > tab_max_range)
|
||||||
|
{
|
||||||
|
my_error(ER_REORG_OUTSIDE_RANGE, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
partition_changed= TRUE;
|
||||||
|
create_info->db_type= DB_TYPE_PARTITION_DB;
|
||||||
|
thd->lex->part_info= tab_part_info;
|
||||||
|
if (alter_info->flags == ALTER_ADD_PARTITION ||
|
||||||
|
alter_info->flags == ALTER_REORGANISE_PARTITION)
|
||||||
|
{
|
||||||
|
if (check_partition_info(tab_part_info, default_engine_type,
|
||||||
|
table->file, (ulonglong)0ULL))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (thd->lex->part_info)
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Need to cater for engine types that can handle partition without
|
When thd->lex->part_info has a reference to a partition_info the
|
||||||
using the partition handler.
|
ALTER TABLE contained a definition of a partitioning.
|
||||||
|
|
||||||
|
Case I:
|
||||||
|
If there was a partition before and there is a new one defined.
|
||||||
|
We use the new partitioning. The new partitioning is already
|
||||||
|
defined in the correct variable so no work is needed to
|
||||||
|
accomplish this.
|
||||||
|
We do however need to update partition_changed to ensure that not
|
||||||
|
only the frm file is changed in the ALTER TABLE command.
|
||||||
|
|
||||||
|
Case IIa:
|
||||||
|
There was a partitioning before and there is no new one defined.
|
||||||
|
Also the user has not specified an explicit engine to use.
|
||||||
|
|
||||||
|
We use the old partitioning also for the new table. We do this
|
||||||
|
by assigning the partition_info from the table loaded in
|
||||||
|
open_ltable to the partition_info struct used by mysql_create_table
|
||||||
|
later in this method.
|
||||||
|
|
||||||
|
Case IIb:
|
||||||
|
There was a partitioning before and there is no new one defined.
|
||||||
|
The user has specified an explicit engine to use.
|
||||||
|
|
||||||
|
Since the user has specified an explicit engine to use we override
|
||||||
|
the old partitioning info and create a new table using the specified
|
||||||
|
engine. This is the reason for the extra check if old and new engine
|
||||||
|
is equal.
|
||||||
|
In this case the partition also is changed.
|
||||||
|
|
||||||
|
Case III:
|
||||||
|
There was no partitioning before altering the table, there is
|
||||||
|
partitioning defined in the altered table. Use the new partitioning.
|
||||||
|
No work needed since the partitioning info is already in the
|
||||||
|
correct variable.
|
||||||
|
Also here partition has changed and thus a new table must be
|
||||||
|
created.
|
||||||
|
|
||||||
|
Case IV:
|
||||||
|
There was no partitioning before and no partitioning defined.
|
||||||
|
Obviously no work needed.
|
||||||
*/
|
*/
|
||||||
if (thd->lex->part_info != table->s->part_info)
|
if (table->s->part_info)
|
||||||
partition_changed= TRUE;
|
{
|
||||||
thd->lex->part_info->default_engine_type= create_info->db_type;
|
if (!thd->lex->part_info &&
|
||||||
create_info->db_type= DB_TYPE_PARTITION_DB;
|
create_info->db_type == old_db_type)
|
||||||
|
thd->lex->part_info= table->s->part_info;
|
||||||
|
}
|
||||||
|
if (thd->lex->part_info)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Need to cater for engine types that can handle partition without
|
||||||
|
using the partition handler.
|
||||||
|
*/
|
||||||
|
if (thd->lex->part_info != table->s->part_info)
|
||||||
|
partition_changed= TRUE;
|
||||||
|
thd->lex->part_info->default_engine_type= create_info->db_type;
|
||||||
|
create_info->db_type= DB_TYPE_PARTITION_DB;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (check_engine(thd, new_name, &create_info->db_type))
|
if (check_engine(thd, new_name, &create_info->db_type))
|
||||||
@ -3503,12 +3901,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
}
|
}
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
if (mysql_bin_log.is_open())
|
write_bin_log(thd, TRUE);
|
||||||
{
|
|
||||||
thd->clear_error();
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
if (do_send_ok)
|
if (do_send_ok)
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
}
|
}
|
||||||
@ -3824,6 +4217,100 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
if (!need_copy_table)
|
if (!need_copy_table)
|
||||||
create_info->frm_only= 1;
|
create_info->frm_only= 1;
|
||||||
|
|
||||||
|
if (partition_changed)
|
||||||
|
{
|
||||||
|
if (online_drop_partition)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Now after all checks and setting state on dropped partitions we can
|
||||||
|
start the actual dropping of the partitions.
|
||||||
|
1) Lock table in TL_WRITE_ONLY to ensure all other accesses on table
|
||||||
|
are completed and no new ones are started until we have changed
|
||||||
|
the frm file.
|
||||||
|
2) Write the new frm file where state of dropped partitions is
|
||||||
|
changed to PART_IS_DROPPED
|
||||||
|
3) Perform the actual drop of the partition using the handler of the
|
||||||
|
table.
|
||||||
|
4) Write a new frm file of the table where the partitions are dropped
|
||||||
|
from the table.
|
||||||
|
|
||||||
|
*/
|
||||||
|
uint old_lock_type;
|
||||||
|
partition_info *part_info= table->s->part_info;
|
||||||
|
char path[FN_REFLEN+1];
|
||||||
|
uint db_options= 0, key_count, syntax_len;
|
||||||
|
KEY *key_info_buffer;
|
||||||
|
char *part_syntax_buf;
|
||||||
|
|
||||||
|
VOID(pthread_mutex_lock(&LOCK_open));
|
||||||
|
if (abort_and_upgrade_lock(thd, table, db, table_name, &old_lock_type))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
|
mysql_prepare_table(thd, create_info, &create_list,
|
||||||
|
&key_list, /*tmp_table*/ 0, &db_options,
|
||||||
|
table->file, &key_info_buffer, &key_count,
|
||||||
|
/*select_field_count*/ 0);
|
||||||
|
if (!(part_syntax_buf= generate_partition_syntax(part_info,
|
||||||
|
&syntax_len,
|
||||||
|
TRUE)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
part_info->part_info_string= part_syntax_buf;
|
||||||
|
part_info->part_info_len= syntax_len;
|
||||||
|
build_table_path(path, sizeof(path), db, table_name, reg_ext);
|
||||||
|
if (mysql_create_frm(thd, path, db, table_name, create_info,
|
||||||
|
create_list, key_count, key_info_buffer,
|
||||||
|
table->file))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
thd->lex->part_info= part_info;
|
||||||
|
build_table_path(path, sizeof(path), db, table_name, "");
|
||||||
|
if (table->file->drop_partitions(path))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> part_it(part_info->partitions);
|
||||||
|
uint i= 0, remove_count= 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
partition_element *part_elem= part_it++;
|
||||||
|
if (is_partition_in_list(part_elem->partition_name,
|
||||||
|
alter_info->partition_names))
|
||||||
|
{
|
||||||
|
part_it.remove();
|
||||||
|
remove_count++;
|
||||||
|
}
|
||||||
|
} while (++i < part_info->no_parts);
|
||||||
|
part_info->no_parts-= remove_count;
|
||||||
|
}
|
||||||
|
if (!(part_syntax_buf= generate_partition_syntax(part_info,
|
||||||
|
&syntax_len,
|
||||||
|
TRUE)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
part_info->part_info_string= part_syntax_buf;
|
||||||
|
part_info->part_info_len= syntax_len;
|
||||||
|
build_table_path(path, sizeof(path), db, table_name, reg_ext);
|
||||||
|
if (mysql_create_frm(thd, path, db, table_name, create_info,
|
||||||
|
create_list, key_count, key_info_buffer,
|
||||||
|
table->file) ||
|
||||||
|
table->file->create_handler_files(path))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
thd->proc_info="end";
|
||||||
|
write_bin_log(thd, FALSE);
|
||||||
|
send_ok(thd);
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handling of symlinked tables:
|
Handling of symlinked tables:
|
||||||
If no rename:
|
If no rename:
|
||||||
@ -3949,12 +4436,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
my_free((gptr) new_table,MYF(0));
|
my_free((gptr) new_table,MYF(0));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (mysql_bin_log.is_open())
|
write_bin_log(thd, TRUE);
|
||||||
{
|
|
||||||
thd->clear_error();
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
goto end_temporary;
|
goto end_temporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4085,15 +4567,14 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
thd->proc_info="end";
|
thd->proc_info="end";
|
||||||
if (mysql_bin_log.is_open())
|
write_bin_log(thd, TRUE);
|
||||||
{
|
|
||||||
thd->clear_error();
|
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
|
||||||
mysql_bin_log.write(&qinfo);
|
|
||||||
}
|
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
#ifdef HAVE_BERKELEY_DB
|
#ifdef HAVE_BERKELEY_DB
|
||||||
|
/*
|
||||||
|
TODO RONM: This problem needs to handled for Berkeley DB partitions
|
||||||
|
as well
|
||||||
|
*/
|
||||||
if (old_db_type == DB_TYPE_BERKELEY_DB)
|
if (old_db_type == DB_TYPE_BERKELEY_DB)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
238
sql/sql_yacc.yy
238
sql/sql_yacc.yy
@ -512,6 +512,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token RELEASE_SYM
|
%token RELEASE_SYM
|
||||||
%token RELOAD
|
%token RELOAD
|
||||||
%token RENAME
|
%token RENAME
|
||||||
|
%token REORGANISE_SYM
|
||||||
%token REPAIR
|
%token REPAIR
|
||||||
%token REPEATABLE_SYM
|
%token REPEATABLE_SYM
|
||||||
%token REPEAT_SYM
|
%token REPEAT_SYM
|
||||||
@ -2618,7 +2619,15 @@ opt_partitioning:
|
|||||||
|
|
||||||
partitioning:
|
partitioning:
|
||||||
PARTITION_SYM
|
PARTITION_SYM
|
||||||
{ Lex->part_info= new partition_info(); }
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->part_info= new partition_info();
|
||||||
|
if (!lex->part_info)
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
partition
|
partition
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -2633,6 +2642,11 @@ partition_entry:
|
|||||||
partition info string into part_info data structure.
|
partition info string into part_info data structure.
|
||||||
*/
|
*/
|
||||||
lex->part_info= new partition_info();
|
lex->part_info= new partition_info();
|
||||||
|
if (!lex->part_info)
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2640,10 +2654,12 @@ partition_entry:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
partition {};
|
partition {}
|
||||||
|
;
|
||||||
|
|
||||||
partition:
|
partition:
|
||||||
BY part_type_def opt_no_parts {} opt_sub_part {} part_defs;
|
BY part_type_def opt_no_parts {} opt_sub_part {} part_defs
|
||||||
|
;
|
||||||
|
|
||||||
part_type_def:
|
part_type_def:
|
||||||
opt_linear KEY_SYM '(' part_field_list ')'
|
opt_linear KEY_SYM '(' part_field_list ')'
|
||||||
@ -2660,22 +2676,26 @@ part_type_def:
|
|||||||
part_func {}
|
part_func {}
|
||||||
| LIST_SYM
|
| LIST_SYM
|
||||||
{ Lex->part_info->part_type= LIST_PARTITION; }
|
{ Lex->part_info->part_type= LIST_PARTITION; }
|
||||||
part_func {};
|
part_func {}
|
||||||
|
;
|
||||||
|
|
||||||
opt_linear:
|
opt_linear:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
| LINEAR_SYM
|
| LINEAR_SYM
|
||||||
{ Lex->part_info->linear_hash_ind= TRUE;};
|
{ Lex->part_info->linear_hash_ind= TRUE;}
|
||||||
|
;
|
||||||
|
|
||||||
part_field_list:
|
part_field_list:
|
||||||
part_field_item {}
|
part_field_item {}
|
||||||
| part_field_list ',' part_field_item {};
|
| part_field_list ',' part_field_item {}
|
||||||
|
;
|
||||||
|
|
||||||
part_field_item:
|
part_field_item:
|
||||||
ident
|
ident
|
||||||
{
|
{
|
||||||
Lex->part_info->part_field_list.push_back($1.str);
|
Lex->part_info->part_field_list.push_back($1.str);
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_func:
|
part_func:
|
||||||
'(' remember_name part_func_expr remember_end ')'
|
'(' remember_name part_func_expr remember_end ')'
|
||||||
@ -2686,7 +2706,8 @@ part_func:
|
|||||||
lex->part_info->part_expr= $3;
|
lex->part_info->part_expr= $3;
|
||||||
lex->part_info->part_func_string= $2+1;
|
lex->part_info->part_func_string= $2+1;
|
||||||
lex->part_info->part_func_len= expr_len;
|
lex->part_info->part_func_len= expr_len;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
sub_part_func:
|
sub_part_func:
|
||||||
'(' remember_name part_func_expr remember_end ')'
|
'(' remember_name part_func_expr remember_end ')'
|
||||||
@ -2697,7 +2718,8 @@ sub_part_func:
|
|||||||
lex->part_info->subpart_expr= $3;
|
lex->part_info->subpart_expr= $3;
|
||||||
lex->part_info->subpart_func_string= $2+1;
|
lex->part_info->subpart_func_string= $2+1;
|
||||||
lex->part_info->subpart_func_len= expr_len;
|
lex->part_info->subpart_func_len= expr_len;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
opt_no_parts:
|
opt_no_parts:
|
||||||
@ -2711,7 +2733,8 @@ opt_no_parts:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
Lex->part_info->no_parts= no_parts;
|
Lex->part_info->no_parts= no_parts;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
opt_sub_part:
|
opt_sub_part:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
@ -2725,15 +2748,18 @@ opt_sub_part:
|
|||||||
lex->part_info->subpart_type= HASH_PARTITION;
|
lex->part_info->subpart_type= HASH_PARTITION;
|
||||||
lex->part_info->list_of_subpart_fields= TRUE;
|
lex->part_info->list_of_subpart_fields= TRUE;
|
||||||
}
|
}
|
||||||
opt_no_subparts {};
|
opt_no_subparts {}
|
||||||
|
;
|
||||||
|
|
||||||
sub_part_field_list:
|
sub_part_field_list:
|
||||||
sub_part_field_item {}
|
sub_part_field_item {}
|
||||||
| sub_part_field_list ',' sub_part_field_item {};
|
| sub_part_field_list ',' sub_part_field_item {}
|
||||||
|
;
|
||||||
|
|
||||||
sub_part_field_item:
|
sub_part_field_item:
|
||||||
ident
|
ident
|
||||||
{ Lex->part_info->subpart_field_list.push_back($1.str); };
|
{ Lex->part_info->subpart_field_list.push_back($1.str); }
|
||||||
|
;
|
||||||
|
|
||||||
part_func_expr:
|
part_func_expr:
|
||||||
bit_expr
|
bit_expr
|
||||||
@ -2749,6 +2775,7 @@ part_func_expr:
|
|||||||
}
|
}
|
||||||
$$=$1;
|
$$=$1;
|
||||||
}
|
}
|
||||||
|
;
|
||||||
|
|
||||||
opt_no_subparts:
|
opt_no_subparts:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
@ -2761,7 +2788,8 @@ opt_no_subparts:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
Lex->part_info->no_subparts= no_parts;
|
Lex->part_info->no_subparts= no_parts;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_defs:
|
part_defs:
|
||||||
/* empty */
|
/* empty */
|
||||||
@ -2785,11 +2813,13 @@ part_defs:
|
|||||||
}
|
}
|
||||||
part_info->count_curr_subparts= 0;
|
part_info->count_curr_subparts= 0;
|
||||||
part_info->count_curr_parts= 0;
|
part_info->count_curr_parts= 0;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_def_list:
|
part_def_list:
|
||||||
part_definition {}
|
part_definition {}
|
||||||
| part_def_list ',' part_definition {};
|
| part_def_list ',' part_definition {}
|
||||||
|
;
|
||||||
|
|
||||||
part_definition:
|
part_definition:
|
||||||
PARTITION_SYM
|
PARTITION_SYM
|
||||||
@ -2812,47 +2842,61 @@ part_definition:
|
|||||||
part_name {}
|
part_name {}
|
||||||
opt_part_values {}
|
opt_part_values {}
|
||||||
opt_part_options {}
|
opt_part_options {}
|
||||||
opt_sub_partition {};
|
opt_sub_partition {}
|
||||||
|
;
|
||||||
|
|
||||||
part_name:
|
part_name:
|
||||||
ident_or_text
|
ident_or_text
|
||||||
{ Lex->part_info->curr_part_elem->partition_name= $1.str; };
|
{ Lex->part_info->curr_part_elem->partition_name= $1.str; }
|
||||||
|
;
|
||||||
|
|
||||||
opt_part_values:
|
opt_part_values:
|
||||||
/* empty */
|
/* empty */
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
if (lex->part_info->part_type == RANGE_PARTITION)
|
if (!is_partition_management(lex))
|
||||||
{
|
{
|
||||||
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
|
if (lex->part_info->part_type == RANGE_PARTITION)
|
||||||
"RANGE", "LESS THAN");
|
{
|
||||||
YYABORT;
|
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
|
||||||
}
|
"RANGE", "LESS THAN");
|
||||||
if (lex->part_info->part_type == LIST_PARTITION)
|
YYABORT;
|
||||||
{
|
}
|
||||||
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
|
if (lex->part_info->part_type == LIST_PARTITION)
|
||||||
"LIST", "IN");
|
{
|
||||||
YYABORT;
|
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
|
||||||
|
"LIST", "IN");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| VALUES LESS_SYM THAN_SYM part_func_max
|
| VALUES LESS_SYM THAN_SYM part_func_max
|
||||||
{
|
{
|
||||||
if (Lex->part_info->part_type != RANGE_PARTITION)
|
LEX *lex= Lex;
|
||||||
|
if (!is_partition_management(lex))
|
||||||
{
|
{
|
||||||
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
|
if (Lex->part_info->part_type != RANGE_PARTITION)
|
||||||
"RANGE", "LESS THAN");
|
{
|
||||||
YYABORT;
|
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
|
||||||
|
"RANGE", "LESS THAN");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| VALUES IN_SYM '(' part_list_func ')'
|
| VALUES IN_SYM '(' part_list_func ')'
|
||||||
{
|
{
|
||||||
if (Lex->part_info->part_type != LIST_PARTITION)
|
LEX *lex= Lex;
|
||||||
|
if (!is_partition_management(lex))
|
||||||
{
|
{
|
||||||
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
|
if (Lex->part_info->part_type != LIST_PARTITION)
|
||||||
"LIST", "IN");
|
{
|
||||||
YYABORT;
|
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
|
||||||
|
"LIST", "IN");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_func_max:
|
part_func_max:
|
||||||
MAX_VALUE_SYM
|
MAX_VALUE_SYM
|
||||||
@ -2873,17 +2917,20 @@ part_func_max:
|
|||||||
yyerror(ER(ER_PARTITION_MAXVALUE_ERROR));
|
yyerror(ER(ER_PARTITION_MAXVALUE_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_range_func:
|
part_range_func:
|
||||||
'(' part_bit_expr ')'
|
'(' part_bit_expr ')'
|
||||||
{
|
{
|
||||||
Lex->part_info->curr_part_elem->range_value= $2;
|
Lex->part_info->curr_part_elem->range_value= $2;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_list_func:
|
part_list_func:
|
||||||
part_list_item {}
|
part_list_item {}
|
||||||
| part_list_func ',' part_list_item {};
|
| part_list_func ',' part_list_item {}
|
||||||
|
;
|
||||||
|
|
||||||
part_list_item:
|
part_list_item:
|
||||||
part_bit_expr
|
part_bit_expr
|
||||||
@ -2896,7 +2943,8 @@ part_list_item:
|
|||||||
}
|
}
|
||||||
*value_ptr= $1;
|
*value_ptr= $1;
|
||||||
Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr);
|
Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr);
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
part_bit_expr:
|
part_bit_expr:
|
||||||
bit_expr
|
bit_expr
|
||||||
@ -2926,6 +2974,7 @@ part_bit_expr:
|
|||||||
item_value= part_expr->val_int();
|
item_value= part_expr->val_int();
|
||||||
$$= item_value;
|
$$= item_value;
|
||||||
}
|
}
|
||||||
|
;
|
||||||
|
|
||||||
opt_sub_partition:
|
opt_sub_partition:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
@ -2947,11 +2996,13 @@ opt_sub_partition:
|
|||||||
part_info->no_subparts= part_info->count_curr_subparts;
|
part_info->no_subparts= part_info->count_curr_subparts;
|
||||||
}
|
}
|
||||||
part_info->count_curr_subparts= 0;
|
part_info->count_curr_subparts= 0;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
sub_part_list:
|
sub_part_list:
|
||||||
sub_part_definition {}
|
sub_part_definition {}
|
||||||
| sub_part_list ',' sub_part_definition {};
|
| sub_part_list ',' sub_part_definition {}
|
||||||
|
;
|
||||||
|
|
||||||
sub_part_definition:
|
sub_part_definition:
|
||||||
SUBPARTITION_SYM
|
SUBPARTITION_SYM
|
||||||
@ -2970,19 +3021,23 @@ sub_part_definition:
|
|||||||
part_info->count_curr_subparts++;
|
part_info->count_curr_subparts++;
|
||||||
p_elem->engine_type= DB_TYPE_UNKNOWN;
|
p_elem->engine_type= DB_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
sub_name opt_part_options {};
|
sub_name opt_part_options {}
|
||||||
|
;
|
||||||
|
|
||||||
sub_name:
|
sub_name:
|
||||||
ident_or_text
|
ident_or_text
|
||||||
{ Lex->part_info->curr_part_elem->partition_name= $1.str; };
|
{ Lex->part_info->curr_part_elem->partition_name= $1.str; }
|
||||||
|
;
|
||||||
|
|
||||||
opt_part_options:
|
opt_part_options:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
| opt_part_option_list {};
|
| opt_part_option_list {}
|
||||||
|
;
|
||||||
|
|
||||||
opt_part_option_list:
|
opt_part_option_list:
|
||||||
opt_part_option_list opt_part_option {}
|
opt_part_option_list opt_part_option {}
|
||||||
| opt_part_option {};
|
| opt_part_option {}
|
||||||
|
;
|
||||||
|
|
||||||
opt_part_option:
|
opt_part_option:
|
||||||
TABLESPACE opt_equal ident_or_text
|
TABLESPACE opt_equal ident_or_text
|
||||||
@ -3000,7 +3055,8 @@ opt_part_option:
|
|||||||
| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
|
| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
|
||||||
{ Lex->part_info->curr_part_elem->index_file_name= $4.str; }
|
{ Lex->part_info->curr_part_elem->index_file_name= $4.str; }
|
||||||
| COMMENT_SYM opt_equal TEXT_STRING_sys
|
| COMMENT_SYM opt_equal TEXT_STRING_sys
|
||||||
{ Lex->part_info->curr_part_elem->part_comment= $3.str; };
|
{ Lex->part_info->curr_part_elem->part_comment= $3.str; }
|
||||||
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
End of partition parser part
|
End of partition parser part
|
||||||
@ -3850,8 +3906,92 @@ alter_commands:
|
|||||||
| alter_list
|
| alter_list
|
||||||
opt_partitioning
|
opt_partitioning
|
||||||
| partitioning
|
| partitioning
|
||||||
|
/*
|
||||||
|
This part was added for release 5.1 by Mikael Ronstr<74>m.
|
||||||
|
From here we insert a number of commands to manage the partitions of a
|
||||||
|
partitioned table such as adding partitions, dropping partitions,
|
||||||
|
reorganising partitions in various manners. In future releases the list
|
||||||
|
will be longer and also include moving partitions to a
|
||||||
|
new table and so forth.
|
||||||
|
*/
|
||||||
|
| add_partition_rule
|
||||||
|
| DROP PARTITION_SYM alt_part_name_list
|
||||||
|
{
|
||||||
|
Lex->alter_info.flags|= ALTER_DROP_PARTITION;
|
||||||
|
}
|
||||||
|
| COALESCE PARTITION_SYM ulong_num
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->alter_info.flags|= ALTER_COALESCE_PARTITION;
|
||||||
|
lex->alter_info.no_parts= $3;
|
||||||
|
}
|
||||||
|
| reorg_partition_rule
|
||||||
;
|
;
|
||||||
|
|
||||||
|
add_partition_rule:
|
||||||
|
ADD PARTITION_SYM
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->part_info= new partition_info();
|
||||||
|
if (!lex->part_info)
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
lex->alter_info.flags|= ALTER_ADD_PARTITION;
|
||||||
|
}
|
||||||
|
add_part_extra
|
||||||
|
{}
|
||||||
|
;
|
||||||
|
|
||||||
|
add_part_extra:
|
||||||
|
| '(' part_def_list ')'
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->part_info->no_parts= lex->part_info->count_curr_parts;
|
||||||
|
}
|
||||||
|
| PARTITIONS_SYM ulong_num
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->part_info->no_parts= $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
reorg_partition_rule:
|
||||||
|
REORGANISE_SYM PARTITION_SYM
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->part_info= new partition_info();
|
||||||
|
if (!lex->part_info)
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
lex->alter_info.flags|= ALTER_REORGANISE_PARTITION;
|
||||||
|
}
|
||||||
|
alt_part_name_list INTO '(' part_def_list ')'
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
lex->part_info->no_parts= lex->part_info->count_curr_parts;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
alt_part_name_list:
|
||||||
|
alt_part_name_item {}
|
||||||
|
| alt_part_name_list ',' alt_part_name_item {}
|
||||||
|
;
|
||||||
|
|
||||||
|
alt_part_name_item:
|
||||||
|
ident
|
||||||
|
{
|
||||||
|
Lex->alter_info.partition_names.push_back($1.str);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
End of management of partition commands
|
||||||
|
*/
|
||||||
|
|
||||||
alter_list:
|
alter_list:
|
||||||
alter_list_item
|
alter_list_item
|
||||||
| alter_list ',' alter_list_item
|
| alter_list ',' alter_list_item
|
||||||
@ -7872,6 +8012,7 @@ keyword_sp:
|
|||||||
| CHANGED {}
|
| CHANGED {}
|
||||||
| CIPHER_SYM {}
|
| CIPHER_SYM {}
|
||||||
| CLIENT_SYM {}
|
| CLIENT_SYM {}
|
||||||
|
| COALESCE {}
|
||||||
| COLLATION_SYM {}
|
| COLLATION_SYM {}
|
||||||
| COLUMNS {}
|
| COLUMNS {}
|
||||||
| COMMITTED_SYM {}
|
| COMMITTED_SYM {}
|
||||||
@ -8007,6 +8148,7 @@ keyword_sp:
|
|||||||
| RELAY_LOG_FILE_SYM {}
|
| RELAY_LOG_FILE_SYM {}
|
||||||
| RELAY_LOG_POS_SYM {}
|
| RELAY_LOG_POS_SYM {}
|
||||||
| RELOAD {}
|
| RELOAD {}
|
||||||
|
| REORGANISE_SYM {}
|
||||||
| REPEATABLE_SYM {}
|
| REPEATABLE_SYM {}
|
||||||
| REPLICATION {}
|
| REPLICATION {}
|
||||||
| RESOURCES {}
|
| RESOURCES {}
|
||||||
|
Reference in New Issue
Block a user