diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 80942c861fe..d84d8e25ef1 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -428,4 +428,40 @@ partition by list (a) alter table t1 rebuild partition; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 drop table t1; +create table t1 (a int) engine=innodb partition by hash(a) ; +show table status like 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 PARTITION 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL +drop table t1; +create table t2 (s1 int not null auto_increment, primary key (s1)) partition by list (s1) (partition p1 values in (1),partition p2 values in (2),partition p3 values in (3),partition p4 values in (4)); +insert into t2 values (null),(null),(null); +select * from t2; +s1 +1 +2 +3 +select * from t2 where s1 < 2; +s1 +1 +update t2 set s1 = s1 + 1 order by s1 desc; +select * from t2 where s1 < 3; +s1 +2 +select * from t2 where s1 = 2; +s1 +2 +drop table t2; +create temporary table t1 (a int) partition by hash(a); +ERROR HY000: Cannot create temporary table with partitions +create table t1 (a int, b int) partition by list (a) +(partition p1 values in (1), partition p2 values in (2)); +alter table t1 add primary key (b); +ERROR HY000: A PRIMARY KEY need to include all fields in the partition function +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY LIST (a) (PARTITION p1 VALUES IN (1) ENGINE = MyISAM, PARTITION p2 VALUES IN (2) ENGINE = MyISAM) +drop table t1; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 8fc46490856..9ee2bbd36b3 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -552,4 +552,40 @@ alter table t1 rebuild partition; drop table t1; +# +# Bug #14673: Wrong InnoDB default row format +# +create table t1 (a int) engine=innodb partition by hash(a) ; +show table status like 't1'; +drop table t1; + +# +# Bug #14526: Partitions: indexed searches fail +# +create table t2 (s1 int not null auto_increment, primary key (s1)) partition by list (s1) (partition p1 values in (1),partition p2 values in (2),partition p3 values in (3),partition p4 values in (4)); +insert into t2 values (null),(null),(null); +select * from t2; +select * from t2 where s1 < 2; +update t2 set s1 = s1 + 1 order by s1 desc; +select * from t2 where s1 < 3; +select * from t2 where s1 = 2; +drop table t2; + +# +# Bug #17497: Partitions: crash if add partition on temporary table +# +--error ER_PARTITION_NO_TEMPORARY +create temporary table t1 (a int) partition by hash(a); + +# +# Bug #17097: Partitions: failing ADD PRIMARY KEY leads to temporary rotten +# metadata,crash +# +create table t1 (a int, b int) partition by list (a) + (partition p1 values in (1), partition p2 values in (2)); +--error ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF +alter table t1 add primary key (b); +show create table t1; +drop table t1; + --echo End of 5.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 14fa9f0393c..b5b33668ba0 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2603,22 +2603,13 @@ void ha_partition::unlock_row() ha_berkeley.cc has a variant of how to store it intact by "packing" it for ha_berkeley's own native storage type. - See the note for update_row() on auto_increments and timestamps. This - case also applied to write_row(). - Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. ADDITIONAL INFO: - Most handlers set timestamp when calling write row if any such fields - exists. Since we are calling an underlying handler we assume theĀ“ - underlying handler will assume this responsibility. - - Underlying handlers will also call update_auto_increment to calculate - the new auto increment value. We will catch the call to - get_auto_increment and ensure this increment value is maintained by - only one of the underlying handlers. + We have to set timestamp fields and auto_increment fields, because those + may be used in determining which partition the row should be written to. */ int ha_partition::write_row(byte * buf) @@ -2632,6 +2623,17 @@ int ha_partition::write_row(byte * buf) DBUG_ENTER("ha_partition::write_row"); DBUG_ASSERT(buf == m_rec0); + /* If we have a timestamp column, update it to the current time */ + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) + table->timestamp_field->set_time(); + + /* + If we have an auto_increment column and we are writing a changed row + or a new row, then update the auto_increment value in the record. + */ + if (table->next_number_field && buf == table->record[0]) + update_auto_increment(); + #ifdef NOT_NEEDED if (likely(buf == rec0)) #endif @@ -5115,6 +5117,22 @@ const char *ha_partition::index_type(uint inx) } +enum row_type ha_partition::get_row_type() const +{ + handler **file; + enum row_type type= (*m_file)->get_row_type(); + + for (file= m_file, file++; *file; file++) + { + enum row_type part_type= (*file)->get_row_type(); + if (part_type != type) + return ROW_TYPE_NOT_USED; + } + + return type; +} + + void ha_partition::print_error(int error, myf errflag) { DBUG_ENTER("ha_partition::print_error"); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index f828cc65ed3..32ea75fabf0 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -527,6 +527,9 @@ public: virtual const char *table_type() const { return "PARTITION"; } + /* The name of the row type used for the underlying tables. */ + virtual enum row_type get_row_type() const; + /* Handler specific error messages */ diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d163da30e95..4255504e98f 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5820,4 +5820,5 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT eng "Cannot change the binary logging format inside a stored function or trigger" ER_NDB_CANT_SWITCH_BINLOG_FORMAT eng "The NDB cluster engine does not support changing the binlog format on the fly yet" - +ER_PARTITION_NO_TEMPORARY + eng "Cannot create temporary table with partitions" diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 014d3616d3d..a27e5b1979f 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4061,6 +4061,15 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info, { DBUG_ENTER("prep_alter_part_table"); + /* + 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= 0 forces a + flush of the table object in close_thread_tables(). + */ + if (table->part_info) + table->s->version= 0L; + if (alter_info->flags & (ALTER_ADD_PARTITION | ALTER_DROP_PARTITION | ALTER_COALESCE_PARTITION | ALTER_REORGANIZE_PARTITION | @@ -4069,19 +4078,12 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info, ALTER_REPAIR_PARTITION | ALTER_REBUILD_PARTITION)) { partition_info *tab_part_info= table->part_info; + uint flags= 0; if (!tab_part_info) { my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0)); DBUG_RETURN(TRUE); } - /* - 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= 0 forces a - flush of the table object in close_thread_tables(). - */ - uint flags= 0; - table->s->version= 0L; if (alter_info->flags == ALTER_TABLE_REORG) { uint new_part_no, curr_part_no; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a046da6b0a5..54fcefa3e6d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2073,6 +2073,11 @@ bool mysql_create_table_internal(THD *thd, char *part_syntax_buf; uint syntax_len; handlerton *engine_type; + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + { + my_error(ER_PARTITION_NO_TEMPORARY, MYF(0)); + goto err; + } while ((key= key_iterator++)) { if (key->type == Key::FOREIGN_KEY)