Commit 37306da9 authored by unknown's avatar unknown

WL #2602, #2603, #2604

Added new syntax for partition management


mysql-test/t/partition_error.test:
  New line
sql/ha_partition.cc:
  Added support for DROP PARTITION on-line
sql/ha_partition.h:
  Added support for DROP PARTITION on-line
sql/handler.h:
  Introduced state of partition
  Introduced extra list of temporary partitions
  Removed no_full_parts
  A couple of methods to check for duplicate names of partitions
  Adaptions of default checks to be useful from ALTER TABLE
  partition management
  New method on handler to drop partitions
  New method to check for foreign keys on table
sql/lex.h:
  COALESCE and REORGANISE used by ALTER TABLE x COALESCE/REORGANISE PARTITION
sql/mysql_priv.h:
  Parser needs method to check if partition management command is ongoing
sql/share/errmsg.txt:
  A number of new error messages for partition management
sql/sql_lex.h:
  Adapted the ALTER_INFO data structure for partition management
sql/sql_partition.cc:
  Couple of new routines + adaption of existing for new
  partition management functionality
sql/sql_table.cc:
  bin log writing into separate subroutine to minimise code
  duplication.
  Lots of new code to handle partition management
sql/sql_yacc.yy:
  New syntax for partition management
  Fixed a few errors in the parser part for partitioning
