diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index e95489864f7..dbb0e20c246 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,5 +1,47 @@ drop table if exists t1; create table t1 (a int) +partition by key(a) +partitions 0.2+e1; +ERROR 42000: Only normal integers allowed as number here near '0.2+e1' at line 3 +create table t1 (a int) +partition by key(a) +partitions -1; +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 '-1' at line 3 +create table t1 (a int) +partition by key(a) +partitions 1.5; +ERROR 42000: Only normal integers allowed as number here near '1.5' at line 3 +create table t1 (a int) +partition by key(a) +partitions 1e+300; +ERROR 42000: Only normal integers allowed as number here near '1e+300' at line 3 +create table t1 (a int) +engine = innodb +partition by key (a); +show table status; +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 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned +insert into t1 values (0), (1), (2), (3); +show table status; +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 InnoDB 10 Compact 4 4096 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned +drop table t1; +create table t1 (a int auto_increment primary key) +engine = innodb +partition by key (a); +show table status; +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 InnoDB 10 Compact 2 8192 16384 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL partitioned +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +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 InnoDB 10 Compact 4 4096 16384 0 0 0 5 NULL NULL NULL latin1_swedish_ci NULL partitioned +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +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 InnoDB 10 Compact 8 2048 16384 0 0 0 9 NULL NULL NULL latin1_swedish_ci NULL partitioned +drop table t1; +create table t1 (a int) partition by list (a) (partition p0 values in (1)); create procedure pz() @@ -1117,4 +1159,32 @@ hello/master-data/tmpinx/t1#P#p1#SP#subpart11.MYI hello/master-data/tmpinx/t1#P#p2#SP#subpart20.MYI hello/master-data/tmpinx/t1#P#p2#SP#subpart21.MYI drop table t1; +create table t1 (a bigint unsigned not null, primary key(a)) +engine = myisam +partition by key (a) +partitions 10; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (a) PARTITIONS 10 */ +insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE), +(18446744073709551613), (18446744073709551612); +select * from t1; +a +18446744073709551612 +18446744073709551613 +18446744073709551614 +18446744073709551615 +select * from t1 where a = 18446744073709551615; +a +18446744073709551615 +delete from t1 where a = 18446744073709551615; +select * from t1; +a +18446744073709551612 +18446744073709551613 +18446744073709551614 +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/partition_mgm.result b/mysql-test/r/partition_mgm.result index f64ffaff495..9b5a34bda50 100644 --- a/mysql-test/r/partition_mgm.result +++ b/mysql-test/r/partition_mgm.result @@ -1,4 +1,14 @@ DROP TABLE IF EXISTS t1; +create table t1 (a int) +partition by range (a) +subpartition by key (a) +(partition p0 values less than (10) (subpartition sp00, subpartition sp01), +partition p1 values less than (20) (subpartition sp10, subpartition sp11)); +alter table t1 reorganize partition p0 into +(partition p0 values less than (10) (subpartition sp00, +subpartition sp01, subpartition sp02)); +ERROR HY000: Wrong number of subpartitions defined, mismatch with previous setting +drop table t1; CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30)) PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER)) PARTITIONS 2; SHOW CREATE TABLE t1; diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 9812c80040b..be88d9f6639 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -1,4 +1,14 @@ drop table if exists t1; +create table t1 (a date) +engine = innodb +partition by range (year(a)) +(partition p0 values less than (2006), +partition p1 values less than (2007)); +explain partitions select * from t1 +where a between '2006-01-01' and '2007-06-01'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where +drop table t1; create table t1 (a int unsigned) partition by range (a) (partition pnull values less than (0), diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index d4e930f91ec..5c5a7a430e3 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -9,6 +9,47 @@ drop table if exists t1; --enable_warnings +# +# Bug 15890: Strange number of partitions accepted +# +-- error 1064 +create table t1 (a int) +partition by key(a) +partitions 0.2+e1; +-- error 1064 +create table t1 (a int) +partition by key(a) +partitions -1; +-- error 1064 +create table t1 (a int) +partition by key(a) +partitions 1.5; +-- error 1064 +create table t1 (a int) +partition by key(a) +partitions 1e+300; + +# +# Bug 21173: SHOW TABLE STATUS crashes server in InnoDB +# +create table t1 (a int) +engine = innodb +partition by key (a); +show table status; +insert into t1 values (0), (1), (2), (3); +show table status; +drop table t1; + +create table t1 (a int auto_increment primary key) +engine = innodb +partition by key (a); +show table status; +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +insert into t1 values (NULL), (NULL), (NULL), (NULL); +show table status; +drop table t1; +>>>>>>> # # Bug 19309 Partitions: Crash if double procedural alter # @@ -1300,4 +1341,22 @@ eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO drop table t1; --exec rmdir $MYSQLTEST_VARDIR/master-data/tmpdata || true --exec rmdir $MYSQLTEST_VARDIR/master-data/tmpinx || true + +# +# Bug 21388: Bigint fails to find record +# +create table t1 (a bigint unsigned not null, primary key(a)) +engine = myisam +partition by key (a) +partitions 10; + +show create table t1; +insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE), +(18446744073709551613), (18446744073709551612); +select * from t1; +select * from t1 where a = 18446744073709551615; +delete from t1 where a = 18446744073709551615; +select * from t1; +drop table t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/partition_mgm.test b/mysql-test/t/partition_mgm.test index 39512de154f..f1a89b28443 100644 --- a/mysql-test/t/partition_mgm.test +++ b/mysql-test/t/partition_mgm.test @@ -2,6 +2,23 @@ --disable_warnings DROP TABLE IF EXISTS t1; --enable_warnings + +# +# Bug 21143: mysqld hang when error in number of subparts in +# REORGANIZE command +# +create table t1 (a int) +partition by range (a) +subpartition by key (a) +(partition p0 values less than (10) (subpartition sp00, subpartition sp01), + partition p1 values less than (20) (subpartition sp10, subpartition sp11)); + +-- error ER_PARTITION_WRONG_NO_SUBPART_ERROR +alter table t1 reorganize partition p0 into +(partition p0 values less than (10) (subpartition sp00, +subpartition sp01, subpartition sp02)); +drop table t1; + CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30)) PARTITION BY HASH(CAST(YEAR(f_date) AS SIGNED INTEGER)) PARTITIONS 2; SHOW CREATE TABLE t1; diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 670b9333ab9..8719cbd98c4 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -9,6 +9,18 @@ drop table if exists t1; --enable_warnings +# +# Bug 21339: Crash in Explain Partitions +# +create table t1 (a date) +engine = innodb +partition by range (year(a)) +(partition p0 values less than (2006), + partition p1 values less than (2007)); +explain partitions select * from t1 +where a between '2006-01-01' and '2007-06-01'; +drop table t1; + # # More checks for partition pruning # @@ -686,3 +698,4 @@ EXPLAIN PARTITIONS SELECT * from t1 WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR (a >= '2005-07-01' AND a <= '2005-09-30'); DROP TABLE t1; + diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 615c4bfb1bf..b43a423575d 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1343,9 +1343,9 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, ones used to be. */ first= FALSE; - DBUG_ASSERT(i + m_reorged_parts <= m_file_tot_parts); + DBUG_ASSERT(((i*no_subparts) + m_reorged_parts) <= m_file_tot_parts); memcpy((void*)m_reorged_file, &m_file[i*no_subparts], - sizeof(handler*)*m_reorged_parts*no_subparts); + sizeof(handler*)*m_reorged_parts); } } while (++i < no_parts); } @@ -4183,9 +4183,19 @@ void ha_partition::info(uint flag) ulonglong nb_reserved_values; DBUG_PRINT("info", ("HA_STATUS_AUTO")); /* we don't want to reserve any values, it's pure information */ - get_auto_increment(0, 0, 0, &stats.auto_increment_value, - &nb_reserved_values); - release_auto_increment(); + + if (table->found_next_number_field) + { + /* + Can only call get_auto_increment for tables that actually + have auto_increment columns, otherwise there will be + problems in handlers that don't expect get_auto_increment + for non-autoincrement tables. + */ + get_auto_increment(0, 0, 0, &stats.auto_increment_value, + &nb_reserved_values); + release_auto_increment(); + } } if (flag & HA_STATUS_VARIABLE) { @@ -5145,13 +5155,12 @@ void ha_partition::print_error(int error, myf errflag) DBUG_ENTER("ha_partition::print_error"); /* Should probably look for my own errors first */ - /* monty: needs to be called for the last used partition ! */ DBUG_PRINT("enter", ("error: %d", error)); if (error == HA_ERR_NO_PARTITION_FOUND) m_part_info->print_no_partition_found(table); else - m_file[0]->print_error(error, errflag); + m_file[m_last_part]->print_error(error, errflag); DBUG_VOID_RETURN; } @@ -5161,8 +5170,7 @@ bool ha_partition::get_error_message(int error, String *buf) DBUG_ENTER("ha_partition::get_error_message"); /* Should probably look for my own errors first */ - /* monty: needs to be called for the last used partition ! */ - DBUG_RETURN(m_file[0]->get_error_message(error, buf)); + DBUG_RETURN(m_file[m_last_part]->get_error_message(error, buf)); } @@ -5363,7 +5371,6 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment, if (increment) // If not check for values *nb_reserved_values= (last_value == ULONGLONG_MAX) ? ULONGLONG_MAX : ((last_value - *first_value) / increment); - DBUG_VOID_RETURN; } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 297e4c5c374..62a362d0859 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5954,3 +5954,5 @@ ER_BAD_LOG_ENGINE eng "One can use only CSV and MyISAM engines for the log tables" ER_CANT_DROP_LOG_TABLE eng "Cannot drop log table if log is enabled" +ER_ONLY_INTEGERS_ALLOWED + eng "Only normal integers allowed as number here" diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index f1c8e099441..208f9a0837a 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2573,10 +2573,13 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, } else { - if (part_func_value == range_array[loc_part_id]) - loc_part_id += test(include_endpoint); - else if (part_func_value > range_array[loc_part_id]) - loc_part_id++; + if (loc_part_id < max_partition) + { + if (part_func_value == range_array[loc_part_id]) + loc_part_id += test(include_endpoint); + else if (part_func_value > range_array[loc_part_id]) + loc_part_id++; + } loc_part_id++; } DBUG_RETURN(loc_part_id); @@ -3471,14 +3474,9 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf, } table->part_info= part_info; table->file->set_part_info(part_info); - if (part_info->default_engine_type == NULL) - { + if (!part_info->default_engine_type) part_info->default_engine_type= default_db_type; - } - else - { - DBUG_ASSERT(part_info->default_engine_type == default_db_type); - } + DBUG_ASSERT(part_info->default_engine_type == default_db_type); part_info->item_free_list= thd->free_list; { @@ -4392,6 +4390,13 @@ state of p1. my_error(ER_REORG_HASH_ONLY_ON_SAME_NO, MYF(0)); DBUG_RETURN(TRUE); } + if (tab_part_info->is_sub_partitioned() && + alt_part_info->no_subparts && + alt_part_info->no_subparts != tab_part_info->no_subparts) + { + my_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR, 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) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index eb3d0d40817..dc6f6277043 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -752,10 +752,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt %type - ulong_num merge_insert_types + ulong_num real_ulong_num merge_insert_types %type - ulonglong_num size_number + ulonglong_num real_ulonglong_num size_number %type part_bit_expr @@ -3097,7 +3097,7 @@ opt_ts_redo_buffer_size: }; opt_ts_nodegroup: - NODEGROUP_SYM opt_equal ulong_num + NODEGROUP_SYM opt_equal real_ulong_num { LEX *lex= Lex; if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP) @@ -3156,7 +3156,7 @@ ts_wait: }; size_number: - ulong_num { $$= $1;} + real_ulong_num { $$= $1;} | IDENT { ulonglong number, test_number; @@ -3395,7 +3395,7 @@ sub_part_func: opt_no_parts: /* empty */ {} - | PARTITIONS_SYM ulong_num + | PARTITIONS_SYM real_ulong_num { uint no_parts= $2; LEX *lex= Lex; @@ -3459,7 +3459,7 @@ part_func_expr: opt_no_subparts: /* empty */ {} - | SUBPARTITIONS_SYM ulong_num + | SUBPARTITIONS_SYM real_ulong_num { uint no_parts= $2; LEX *lex= Lex; @@ -3799,11 +3799,11 @@ opt_part_option: lex->part_info->curr_part_elem->engine_type= $4; lex->part_info->default_engine_type= $4; } - | NODEGROUP_SYM opt_equal ulong_num + | NODEGROUP_SYM opt_equal real_ulong_num { Lex->part_info->curr_part_elem->nodegroup_id= $3; } - | MAX_ROWS opt_equal ulonglong_num + | MAX_ROWS opt_equal real_ulonglong_num { Lex->part_info->curr_part_elem->part_max_rows= $3; } - | MIN_ROWS opt_equal ulonglong_num + | MIN_ROWS opt_equal real_ulonglong_num { Lex->part_info->curr_part_elem->part_min_rows= $3; } | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->part_info->curr_part_elem->data_file_name= $4.str; } @@ -4933,7 +4933,7 @@ alter_commands: lex->check_opt.init(); } opt_mi_repair_type - | COALESCE PARTITION_SYM opt_no_write_to_binlog ulong_num + | COALESCE PARTITION_SYM opt_no_write_to_binlog real_ulong_num { LEX *lex= Lex; lex->alter_info.flags|= ALTER_COALESCE_PARTITION; @@ -4981,7 +4981,7 @@ add_part_extra: LEX *lex= Lex; lex->part_info->no_parts= lex->part_info->partitions.elements; } - | PARTITIONS_SYM ulong_num + | PARTITIONS_SYM real_ulong_num { LEX *lex= Lex; lex->part_info->no_parts= $2; @@ -7516,7 +7516,15 @@ ulong_num: | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } | DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } | FLOAT_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } - ; + ; + +real_ulong_num: + NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } + | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); } + | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } + | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } + | dec_num_error { YYABORT; } + ; ulonglong_num: NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } @@ -7526,6 +7534,23 @@ ulonglong_num: | FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } ; +real_ulonglong_num: + NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } + | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } + | LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); } + | dec_num_error { YYABORT; } + ; + +dec_num_error: + dec_num + { yyerror(ER(ER_ONLY_INTEGERS_ALLOWED)); } + ; + +dec_num: + DECIMAL_NUM + | FLOAT_NUM + ; + procedure_clause: /* empty */ | PROCEDURE ident /* Procedure name */