parent f8c544f0
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
(partition x1 values in 4,
partition x2 values in (5));
#
# 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
****************************************************************************/
/*
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
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)
{
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))
{
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);
}
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)
{
......@@ -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.
......
......@@ -166,6 +166,7 @@ class ha_partition :public handler
virtual int create_handler_files(const char *name);
virtual void update_create_info(HA_CREATE_INFO * create_info);
virtual char *update_table_comment(const char *comment);
virtual int drop_partitions(const char *path);
private:
/*
delete_table, rename_table and create uses very similar logic which
......@@ -633,6 +634,11 @@ class ha_partition :public handler
index scan module.
(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
{ return m_table_flags; }
/*
......
......@@ -103,6 +103,10 @@
#define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
#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 */
#define HA_KEY_SWITCH_NONUNIQ 0
#define HA_KEY_SWITCH_ALL 1
......@@ -399,6 +403,16 @@ enum partition_type {
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
class Item;
......@@ -415,13 +429,15 @@ class partition_element :public Sql_alloc {
char* data_file_name;
char* index_file_name;
enum db_type engine_type;
enum partition_state part_state;
uint16 nodegroup_id;
partition_element()
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
tablespace_name(NULL), range_value(0), part_comment(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();
list_val_list.empty();
......@@ -447,6 +463,7 @@ class partition_info :public Sql_alloc {
* Here comes a set of definitions needed for partitioned table handlers.
*/
List<partition_element> partitions;
List<partition_element> temp_partitions;
List<char> part_field_list;
List<char> subpart_field_list;
......@@ -492,7 +509,6 @@ class partition_info :public Sql_alloc {
uint part_func_len;
uint subpart_func_len;
uint no_full_parts;
uint no_parts;
uint no_subparts;
uint count_curr_parts;
......@@ -529,7 +545,7 @@ class partition_info :public Sql_alloc {
part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
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),
no_list_values(0), no_part_fields(0), no_subpart_fields(0),
no_full_part_fields(0), linear_hash_mask(0),
......@@ -543,6 +559,7 @@ class partition_info :public Sql_alloc {
all_fields_in_SPF.clear_all();
some_fields_in_PF.clear_all();
partitions.empty();
temp_partitions.empty();
part_field_list.empty();
subpart_field_list.empty();
}
......@@ -634,6 +651,13 @@ typedef struct st_ha_check_opt
#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);
int get_parts_for_update(const byte *old_data, byte *new_data,
const byte *rec0, partition_info *part_info,
......@@ -1138,6 +1162,20 @@ class handler :public Sql_alloc
virtual char *update_table_comment(const char * comment)
{ return (char*) comment;}
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()
{ return(NULL);} /* gets foreign key create string from InnoDB */
/* used in ALTER TABLE; 1 if changing storage engine is allowed */
......@@ -1153,6 +1191,7 @@ class handler :public Sql_alloc
virtual const char *table_type() const =0;
virtual const char **bas_ext() const =0;
virtual ulong table_flags(void) const =0;
virtual ulong alter_table_flags(void) const { return 0; }
#ifdef HAVE_PARTITION_DB
virtual ulong partition_flags(void) const { return 0;}
virtual int get_default_no_partitions(ulonglong max_rows) { return 1;}
......@@ -1198,6 +1237,19 @@ class handler :public Sql_alloc
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
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 */
virtual uint lock_count(void) const { return 1; }
virtual THR_LOCK_DATA **store_lock(THD *thd,
......
......@@ -110,6 +110,7 @@ static SYMBOL symbols[] = {
{ "CIPHER", SYM(CIPHER_SYM)},
{ "CLIENT", SYM(CLIENT_SYM)},
{ "CLOSE", SYM(CLOSE_SYM)},
{ "COALESCE", SYM(COALESCE)},
{ "COLLATE", SYM(COLLATE_SYM)},
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
......@@ -408,6 +409,7 @@ static SYMBOL symbols[] = {
{ "RELEASE", SYM(RELEASE_SYM)},
{ "RELOAD", SYM(RELOAD)},
{ "RENAME", SYM(RENAME)},
{ "REORGANISE", SYM(REORGANISE_SYM)},
{ "REPAIR", SYM(REPAIR)},
{ "REPEATABLE", SYM(REPEATABLE_SYM)},
{ "REPLACE", SYM(REPLACE)},
......@@ -589,7 +591,6 @@ static SYMBOL sql_functions[] = {
{ "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)},
{ "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)},
{ "COMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)},
{ "CONCAT", SYM(CONCAT)},
......
......@@ -627,6 +627,10 @@ bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
bool no_errors);
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
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"
swe "Partitioneringssyntax kan inte anvndas p egen hand i en SQL-frga"
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 r inte tillten i denna version av MySQL"
ER_PARTITION_NOT_DEFINED_ERROR
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
eng "Number of %s = 0 is not an allowed value"
swe "Antal %s = 0 r inte ett tillten vrde"
ER_PARTITION_MGMT_ON_NONPARTITIONED
eng "Partition management on a not partitioned table is not possible"
swe "Partitioneringskommando p en opartitionerad tabell r inte mjligt"
ER_DROP_PARTITION_NON_EXISTENT
eng "Error in list of partitions to change"
swe "Fel i listan av partitioner att frndra"
ER_DROP_LAST_PARTITION
eng "Cannot remove all partitions, use DROP TABLE instead"
swe "Det r inte tilltet att ta bort alla partitioner, anvnd DROP TABLE istllet"
ER_COALESCE_ONLY_ON_HASH_PARTITION
eng "COALESCE PARTITION can only be used on HASH/KEY partitions"
swe "COALESCE PARTITION kan bara anvndas 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 anvndas 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 "tminstone en partition mste lggas till vid ADD PARTITION"
ER_COALESCE_PARTITION_NO_PARTITION
eng "At least one partition must be coalesced"
swe "tminstone en partition mste sls ihop vid COALESCE PARTITION"
ER_REORG_PARTITION_NOT_EXIST
eng "More partitions to reorganise than there are partitions"
swe "Fler partitioner att reorganisera n det finns partitioner"
ER_SAME_NAME_PARTITION
eng "All partitions must have unique names in the table"
swe "Alla partitioner i tabellen mste ha unika namn"
ER_CONSECUTIVE_REORG_PARTITIONS
eng "When reorganising a set of partitions they must be in consecutive order"
swe "Nr ett antal partitioner omorganiseras mste 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 tcker ett strre intervall 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 nr en frmmande nyckel r definierad p tabellen"
......@@ -650,6 +650,10 @@ typedef class st_select_lex SELECT_LEX;
#define ALTER_CONVERT 1024
#define ALTER_FORCE 2048
#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
{
......@@ -658,9 +662,17 @@ typedef struct st_alter_info
uint flags;
enum enum_enable_or_disable keys_onoff;
enum tablespace_op_type tablespace_op;
List<char> partition_names;
uint no_parts;
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();}
} ALTER_INFO;
......
......@@ -89,7 +89,106 @@ uint32 get_partition_id_hash_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_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
the partition ids of the old and the new record.
......@@ -415,7 +514,8 @@ static bool check_list_constants(partition_info *part_info)
#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 *move_ptr= ptr;
......@@ -426,9 +526,9 @@ static char *create_default_partition_names(uint no_parts, bool subpart)
do
{
if (subpart)
my_sprintf(move_ptr, (move_ptr,"sp%u", i));
my_sprintf(move_ptr, (move_ptr,"sp%u", (start_no + i)));
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;
} 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,
handler *file, ulonglong max_rows)
handler *file, ulonglong max_rows,
uint start_no)
{
uint no_parts, i;
char *default_name;
......@@ -482,12 +583,14 @@ static bool set_up_default_partitions(partition_info *part_info,
if (part_info->no_parts == 0)
part_info->no_parts= file->get_default_no_partitions(max_rows);
no_parts= part_info->no_parts;
part_info->use_default_partitions= FALSE;
if (unlikely(no_parts > MAX_PARTITIONS))
{
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
goto end;
}
if (unlikely((!(default_name= create_default_partition_names(no_parts,
start_no,
FALSE)))))
goto end;
i= 0;
......@@ -537,8 +640,8 @@ static bool set_up_default_partitions(partition_info *part_info,
static bool set_up_default_subpartitions(partition_info *part_info,
handler *file, ulonglong max_rows)
{
uint i, j= 0, no_parts, no_subparts;
char *default_name;
uint i, j, no_parts, no_subparts;
char *default_name, *name_ptr;
bool result= TRUE;
partition_element *part_elem;
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);
no_parts= part_info->no_parts;
no_subparts= part_info->no_subparts;
part_info->use_default_subpartitions= FALSE;
if (unlikely((no_parts * no_subparts) > MAX_PARTITIONS))
{
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
goto end;
}
if (unlikely((!(default_name=
create_default_partition_names(no_subparts, TRUE)))))
create_default_partition_names(no_subparts, (uint)0, TRUE)))))
goto end;
i= 0;
do
{
part_elem= part_it++;
j= 0;
name_ptr= default_name;
do
{
partition_element *subpart_elem= new partition_element();
if (likely(subpart_elem != 0))
{
subpart_elem->engine_type= DB_TYPE_UNKNOWN;
subpart_elem->partition_name= default_name;
default_name+= MAX_PART_NAME_SIZE;
subpart_elem->partition_name= name_ptr;
name_ptr+= MAX_PART_NAME_SIZE;
part_elem->subpartitions.push_back(subpart_elem);
}
else
......@@ -598,14 +704,15 @@ static bool set_up_default_subpartitions(partition_info *part_info,
Support routine for check_partition_info
*/
static bool set_up_defaults_for_partitioning(partition_info *part_info,
handler *file,
ulonglong max_rows)
bool set_up_defaults_for_partitioning(partition_info *part_info,
handler *file,
ulonglong max_rows, uint start_no)
{
DBUG_ENTER("set_up_defaults_for_partitioning");
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)
DBUG_RETURN(set_up_default_subpartitions(part_info, file, max_rows));
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));
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;
tot_partitions= get_tot_partitions(part_info);
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));
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));
if (unlikely(!engine_array))
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];
tables.db= db_name;
part_info->no_full_parts= part_info->no_parts;
if (is_sub_partitioned(part_info))
{
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
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)
{
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;
KEY *key_info= NULL;
bool found_part_field= FALSE;
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment