From 9901efea1f23b697a08f13ff6e6061985d01331b Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Thu, 29 Jun 2006 15:50:44 +0500 Subject: [PATCH 01/22] Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context user name is calculated on function execution stage instead of parse stage --- mysql-test/r/sp_notembedded.result | 14 ++++++ mysql-test/t/sp_notembedded.test | 20 ++++++++ sql/mysql_priv.h | 1 + sql/sql_acl.cc | 73 +++++++++++++++++++++++------- sql/sql_parse.cc | 54 +++++++++++++++++++--- sql/sql_yacc.yy | 40 ++++------------ 6 files changed, 149 insertions(+), 53 deletions(-) diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index c8cafe5ace1..bcde32572c2 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -206,3 +206,17 @@ drop procedure bug10100pd| drop procedure bug10100pc| drop view v1| drop table t3| +drop procedure if exists bug15298_1; +drop procedure if exists bug15298_2; +grant all privileges on test.* to 'mysqltest_1'@'localhost'; +create procedure 15298_1 () sql security definer show grants for current_user; +create procedure 15298_2 () sql security definer show grants; +call 15298_1(); +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +call 15298_2(); +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +drop user mysqltest_1@localhost; +drop procedure 15298_1; +drop procedure 15298_2; diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index 0adbeb2d98b..b087f699f86 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -265,3 +265,23 @@ drop view v1| drop table t3| delimiter ;| + +# +# Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context +# +--disable_warnings +drop procedure if exists bug15298_1; +drop procedure if exists bug15298_2; +--enable_warnings +grant all privileges on test.* to 'mysqltest_1'@'localhost'; +create procedure 15298_1 () sql security definer show grants for current_user; +create procedure 15298_2 () sql security definer show grants; + +connect (con1,localhost,mysqltest_1,,test); +call 15298_1(); +call 15298_2(); + +connection default; +drop user mysqltest_1@localhost; +drop procedure 15298_1; +drop procedure 15298_2; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3c58f2cbc6b..fcdfe1567e3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -537,6 +537,7 @@ int append_query_string(CHARSET_INFO *csinfo, void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); +LEX_USER *get_current_user(THD *thd, LEX_USER *user); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8b235d26d37..ae7df0dae54 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2766,7 +2766,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, { ulong column_priv= 0; List_iterator str_list (user_list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; TABLE_LIST tables[3]; bool create_new_users=0; char *db_name, *table_name; @@ -2891,10 +2891,15 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, thd->mem_root= &memex; grant_version++; - while ((Str = str_list++)) + while ((tmp_Str = str_list++)) { int error; GRANT_TABLE *grant_table; + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -3030,7 +3035,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, bool revoke_grant, bool no_error) { List_iterator str_list (user_list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; TABLE_LIST tables[2]; bool create_new_users=0, result=0; char *db_name, *table_name; @@ -3098,10 +3103,15 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, DBUG_PRINT("info",("now time to iterate and add users")); - while ((Str= str_list++)) + while ((tmp_Str= str_list++)) { int error; GRANT_NAME *grant_name; + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -3170,7 +3180,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, ulong rights, bool revoke_grant) { List_iterator str_list (list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; char tmp_db[NAME_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; @@ -3229,8 +3239,13 @@ bool mysql_grant(THD *thd, const char *db, List &list, grant_version++; int result=0; - while ((Str = str_list++)) + while ((tmp_Str = str_list++)) { + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -5187,7 +5202,7 @@ bool mysql_create_user(THD *thd, List &list) int result; String wrong_users; ulong sql_mode; - LEX_USER *user_name; + LEX_USER *user_name, *tmp_user_name; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_create_user"); @@ -5199,8 +5214,13 @@ bool mysql_create_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_name= user_list++)) + while ((tmp_user_name= user_list++)) { + if (!(user_name= get_current_user(thd, tmp_user_name))) + { + result= TRUE; + continue; + } /* Search all in-memory structures and grant tables for a mention of the new user name. @@ -5246,7 +5266,7 @@ bool mysql_drop_user(THD *thd, List &list) { int result; String wrong_users; - LEX_USER *user_name; + LEX_USER *user_name, *tmp_user_name; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_drop_user"); @@ -5258,8 +5278,14 @@ bool mysql_drop_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_name= user_list++)) + while ((tmp_user_name= user_list++)) { + user_name= get_current_user(thd, tmp_user_name); + if (!(user_name= get_current_user(thd, tmp_user_name))) + { + result= TRUE; + continue; + } if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { append_user(&wrong_users, user_name); @@ -5296,8 +5322,8 @@ bool mysql_rename_user(THD *thd, List &list) { int result; String wrong_users; - LEX_USER *user_from; - LEX_USER *user_to; + LEX_USER *user_from, *tmp_user_from; + LEX_USER *user_to, *tmp_user_to; List_iterator user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_rename_user"); @@ -5309,9 +5335,19 @@ bool mysql_rename_user(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_from= user_list++)) + while ((tmp_user_from= user_list++)) { - user_to= user_list++; + if (!(user_from= get_current_user(thd, tmp_user_from))) + { + result= TRUE; + continue; + } + tmp_user_to= user_list++; + if (!(user_to= get_current_user(thd, tmp_user_to))) + { + result= TRUE; + continue; + } DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ /* @@ -5366,10 +5402,15 @@ bool mysql_revoke_all(THD *thd, List &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - LEX_USER *lex_user; + LEX_USER *lex_user, *tmp_lex_user; List_iterator user_list(list); - while ((lex_user=user_list++)) + while ((tmp_lex_user= user_list++)) { + if (!(lex_user= get_current_user(thd, tmp_lex_user))) + { + result= -1; + continue; + } if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE)) { sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not " diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cd57c280950..fca453f9e8f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3887,11 +3887,13 @@ end_with_restore_list: if (thd->security_ctx->user) // If not replication { - LEX_USER *user; + LEX_USER *user, *tmp_user; List_iterator user_list(lex->users_list); - while ((user= user_list++)) + while ((tmp_user= user_list++)) { + if (!(user= get_current_user(thd, tmp_user))) + goto error; if (specialflag & SPECIAL_NO_RESOLVE && hostname_requires_resolving(user->host.str)) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, @@ -3973,9 +3975,13 @@ end_with_restore_list: if (lex->sql_command == SQLCOM_GRANT) { List_iterator str_list(lex->users_list); - LEX_USER *user; - while ((user=str_list++)) + LEX_USER *user, *tmp_user; + while ((tmp_user=str_list++)) + { + if (!(user= get_current_user(thd, tmp_user))) + goto error; reset_mqh(user); + } } } } @@ -4030,13 +4036,18 @@ end_with_restore_list: } #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: + { + LEX_USER *grant_user= get_current_user(thd, lex->grant_user); + if (!grant_user) + goto error; if ((thd->security_ctx->priv_user && - !strcmp(thd->security_ctx->priv_user, lex->grant_user->user.str)) || + !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) { - res = mysql_show_grants(thd,lex->grant_user); + res = mysql_show_grants(thd, grant_user); } break; + } #endif case SQLCOM_HA_OPEN: DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -7495,3 +7506,34 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) return definer; } + + +/* + Retuns information about user or current user. + + SYNOPSIS + get_current_user() + thd [in] thread handler + user [in] user + + RETURN + On success, return a valid pointer to initialized + LEX_USER, which contains user information. + On error, return 0. +*/ + +LEX_USER *get_current_user(THD *thd, LEX_USER *user) +{ + LEX_USER *curr_user; + if (!user->user.str) // current_user + { + if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER)); + return 0; + } + get_default_definer(thd, curr_user); + return curr_user; + } + return user; +} diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e45be1ef148..256b0b48c64 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6510,24 +6510,10 @@ show_param: { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_GRANTS; - THD *thd= lex->thd; - Security_context *sctx= thd->security_ctx; LEX_USER *curr_user; - if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user)))) YYABORT; - curr_user->user.str= sctx->priv_user; - curr_user->user.length= strlen(sctx->priv_user); - if (*sctx->priv_host != 0) - { - curr_user->host.str= sctx->priv_host; - curr_user->host.length= strlen(sctx->priv_host); - } - else - { - curr_user->host.str= (char *) "%"; - curr_user->host.length= 1; - } - curr_user->password=null_lex_str; + bzero(curr_user, sizeof(st_lex_user)); lex->grant_user= curr_user; } | GRANTS FOR_SYM user @@ -7477,22 +7463,14 @@ user: } | CURRENT_USER optional_braces { - THD *thd= YYTHD; - Security_context *sctx= thd->security_ctx; - if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) YYABORT; - $$->user.str= sctx->priv_user; - $$->user.length= strlen(sctx->priv_user); - if (*sctx->priv_host != 0) - { - $$->host.str= sctx->priv_host; - $$->host.length= strlen(sctx->priv_host); - } - else - { - $$->host.str= (char *) "%"; - $$->host.length= 1; - } + /* + empty LEX_USER means current_user and + will be handled in the get_current_user() function + later + */ + bzero($$, sizeof(LEX_USER)); }; /* Keyword that we allow for identifiers (except SP labels) */ From f9214221fc5a42f1f864b14046cdcebbff5a7d0e Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Thu, 29 Jun 2006 16:52:46 +0500 Subject: [PATCH 02/22] Bug#19671 mysql_list_fields returns incorrect table name for VIEWs After view onening real view db name and table name are placed into table_list->view_db & table_list->view_name. Item_field class does not handle these names properly during intialization of Send_field. The fix is to use new class 'Item_ident_for_show' which sets correct view db name and table name for Send_field. --- sql/item.cc | 13 ++++++++++++- sql/item.h | 22 ++++++++++++++++++++++ sql/sql_show.cc | 9 ++++++++- tests/mysql_client_test.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 24efc1f106f..e73a6044574 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1457,7 +1457,18 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, } - +void Item_ident_for_show::make_field(Send_field *tmp_field) +{ + tmp_field->table_name= tmp_field->org_table_name= table_name; + tmp_field->db_name= db_name; + tmp_field->col_name= tmp_field->org_col_name= field->field_name; + tmp_field->charsetnr= field->charset()->number; + tmp_field->length=field->field_length; + tmp_field->type=field->type(); + tmp_field->flags= field->table->maybe_null ? + (field->flags & ~NOT_NULL_FLAG) : field->flags; + tmp_field->decimals= 0; +} /**********************************************/ diff --git a/sql/item.h b/sql/item.h index 2cadfda6895..bee24d23245 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1142,6 +1142,28 @@ public: bool any_privileges); }; + +class Item_ident_for_show :public Item +{ +public: + Field *field; + const char *db_name; + const char *table_name; + + Item_ident_for_show(Field *par_field, const char *db_arg, + const char *table_name_arg) + :field(par_field), db_name(db_arg), table_name(table_name_arg) + {} + + enum Type type() const { return FIELD_ITEM; } + double val_real() { return field->val_real(); } + longlong val_int() { return field->val_int(); } + String *val_str(String *str) { return field->val_str(str); } + my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); } + void make_field(Send_field *tmp_field); +}; + + class Item_equal; class COND_EQUAL; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 60d50c415d5..71a6b0acde9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -582,7 +582,14 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) { if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name,wild)) - field_list.push_back(new Item_field(field)); + { + if (table_list->view) + field_list.push_back(new Item_ident_for_show(field, + table_list->view_db.str, + table_list->view_name.str)); + else + field_list.push_back(new Item_field(field)); + } } restore_record(table, s->default_values); // Get empty record if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS | diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 3876de58b0e..0f2847e0f63 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -8311,6 +8311,39 @@ static void test_list_fields() } +static void test_bug19671() +{ + MYSQL_RES *result; + int rc; + myheader("test_bug19671"); + + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + + rc= mysql_query(mysql, "drop view if exists v1"); + myquery(rc); + + rc= mysql_query(mysql, "create table t1(f1 int)"); + myquery(rc); + + rc= mysql_query(mysql, "create view v1 as select va.* from t1 va"); + myquery(rc); + + result= mysql_list_fields(mysql, "v1", NULL); + mytest(result); + + rc= my_process_result_set(result); + DIE_UNLESS(rc == 0); + + verify_prepare_field(result, 0, "f1", "f1", MYSQL_TYPE_LONG, + "v1", "v1", current_db, 11, "0"); + + mysql_free_result(result); + myquery(mysql_query(mysql, "drop view v1")); + myquery(mysql_query(mysql, "drop table t1")); +} + + /* Test a memory ovverun bug */ static void test_mem_overun() @@ -15195,6 +15228,7 @@ static struct my_tests_st my_tests[]= { { "test_bug15613", test_bug15613 }, { "test_bug14169", test_bug14169 }, { "test_bug17667", test_bug17667 }, + { "test_bug19671", test_bug19671}, { 0, 0 } }; From a230166f28099d947996c5e5d3e55eabbcfd202d Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Thu, 29 Jun 2006 18:39:34 +0500 Subject: [PATCH 03/22] Fix for bug#13934 Silent truncation of table comments Table comment: issue a warning(error in traditional mode) if length of comment > 60 symbols Column comment: issue a warning(error in traditional mode) if length of comment > 255 symbols Table 'comment' is changed from char* to LEX_STRING --- mysql-test/r/strict.result | 46 +++++++++++++++++++++++++++++++++++ mysql-test/t/strict.test | 39 ++++++++++++++++++++++++++++++ sql/handler.h | 3 ++- sql/sql_show.cc | 13 ++++++---- sql/sql_table.cc | 7 ++++-- sql/sql_yacc.yy | 2 +- sql/table.cc | 4 +++- sql/table.h | 2 +- sql/unireg.cc | 49 ++++++++++++++++++++++++++++++++++---- 9 files changed, 150 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 271cd7bf486..d0cf11d0511 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -1298,3 +1298,49 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t2,t1; set @@sql_mode= @org_mode; +set @@sql_mode='traditional'; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*123456789*'; +ERROR HY000: Too long comment for table 't1' +create table t1 ( +i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +ERROR HY000: Too long comment for field 'i' +set @@sql_mode= @org_mode; +create table t1 +(i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +Warnings: +Warning 1105 Unknown error +select column_name, column_comment from information_schema.columns where +table_schema = 'test' and table_name = 't1'; +column_name column_comment +i 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* +drop table t1; +set names utf8; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789*123456789*'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='123456789*123456789*123456789*123456789*123456789*123456789*' +drop table t1; diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index 5044a20ae9f..ce269b42ee9 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -1155,3 +1155,42 @@ create table t2 select date from t1; show create table t2; drop table t2,t1; set @@sql_mode= @org_mode; + +# +# Bug #13934 Silent truncation of table comments +# +set @@sql_mode='traditional'; +--error 1105 +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*123456789*'; +--error 1105 +create table t1 ( +i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +set @@sql_mode= @org_mode; +create table t1 +(i int comment + '123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); + +select column_name, column_comment from information_schema.columns where +table_schema = 'test' and table_name = 't1'; +drop table t1; + +set names utf8; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789*123456789*'; +show create table t1; +drop table t1; diff --git a/sql/handler.h b/sql/handler.h index 31aac075a5e..6efb6e9e470 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -428,7 +428,8 @@ typedef struct st_ha_create_information { CHARSET_INFO *table_charset, *default_table_charset; LEX_STRING connect_string; - const char *comment,*password; + LEX_STRING comment; + const char *password; const char *data_file_name, *index_file_name; const char *alias; ulonglong max_rows,min_rows; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 71a6b0acde9..34b5bdd142a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1080,10 +1080,10 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(ha_row_type[(uint) share->row_type]); } table->file->append_create_info(packet); - if (share->comment && share->comment[0]) + if (share->comment.length) { packet->append(STRING_WITH_LEN(" COMMENT=")); - append_unescaped(packet, share->comment, strlen(share->comment)); + append_unescaped(packet, share->comment.str, share->comment.length); } if (share->connect_string.length) { @@ -2547,11 +2547,14 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, (uint) (ptr-option_buff)-1), cs); { char *comment; - comment= show_table->file->update_table_comment(share->comment); + comment= show_table->file->update_table_comment(share->comment.str); if (comment) { - table->field[20]->store(comment, strlen(comment), cs); - if (comment != share->comment) + table->field[20]->store(comment, + (comment == share->comment.str ? + share->comment.length : + strlen(comment)), cs); + if (comment != share->comment.str) my_free(comment, MYF(0)); } } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 91c71193df2..1d69c69b5cf 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3598,8 +3598,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } create_info->db_type=new_db_type; - if (!create_info->comment) - create_info->comment= table->s->comment; + if (!create_info->comment.str) + { + create_info->comment.str= table->s->comment.str; + create_info->comment.length= table->s->comment.length; + } table->file->update_create_info(create_info); if ((create_info->table_options & diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 256b0b48c64..fc11157bdf7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2529,7 +2529,7 @@ create_table_option: | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ulong_num { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; } - | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } + | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } | AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} | PACK_KEYS_SYM opt_equal ulong_num { diff --git a/sql/table.cc b/sql/table.cc index 9ec9463c33c..1cace0d864d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -410,7 +410,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, int_length= uint2korr(head+274); share->null_fields= uint2korr(head+282); com_length= uint2korr(head+284); - share->comment= strdup_root(&outparam->mem_root, (char*) head+47); + share->comment.length= (int) (head[46]); + share->comment.str= strmake_root(&outparam->mem_root, (char*) head+47, + share->comment.length); DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length)); diff --git a/sql/table.h b/sql/table.h index ebb4481ef3a..d23d58e964f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -124,7 +124,7 @@ typedef struct st_table_share #endif uint *blob_field; /* Index to blobs in Field arrray*/ byte *default_values; /* row with default values */ - char *comment; /* Comment about table */ + LEX_STRING comment; /* Comment about table */ CHARSET_INFO *table_charset; /* Default charset of string fields */ /* A pair "database_name\0table_name\0", widely used as simply a db name */ diff --git a/sql/unireg.cc b/sql/unireg.cc index 0ab77462f61..3a139aea4c7 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -76,7 +76,7 @@ bool mysql_create_frm(THD *thd, my_string file_name, handler *db_file) { LEX_STRING str_db_type; - uint reclength,info_length,screens,key_info_length,maxlength; + uint reclength, info_length, screens, key_info_length, maxlength, tmp_len; ulong key_buff_length; File file; ulong filepos, data_offset; @@ -143,10 +143,30 @@ bool mysql_create_frm(THD *thd, my_string file_name, fileinfo[26]= (uchar) test((create_info->max_rows == 1) && (create_info->min_rows == 1) && (keys == 0)); int2store(fileinfo+28,key_info_length); - strmake((char*) forminfo+47,create_info->comment ? create_info->comment : "", - 60); - forminfo[46]=(uchar) strlen((char*)forminfo+47); // Length of comment + tmp_len= system_charset_info->cset->charpos(system_charset_info, + create_info->comment.str, + create_info->comment.str + + create_info->comment.length, 60); + if (tmp_len < create_info->comment.length) + { + char buff[128]; + (void) my_snprintf(buff, sizeof(buff), "Too long comment for table '%s'", + table); + if ((thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_message(ER_UNKNOWN_ERROR, buff, MYF(0)); + goto err; + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff); + create_info->comment.length= tmp_len; + } + + strmake((char*) forminfo+47, create_info->comment.str ? + create_info->comment.str : "", create_info->comment.length); + forminfo[46]=(uchar) create_info->comment.length; if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) || my_pwrite(file,(byte*) keybuff,key_info_length, (ulong) uint2korr(fileinfo+6),MYF_RW)) @@ -449,6 +469,27 @@ static bool pack_header(uchar *forminfo, enum db_type table_type, create_field *field; while ((field=it++)) { + + uint tmp_len= system_charset_info->cset->charpos(system_charset_info, + field->comment.str, + field->comment.str + + field->comment.length, 255); + if (tmp_len < field->comment.length) + { + char buff[128]; + (void) my_snprintf(buff,sizeof(buff), "Too long comment for field '%s'", + field->field_name); + if ((current_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_message(ER_UNKNOWN_ERROR, buff, MYF(0)); + DBUG_RETURN(1); + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff); + field->comment.length= tmp_len; + } + totlength+= field->length; com_length+= field->comment.length; if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY || From 1bcf6b1d0935ac24c4f7ba2109e45cbf7fadbe47 Mon Sep 17 00:00:00 2001 From: "kroki@mysql.com" <> Date: Fri, 30 Jun 2006 00:21:55 +0400 Subject: [PATCH 04/22] Bug#20230: routine_definition is not null SHOW CREATE PROCEDURE and SHOW CREATE FUNCTION are fixed as well as INFORMATION_SCHEMA.ROUTINES.ROUTINE_NAME. --- mysql-test/r/information_schema.result | 52 ++++++++++++++++++++++---- mysql-test/t/information_schema.test | 36 ++++++++++++++++++ sql/sp_head.cc | 18 +++++++-- sql/sql_show.cc | 3 +- 4 files changed, 96 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 64969fcdf44..a2feba7ad5d 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -294,26 +294,26 @@ show create function sub1; ERROR 42000: FUNCTION sub1 does not exist select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL grant all privileges on test.* to mysqltest_1@localhost; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL create function sub2(i int) returns int return i+1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL sub2 return i+1 show create procedure sel2; Procedure sql_mode Create Procedure -sel2 +sel2 NULL show create function sub1; Function sql_mode Create Function -sub1 +sub1 NULL show create function sub2; Function sql_mode Create Function sub2 CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11) @@ -1134,3 +1134,39 @@ concat(@a, table_name) @a table_name .t1 . t1 .t2 . t2 drop table t1,t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 RETURN @a + 1 +p1 SET @a= 1 +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +SET @a= 1 +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) +RETURN @a + 1 +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 NULL +p1 NULL +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 NULL +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 NULL +CALL p1(); +SELECT f1(); +f1() +2 +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 0bcd9ef8c0b..a2e19112cf9 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -852,3 +852,39 @@ create table t2(f1 char(5)); select concat(@a, table_name), @a, table_name from information_schema.tables where table_schema = 'test'; drop table t1,t2; + + +# +# Bug#20230: routine_definition is not null +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; + +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; + +connect (conn1, localhost, mysql_bug20230,,); + +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; +CALL p1(); +SELECT f1(); + +disconnect conn1; +connection default; + +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; + +# End of 5.0 tests. diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b3b99557b63..9965c48935a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1869,8 +1869,11 @@ sp_head::show_create_procedure(THD *thd) field_list.push_back(new Item_empty_string("Procedure", NAME_LEN)); field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len)); // 1024 is for not to confuse old clients - field_list.push_back(new Item_empty_string("Create Procedure", - max(buffer.length(), 1024))); + Item_empty_string *definition= + new Item_empty_string("Create Procedure", max(buffer.length(),1024)); + definition->maybe_null= TRUE; + field_list.push_back(definition); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); @@ -1879,6 +1882,8 @@ sp_head::show_create_procedure(THD *thd) protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); if (full_access) protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + else + protocol->store_null(); res= protocol->write(); send_eof(thd); @@ -1934,8 +1939,11 @@ sp_head::show_create_function(THD *thd) &sql_mode_len); field_list.push_back(new Item_empty_string("Function",NAME_LEN)); field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len)); - field_list.push_back(new Item_empty_string("Create Function", - max(buffer.length(),1024))); + Item_empty_string *definition= + new Item_empty_string("Create Function", max(buffer.length(),1024)); + definition->maybe_null= TRUE; + field_list.push_back(definition); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); @@ -1944,6 +1952,8 @@ sp_head::show_create_function(THD *thd) protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); if (full_access) protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + else + protocol->store_null(); res= protocol->write(); send_eof(thd); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 60d50c415d5..2c7a9b05cd9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2916,6 +2916,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, { get_field(thd->mem_root, proc_table->field[10], &tmp_string); table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); + table->field[7]->set_notnull(); } table->field[6]->store(STRING_WITH_LEN("SQL"), cs); table->field[10]->store(STRING_WITH_LEN("SQL"), cs); @@ -4069,7 +4070,7 @@ ST_FIELD_INFO proc_fields_info[]= {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0}, - {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0}, From 96bddcafe7072a9a709122b438499f765652a600 Mon Sep 17 00:00:00 2001 From: "kroki@mysql.com" <> Date: Fri, 30 Jun 2006 18:14:22 +0400 Subject: [PATCH 05/22] Bug#17226: Variable set in cursor on first iteration is assigned second iterations value During assignment to the BLOB variable in routine body the value wasn't copied. --- mysql-test/r/sp-vars.result | 15 +++++++++++++++ mysql-test/t/sp-vars.test | 36 ++++++++++++++++++++++++++++++++++++ sql/field_conv.cc | 11 ++++++++--- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index 6b4d7b1a6d3..83ee188bfa4 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -1075,3 +1075,18 @@ SELECT f1(); f1() abc DROP FUNCTION f1; +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE v_char VARCHAR(255); +DECLARE v_text TEXT DEFAULT ''; +SET v_char = 'abc'; +SET v_text = v_char; +SET v_char = 'def'; +SET v_text = concat(v_text, '|', v_char); +SELECT v_text; +END| +CALL p1(); +v_text +abc|def +DROP PROCEDURE p1; diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test index 81504904797..48dbd4de7aa 100644 --- a/mysql-test/t/sp-vars.test +++ b/mysql-test/t/sp-vars.test @@ -1271,3 +1271,39 @@ SELECT f1(); # DROP FUNCTION f1; + + +# +# Bug#17226: Variable set in cursor on first iteration is assigned +# second iterations value +# +# The problem was in incorrect handling of local variables of type +# TEXT (BLOB). +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + DECLARE v_char VARCHAR(255); + DECLARE v_text TEXT DEFAULT ''; + + SET v_char = 'abc'; + + SET v_text = v_char; + + SET v_char = 'def'; + + SET v_text = concat(v_text, '|', v_char); + + SELECT v_text; +END| +delimiter ;| + +CALL p1(); + +DROP PROCEDURE p1; + +# End of 5.0 tests. diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 4e977c06180..3200f2ca9b2 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -675,9 +675,14 @@ void field_conv(Field *to,Field *from) { // Be sure the value is stored Field_blob *blob=(Field_blob*) to; from->val_str(&blob->value); - if (!blob->value.is_alloced() && - from->real_type() != MYSQL_TYPE_STRING && - from->real_type() != MYSQL_TYPE_VARCHAR) + /* + Copy value if copy_blobs is set, or source is not a string and + we have a pointer to its internal string conversion buffer. + */ + if (to->table->copy_blobs || + (!blob->value.is_alloced() && + from->real_type() != MYSQL_TYPE_STRING && + from->real_type() != MYSQL_TYPE_VARCHAR)) blob->value.copy(); blob->store(blob->value.ptr(),blob->value.length(),from->charset()); return; From 41fea3d763a26f799f110bd6ede3dba9a7f53f04 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Sat, 1 Jul 2006 00:14:28 +0400 Subject: [PATCH 06/22] Remove a couple of unused/barely used names. --- sql/sql_lex.cc | 4 ---- sql/sql_lex.h | 3 --- sql/sql_parse.cc | 6 +++--- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 47af816f41d..7d4dca15608 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -41,8 +41,6 @@ sys_var_long_ptr trg_new_row_fake_var(0, 0); #define yySkip() lex->ptr++ #define yyLength() ((uint) (lex->ptr - lex->tok_start)-1) -pthread_key(LEX*,THR_LEX); - /* Longest standard keyword name */ #define TOCK_NAME_LENGTH 24 @@ -91,8 +89,6 @@ void lex_init(void) for (i=0 ; i < array_elements(sql_functions) ; i++) sql_functions[i].length=(uchar) strlen(sql_functions[i].name); - VOID(pthread_key_create(&THR_LEX,NULL)); - DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 285e1d6d5a6..356c64526fa 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1116,6 +1116,3 @@ extern void lex_start(THD *thd, uchar *buf,uint length); extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); -extern pthread_key(LEX*,THR_LEX); - -#define current_lex (current_thd->lex) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cd57c280950..0e21b848125 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2365,7 +2365,7 @@ static void reset_one_shot_variables(THD *thd) /* - Execute command saved in thd and current_lex->sql_command + Execute command saved in thd and lex->sql_command SYNOPSIS mysql_execute_command() @@ -5541,7 +5541,7 @@ bool check_stack_overrun(THD *thd, long margin, bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) { - LEX *lex=current_lex; + LEX *lex= current_thd->lex; ulong old_info=0; if ((uint) *yystacksize >= MY_YACC_MAX) return 1; @@ -5978,7 +5978,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, void store_position_for_column(const char *name) { - current_lex->last_field->after=my_const_cast(char*) (name); + current_thd->lex->last_field->after=my_const_cast(char*) (name); } bool From fbeb42a9e1a4406287897e8da5932fb012f7c0df Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Sat, 1 Jul 2006 00:33:47 +0400 Subject: [PATCH 07/22] Remove an unused variable. --- sql/item.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sql/item.h b/sql/item.h index 2cadfda6895..e2794a97ae3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -827,13 +827,6 @@ protected: public: LEX_STRING m_name; - /* - Buffer, pointing to the string value of the item. We need it to - protect internal buffer from changes. See comment to analogous - member in Item_param for more details. - */ - String str_value_ptr; - public: #ifndef DBUG_OFF /* From 8b319bb5c21e626caf55a625627f1a8e72a2afd2 Mon Sep 17 00:00:00 2001 From: "mikael@dator5.(none)" <> Date: Wed, 5 Jul 2006 12:57:23 -0400 Subject: [PATCH 08/22] BUG#20770: DATA DIRECTORY and INDEX DIRECTORY error when ALTER TABLE ADD/DROP/REORGANIZE partition Also some error in handling options for subpartitions. --- mysql-test/r/partition.result | 39 +++++++++++++++++++++++++++++++ mysql-test/t/partition.test | 43 +++++++++++++++++++++++++++++++++++ sql/ha_partition.cc | 23 ++++++++++++------- sql/ha_partition.h | 6 +++-- sql/sql_yacc.yy | 9 ++++---- 5 files changed, 106 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 8bb895386bf..26969d1ad5d 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1082,4 +1082,43 @@ a 2 1 drop table t1; +create table t1 (a int) engine myisam +partition by range (a) +subpartition by hash (a) +(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart00, SUBPARTITION subpart01)); +t1#P#p0#SP#subpart00.MYD +t1#P#p0#SP#subpart00.MYI +t1#P#p0#SP#subpart01.MYD +t1#P#p0#SP#subpart01.MYI +t1.frm +t1.par +t1#P#p0#SP#subpart00.MYD +t1#P#p0#SP#subpart01.MYD +t1#P#p0#SP#subpart00.MYI +t1#P#p0#SP#subpart01.MYI +ALTER TABLE t1 REORGANIZE PARTITION p0 INTO +(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart10, SUBPARTITION subpart11), +partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart20, SUBPARTITION subpart21)); +t1#P#p1#SP#subpart10.MYD +t1#P#p1#SP#subpart10.MYI +t1#P#p1#SP#subpart11.MYD +t1#P#p1#SP#subpart11.MYI +t1#P#p2#SP#subpart20.MYD +t1#P#p2#SP#subpart20.MYI +t1#P#p2#SP#subpart21.MYD +t1#P#p2#SP#subpart21.MYI +t1.frm +t1.par +t1#P#p1#SP#subpart10.MYD +t1#P#p1#SP#subpart11.MYD +t1#P#p2#SP#subpart20.MYD +t1#P#p2#SP#subpart21.MYD +t1#P#p1#SP#subpart10.MYI +t1#P#p1#SP#subpart11.MYI +t1#P#p2#SP#subpart20.MYI +t1#P#p2#SP#subpart21.MYI +drop table t1; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 04519800ff6..1c606c47183 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1261,4 +1261,47 @@ insert into t1 values (1),(2); select * from t1 ORDER BY a DESC; drop table t1; +# +# Bug 20770 Partitions: DATA DIRECTORY clause change in reorganize +# doesn't remove old directory +# +--disable_query_log +--exec mkdir $MYSQLTEST_VARDIR/master-data/tmpdata || true +eval SET @data_dir = 'DATA DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpdata'''; +let $data_directory = `select @data_dir`; + +--exec mkdir $MYSQLTEST_VARDIR/master-data/tmpinx || true +eval SET @inx_dir = 'INDEX DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpinx'''; +let $inx_directory = `select @inx_dir`; +--enable_query_log + +--replace_result $MYSQLTEST_VARDIR "hello" +eval create table t1 (a int) engine myisam +partition by range (a) +subpartition by hash (a) +(partition p0 VALUES LESS THAN (1) $data_directory $inx_directory + (SUBPARTITION subpart00, SUBPARTITION subpart01)); + +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/test || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx || true +--replace_result $MYSQLTEST_VARDIR "hello" + +eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO +(partition p1 VALUES LESS THAN (1) $data_directory $inx_directory + (SUBPARTITION subpart10, SUBPARTITION subpart11), + partition p2 VALUES LESS THAN (2) $data_directory $inx_directory + (SUBPARTITION subpart20, SUBPARTITION subpart21)); + +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/test || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx || true + +drop table t1; --echo End of 5.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..85b02553be4 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1125,13 +1125,15 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, int ha_partition::prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, - handler *file, const char *part_name) + handler *file, const char *part_name, + partition_element *p_elem) { int error; bool create_flag= FALSE; bool open_flag= FALSE; DBUG_ENTER("prepare_new_partition"); + set_up_table_before_create(table, part_name, create_info, 0, p_elem); if ((error= file->create(part_name, table, create_info))) goto error; create_flag= TRUE; @@ -1420,7 +1422,8 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_PRINT("info", ("Add subpartition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[part], - (const char *)part_name_buff))) + (const char *)part_name_buff, + sub_elem))) { cleanup_new_partition(part_count); DBUG_RETURN(error); @@ -1436,7 +1439,8 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], - (const char *)part_name_buff))) + (const char *)part_name_buff, + part_elem))) { cleanup_new_partition(part_count); DBUG_RETURN(error); @@ -1648,7 +1652,7 @@ uint ha_partition::del_ren_cre_table(const char *from, error= (*file)->delete_table((const char*) from_buff); else { - set_up_table_before_create(table_arg, from_buff, create_info, i); + set_up_table_before_create(table_arg, from_buff, create_info, i, NULL); error= (*file)->create(from_buff, table_arg, create_info); } name_buffer_ptr= strend(name_buffer_ptr) + 1; @@ -1724,12 +1728,15 @@ partition_element *ha_partition::find_partition_element(uint part_id) void ha_partition::set_up_table_before_create(TABLE *table, const char *partition_name_with_path, HA_CREATE_INFO *info, - uint part_id) + uint part_id, + partition_element *part_elem) { - partition_element *part_elem= find_partition_element(part_id); - if (!part_elem) - return; // Fatal error + { + part_elem= find_partition_element(part_id); + if (!part_elem) + return; // Fatal error + } table->s->max_rows= part_elem->part_max_rows; table->s->min_rows= part_elem->part_min_rows; const char *partition_name= strrchr(partition_name_with_path, FN_LIBCHAR); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4c627cd50f8..cbf87ae3a92 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -202,7 +202,8 @@ private: int copy_partitions(ulonglong *copied, ulonglong *deleted); void cleanup_new_partition(uint part_count); int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, - handler *file, const char *part_name); + handler *file, const char *part_name, + partition_element *p_elem); /* delete_table, rename_table and create uses very similar logic which is packed into this routine. @@ -222,7 +223,8 @@ private: void set_up_table_before_create(TABLE *table_arg, const char *partition_name_with_path, HA_CREATE_INFO *info, - uint part_id); + uint part_id, + partition_element *p_elem); partition_element *find_partition_element(uint part_id); public: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0632e2298cd..0001676aab4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3716,14 +3716,15 @@ sub_part_definition: { LEX *lex= Lex; partition_info *part_info= lex->part_info; - partition_element *p_elem= new partition_element(); - if (!p_elem || - part_info->current_partition->subpartitions.push_back(p_elem)) + partition_element *curr_part= part_info->current_partition; + partition_element *sub_p_elem= new partition_element(curr_part); + if (!sub_p_elem || + curr_part->subpartitions.push_back(sub_p_elem)) { mem_alloc_error(sizeof(partition_element)); YYABORT; } - part_info->curr_part_elem= p_elem; + part_info->curr_part_elem= sub_p_elem; part_info->use_default_subpartitions= FALSE; part_info->use_default_no_subpartitions= FALSE; part_info->count_curr_subparts++; From 854cdc9b35d2d4e7c0a830a3cc6dd3370a67d4f6 Mon Sep 17 00:00:00 2001 From: "mikael@dator5.(none)" <> Date: Wed, 5 Jul 2006 16:06:51 -0400 Subject: [PATCH 09/22] BUG#20770: Added some more test cases --- mysql-test/r/partition_range.result | 112 ++++++++++++++++++++++++++++ mysql-test/t/partition_range.test | 87 +++++++++++++++++++++ 2 files changed, 199 insertions(+) diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 3cbb517053a..9123c894f32 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -519,3 +519,115 @@ partition p3 values less than (1998), partition p4 values less than (1999), partition p5 values less than (2000)); drop table t1; +CREATE TABLE t1 (a date) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION p3xx VALUES LESS THAN (TO_DAYS('2004-01-01')), +PARTITION p401 VALUES LESS THAN (TO_DAYS('2004-02-01')), +PARTITION p402 VALUES LESS THAN (TO_DAYS('2004-03-01')), +PARTITION p403 VALUES LESS THAN (TO_DAYS('2004-04-01')), +PARTITION p404 VALUES LESS THAN (TO_DAYS('2004-05-01')), +PARTITION p405 VALUES LESS THAN (TO_DAYS('2004-06-01')), +PARTITION p406 VALUES LESS THAN (TO_DAYS('2004-07-01')), +PARTITION p407 VALUES LESS THAN (TO_DAYS('2004-08-01')), +PARTITION p408 VALUES LESS THAN (TO_DAYS('2004-09-01')), +PARTITION p409 VALUES LESS THAN (TO_DAYS('2004-10-01')), +PARTITION p410 VALUES LESS THAN (TO_DAYS('2004-11-01')), +PARTITION p411 VALUES LESS THAN (TO_DAYS('2004-12-01')), +PARTITION p412 VALUES LESS THAN (TO_DAYS('2005-01-01')), +PARTITION p501 VALUES LESS THAN (TO_DAYS('2005-02-01')), +PARTITION p502 VALUES LESS THAN (TO_DAYS('2005-03-01')), +PARTITION p503 VALUES LESS THAN (TO_DAYS('2005-04-01')), +PARTITION p504 VALUES LESS THAN (TO_DAYS('2005-05-01')), +PARTITION p505 VALUES LESS THAN (TO_DAYS('2005-06-01')), +PARTITION p506 VALUES LESS THAN (TO_DAYS('2005-07-01')), +PARTITION p507 VALUES LESS THAN (TO_DAYS('2005-08-01')), +PARTITION p508 VALUES LESS THAN (TO_DAYS('2005-09-01')), +PARTITION p509 VALUES LESS THAN (TO_DAYS('2005-10-01')), +PARTITION p510 VALUES LESS THAN (TO_DAYS('2005-11-01')), +PARTITION p511 VALUES LESS THAN (TO_DAYS('2005-12-01')), +PARTITION p512 VALUES LESS THAN (TO_DAYS('2006-01-01')), +PARTITION p601 VALUES LESS THAN (TO_DAYS('2006-02-01')), +PARTITION p602 VALUES LESS THAN (TO_DAYS('2006-03-01')), +PARTITION p603 VALUES LESS THAN (TO_DAYS('2006-04-01')), +PARTITION p604 VALUES LESS THAN (TO_DAYS('2006-05-01')), +PARTITION p605 VALUES LESS THAN (TO_DAYS('2006-06-01')), +PARTITION p606 VALUES LESS THAN (TO_DAYS('2006-07-01')), +PARTITION p607 VALUES LESS THAN (TO_DAYS('2006-08-01'))); +INSERT INTO t1 VALUES ('2003-01-13'),('2003-06-20'),('2003-08-30'); +INSERT INTO t1 VALUES ('2003-04-13'),('2003-07-20'),('2003-10-30'); +INSERT INTO t1 VALUES ('2003-05-13'),('2003-11-20'),('2003-12-30'); +INSERT INTO t1 VALUES ('2004-01-13'),('2004-01-20'),('2004-01-30'); +INSERT INTO t1 VALUES ('2004-02-13'),('2004-02-20'),('2004-02-28'); +INSERT INTO t1 VALUES ('2004-03-13'),('2004-03-20'),('2004-03-30'); +INSERT INTO t1 VALUES ('2004-04-13'),('2004-04-20'),('2004-04-30'); +INSERT INTO t1 VALUES ('2004-05-13'),('2004-05-20'),('2004-05-30'); +INSERT INTO t1 VALUES ('2004-06-13'),('2004-06-20'),('2004-06-30'); +INSERT INTO t1 VALUES ('2004-07-13'),('2004-07-20'),('2004-07-30'); +INSERT INTO t1 VALUES ('2004-08-13'),('2004-08-20'),('2004-08-30'); +INSERT INTO t1 VALUES ('2004-09-13'),('2004-09-20'),('2004-09-30'); +INSERT INTO t1 VALUES ('2004-10-13'),('2004-10-20'),('2004-10-30'); +INSERT INTO t1 VALUES ('2004-11-13'),('2004-11-20'),('2004-11-30'); +INSERT INTO t1 VALUES ('2004-12-13'),('2004-12-20'),('2004-12-30'); +INSERT INTO t1 VALUES ('2005-01-13'),('2005-01-20'),('2005-01-30'); +INSERT INTO t1 VALUES ('2005-02-13'),('2005-02-20'),('2005-02-28'); +INSERT INTO t1 VALUES ('2005-03-13'),('2005-03-20'),('2005-03-30'); +INSERT INTO t1 VALUES ('2005-04-13'),('2005-04-20'),('2005-04-30'); +INSERT INTO t1 VALUES ('2005-05-13'),('2005-05-20'),('2005-05-30'); +INSERT INTO t1 VALUES ('2005-06-13'),('2005-06-20'),('2005-06-30'); +INSERT INTO t1 VALUES ('2005-07-13'),('2005-07-20'),('2005-07-30'); +INSERT INTO t1 VALUES ('2005-08-13'),('2005-08-20'),('2005-08-30'); +INSERT INTO t1 VALUES ('2005-09-13'),('2005-09-20'),('2005-09-30'); +INSERT INTO t1 VALUES ('2005-10-13'),('2005-10-20'),('2005-10-30'); +INSERT INTO t1 VALUES ('2005-11-13'),('2005-11-20'),('2005-11-30'); +INSERT INTO t1 VALUES ('2005-12-13'),('2005-12-20'),('2005-12-30'); +INSERT INTO t1 VALUES ('2006-01-13'),('2006-01-20'),('2006-01-30'); +INSERT INTO t1 VALUES ('2006-02-13'),('2006-02-20'),('2006-02-28'); +INSERT INTO t1 VALUES ('2006-03-13'),('2006-03-20'),('2006-03-30'); +INSERT INTO t1 VALUES ('2006-04-13'),('2006-04-20'),('2006-04-30'); +INSERT INTO t1 VALUES ('2006-05-13'),('2006-05-20'),('2006-05-30'); +INSERT INTO t1 VALUES ('2006-06-13'),('2006-06-20'),('2006-06-30'); +INSERT INTO t1 VALUES ('2006-07-13'),('2006-07-20'),('2006-07-30'); +SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +a +2004-07-13 +2004-07-20 +2004-07-30 +2004-08-13 +2004-08-20 +2004-08-30 +2004-09-13 +2004-09-20 +2004-09-30 +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where +SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR +(a >= '2005-07-01' AND a <= '2005-09-30'); +a +2004-07-13 +2004-07-20 +2004-07-30 +2004-08-13 +2004-08-20 +2004-08-30 +2004-09-13 +2004-09-20 +2004-09-30 +2005-07-13 +2005-07-20 +2005-07-30 +2005-08-13 +2005-08-20 +2005-08-30 +2005-09-13 +2005-09-20 +2005-09-30 +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'); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where +DROP TABLE t1; diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 8e1e2e72e69..38142a9d485 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -555,3 +555,90 @@ reorganize partition p5 into drop table t1; +# +# New test cases for date based partitioning +# +CREATE TABLE t1 (a date) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION p3xx VALUES LESS THAN (TO_DAYS('2004-01-01')), + PARTITION p401 VALUES LESS THAN (TO_DAYS('2004-02-01')), + PARTITION p402 VALUES LESS THAN (TO_DAYS('2004-03-01')), + PARTITION p403 VALUES LESS THAN (TO_DAYS('2004-04-01')), + PARTITION p404 VALUES LESS THAN (TO_DAYS('2004-05-01')), + PARTITION p405 VALUES LESS THAN (TO_DAYS('2004-06-01')), + PARTITION p406 VALUES LESS THAN (TO_DAYS('2004-07-01')), + PARTITION p407 VALUES LESS THAN (TO_DAYS('2004-08-01')), + PARTITION p408 VALUES LESS THAN (TO_DAYS('2004-09-01')), + PARTITION p409 VALUES LESS THAN (TO_DAYS('2004-10-01')), + PARTITION p410 VALUES LESS THAN (TO_DAYS('2004-11-01')), + PARTITION p411 VALUES LESS THAN (TO_DAYS('2004-12-01')), + PARTITION p412 VALUES LESS THAN (TO_DAYS('2005-01-01')), + PARTITION p501 VALUES LESS THAN (TO_DAYS('2005-02-01')), + PARTITION p502 VALUES LESS THAN (TO_DAYS('2005-03-01')), + PARTITION p503 VALUES LESS THAN (TO_DAYS('2005-04-01')), + PARTITION p504 VALUES LESS THAN (TO_DAYS('2005-05-01')), + PARTITION p505 VALUES LESS THAN (TO_DAYS('2005-06-01')), + PARTITION p506 VALUES LESS THAN (TO_DAYS('2005-07-01')), + PARTITION p507 VALUES LESS THAN (TO_DAYS('2005-08-01')), + PARTITION p508 VALUES LESS THAN (TO_DAYS('2005-09-01')), + PARTITION p509 VALUES LESS THAN (TO_DAYS('2005-10-01')), + PARTITION p510 VALUES LESS THAN (TO_DAYS('2005-11-01')), + PARTITION p511 VALUES LESS THAN (TO_DAYS('2005-12-01')), + PARTITION p512 VALUES LESS THAN (TO_DAYS('2006-01-01')), + PARTITION p601 VALUES LESS THAN (TO_DAYS('2006-02-01')), + PARTITION p602 VALUES LESS THAN (TO_DAYS('2006-03-01')), + PARTITION p603 VALUES LESS THAN (TO_DAYS('2006-04-01')), + PARTITION p604 VALUES LESS THAN (TO_DAYS('2006-05-01')), + PARTITION p605 VALUES LESS THAN (TO_DAYS('2006-06-01')), + PARTITION p606 VALUES LESS THAN (TO_DAYS('2006-07-01')), + PARTITION p607 VALUES LESS THAN (TO_DAYS('2006-08-01'))); + +INSERT INTO t1 VALUES ('2003-01-13'),('2003-06-20'),('2003-08-30'); +INSERT INTO t1 VALUES ('2003-04-13'),('2003-07-20'),('2003-10-30'); +INSERT INTO t1 VALUES ('2003-05-13'),('2003-11-20'),('2003-12-30'); + +INSERT INTO t1 VALUES ('2004-01-13'),('2004-01-20'),('2004-01-30'); +INSERT INTO t1 VALUES ('2004-02-13'),('2004-02-20'),('2004-02-28'); +INSERT INTO t1 VALUES ('2004-03-13'),('2004-03-20'),('2004-03-30'); +INSERT INTO t1 VALUES ('2004-04-13'),('2004-04-20'),('2004-04-30'); +INSERT INTO t1 VALUES ('2004-05-13'),('2004-05-20'),('2004-05-30'); +INSERT INTO t1 VALUES ('2004-06-13'),('2004-06-20'),('2004-06-30'); +INSERT INTO t1 VALUES ('2004-07-13'),('2004-07-20'),('2004-07-30'); +INSERT INTO t1 VALUES ('2004-08-13'),('2004-08-20'),('2004-08-30'); +INSERT INTO t1 VALUES ('2004-09-13'),('2004-09-20'),('2004-09-30'); +INSERT INTO t1 VALUES ('2004-10-13'),('2004-10-20'),('2004-10-30'); +INSERT INTO t1 VALUES ('2004-11-13'),('2004-11-20'),('2004-11-30'); +INSERT INTO t1 VALUES ('2004-12-13'),('2004-12-20'),('2004-12-30'); + +INSERT INTO t1 VALUES ('2005-01-13'),('2005-01-20'),('2005-01-30'); +INSERT INTO t1 VALUES ('2005-02-13'),('2005-02-20'),('2005-02-28'); +INSERT INTO t1 VALUES ('2005-03-13'),('2005-03-20'),('2005-03-30'); +INSERT INTO t1 VALUES ('2005-04-13'),('2005-04-20'),('2005-04-30'); +INSERT INTO t1 VALUES ('2005-05-13'),('2005-05-20'),('2005-05-30'); +INSERT INTO t1 VALUES ('2005-06-13'),('2005-06-20'),('2005-06-30'); +INSERT INTO t1 VALUES ('2005-07-13'),('2005-07-20'),('2005-07-30'); +INSERT INTO t1 VALUES ('2005-08-13'),('2005-08-20'),('2005-08-30'); +INSERT INTO t1 VALUES ('2005-09-13'),('2005-09-20'),('2005-09-30'); +INSERT INTO t1 VALUES ('2005-10-13'),('2005-10-20'),('2005-10-30'); +INSERT INTO t1 VALUES ('2005-11-13'),('2005-11-20'),('2005-11-30'); +INSERT INTO t1 VALUES ('2005-12-13'),('2005-12-20'),('2005-12-30'); + +INSERT INTO t1 VALUES ('2006-01-13'),('2006-01-20'),('2006-01-30'); +INSERT INTO t1 VALUES ('2006-02-13'),('2006-02-20'),('2006-02-28'); +INSERT INTO t1 VALUES ('2006-03-13'),('2006-03-20'),('2006-03-30'); +INSERT INTO t1 VALUES ('2006-04-13'),('2006-04-20'),('2006-04-30'); +INSERT INTO t1 VALUES ('2006-05-13'),('2006-05-20'),('2006-05-30'); +INSERT INTO t1 VALUES ('2006-06-13'),('2006-06-20'),('2006-06-30'); +INSERT INTO t1 VALUES ('2006-07-13'),('2006-07-20'),('2006-07-30'); + +SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR + (a >= '2005-07-01' AND a <= '2005-09-30'); +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; From 65979719c77878c205994284000d820935e9d26d Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 10 Jul 2006 17:08:42 -0400 Subject: [PATCH 10/22] BUG#20893: Valgrind error --- mysql-test/r/partition_mgm.result | 12 ++++++++++++ mysql-test/t/partition_mgm.test | 16 +++++++++++++++- sql/ha_partition.cc | 15 +++++++++++---- sql/ha_partition.h | 1 + 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/partition_mgm.result b/mysql-test/r/partition_mgm.result index 0f2c8c57872..f64ffaff495 100644 --- a/mysql-test/r/partition_mgm.result +++ b/mysql-test/r/partition_mgm.result @@ -24,3 +24,15 @@ hello/master-data/test/t1#P#p0.MYD hello/master-data/test/t1#P#p0.MYI hello/master-data/test/t1.frm hello/master-data/test/t1.par +drop table t1; +create table t1 (a int) +partition by list (a) +subpartition by hash (a) +(partition p11 values in (1,2), +partition p12 values in (3,4)); +alter table t1 REORGANIZE partition p11, p12 INTO +(partition p1 values in (1,2,3,4)); +alter table t1 REORGANIZE partition p1 INTO +(partition p11 values in (1,2), +partition p12 values in (3,4)); +drop table t1; diff --git a/mysql-test/t/partition_mgm.test b/mysql-test/t/partition_mgm.test index cfb76192de4..39512de154f 100644 --- a/mysql-test/t/partition_mgm.test +++ b/mysql-test/t/partition_mgm.test @@ -12,7 +12,21 @@ ALTER TABLE t1 COALESCE PARTITION 1; SHOW CREATE TABLE t1; --replace_result $MYSQLTEST_VARDIR "hello" --exec ls $MYSQLTEST_VARDIR/master-data/test/t1* +drop table t1; +# +# Bug 20767: REORGANIZE partition crashes +# +create table t1 (a int) +partition by list (a) +subpartition by hash (a) +(partition p11 values in (1,2), + partition p12 values in (3,4)); +alter table t1 REORGANIZE partition p11, p12 INTO +(partition p1 values in (1,2,3,4)); +alter table t1 REORGANIZE partition p1 INTO +(partition p11 values in (1,2), + partition p12 values in (3,4)); - +drop table t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..1ee1c1b51cf 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -204,6 +204,7 @@ void ha_partition::init_handler_variables() m_name_buffer_ptr= NULL; m_engine_array= NULL; m_file= NULL; + m_file_tot_parts= 0; m_reorged_file= NULL; m_new_file= NULL; m_reorged_parts= 0; @@ -1231,7 +1232,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, uint no_parts= m_part_info->partitions.elements; uint no_subparts= m_part_info->no_subparts; uint i= 0; - uint no_remain_partitions, part_count; + uint no_remain_partitions, part_count, orig_count; handler **new_file_array; int error= 1; bool first; @@ -1266,10 +1267,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, } while (++i < no_parts); } if (m_reorged_parts && - !(m_reorged_file= (handler**)sql_calloc(sizeof(partition_element*)* + !(m_reorged_file= (handler**)sql_calloc(sizeof(handler*)* (m_reorged_parts + 1)))) { - mem_alloc_error(sizeof(partition_element*)*(m_reorged_parts+1)); + mem_alloc_error(sizeof(handler*)*(m_reorged_parts+1)); DBUG_RETURN(ER_OUTOFMEMORY); } @@ -1340,6 +1341,7 @@ 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); memcpy((void*)m_reorged_file, &m_file[i*no_subparts], sizeof(handler*)*m_reorged_parts*no_subparts); } @@ -1353,15 +1355,18 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, */ i= 0; part_count= 0; + orig_count= 0; part_it.rewind(); do { partition_element *part_elem= part_it++; if (part_elem->part_state == PART_NORMAL) { - memcpy((void*)&new_file_array[part_count], (void*)&m_file[i], + DBUG_ASSERT(orig_count + no_subparts <= m_file_tot_parts); + memcpy((void*)&new_file_array[part_count], (void*)&m_file[orig_count], sizeof(handler*)*no_subparts); part_count+= no_subparts; + orig_count+= no_subparts; } else if (part_elem->part_state == PART_CHANGED || part_elem->part_state == PART_TO_BE_ADDED) @@ -1959,6 +1964,7 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) if (!(m_file= (handler **) alloc_root(mem_root, alloc_len))) DBUG_RETURN(TRUE); + m_file_tot_parts= m_tot_parts; bzero((char*) m_file, alloc_len); for (i= 0; i < m_tot_parts; i++) { @@ -2008,6 +2014,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root) mem_alloc_error(alloc_len); goto error_end; } + m_file_tot_parts= m_tot_parts; bzero((char*) m_file, alloc_len); DBUG_ASSERT(m_part_info->no_parts > 0); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4c627cd50f8..73ec7f60df5 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -55,6 +55,7 @@ private: char *m_name_buffer_ptr; // Pointer to first partition name handlerton **m_engine_array; // Array of types of the handlers handler **m_file; // Array of references to handler inst. + uint m_file_tot_parts; // Debug handler **m_new_file; // Array of references to new handlers handler **m_reorged_file; // Reorganised partitions handler **m_added_file; // Added parts kept for errors From 6af016ba8a6e48c2c23bc500feedd37c271a5a2d Mon Sep 17 00:00:00 2001 From: "pekka@orca.ndb.mysql.com" <> Date: Tue, 11 Jul 2006 17:07:23 +0200 Subject: [PATCH 11/22] ndb - (4.1) trivial fix to error.log (wday=0 was printed as "x") --- ndb/src/kernel/error/TimeModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/kernel/error/TimeModule.cpp b/ndb/src/kernel/error/TimeModule.cpp index 4bd8e3daf99..c4e569e7221 100644 --- a/ndb/src/kernel/error/TimeModule.cpp +++ b/ndb/src/kernel/error/TimeModule.cpp @@ -22,7 +22,7 @@ static const char* cMonth[] = { "x", "January", "February", "Mars", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; -static const char* cDay[] = { "x", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", +static const char* cDay[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; static const char* cHour[] = { "00","01","02","03","04","05","06","07","08","09","10","11","12", From e9ba287dc7754781b7504190793a7a0fbb8bfcc2 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Wed, 12 Jul 2006 20:38:17 -0400 Subject: [PATCH 12/22] BUG#20852: Using update with full table scan causes mysqld to enter an eternal loop --- mysql-test/r/partition_innodb.result | 11 +++++++++++ mysql-test/t/partition_innodb.test | 13 +++++++++++++ sql/ha_partition.cc | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 5e5931fdbf8..73745aad58b 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -107,3 +107,14 @@ select * from t1 where id = 'aaa'; id aaa drop table t1; +create table t1 (a int, b int, primary key (b,a)) +engine = innodb +partition by hash (a); +insert into t1 values (0, 0); +insert into t1 values (1, 0); +update t1 set b = b + 1 where a = 1; +select * from t1; +a b +0 0 +1 1 +drop table t1; diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 51f5b0fec01..e40d9fffbf8 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -78,3 +78,16 @@ select * from t1 where id = 'a'; select * from t1 where id = 'aa'; select * from t1 where id = 'aaa'; drop table t1; + +# +# Bug #20852 Partitions: Crash if hash innodb, composite primary key +# +create table t1 (a int, b int, primary key (b,a)) +engine = innodb +partition by hash (a); +insert into t1 values (0, 0); +insert into t1 values (1, 0); +update t1 set b = b + 1 where a = 1; +select * from t1; +drop table t1; + diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..a02971f9f66 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2229,7 +2229,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_table_flags&= ~(HA_CAN_GEOMETRY | HA_CAN_FULLTEXT | HA_DUPLICATE_POS | HA_CAN_SQL_HANDLER | HA_CAN_INSERT_DELAYED); m_table_flags|= HA_FILE_BASED | HA_REC_NOT_IN_SEQ; - + key_used_on_scan= m_file[0]->key_used_on_scan; + implicit_emptied= m_file[0]->implicit_emptied; /* Add 2 bytes for partition id in position ref length. ref_length=max_in_all_partitions(ref_length) + PARTITION_BYTES_IN_POS From 231565c206b3a83005b020c14f87f03aaf8ccb76 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.local" <> Date: Sat, 15 Jul 2006 03:08:56 +0400 Subject: [PATCH 13/22] Fix information_schema.result after a manual merge. --- mysql-test/r/information_schema.result | 54 ++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 363c5296a1b..a472aa0c68d 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -310,26 +310,26 @@ show create function sub1; ERROR 42000: FUNCTION sub1 does not exist select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL grant all privileges on test.* to mysqltest_1@localhost; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL create function sub2(i int) returns int return i+1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL sub2 return i+1 show create procedure sel2; Procedure sql_mode Create Procedure -sel2 +sel2 NULL show create function sub1; Function sql_mode Create Function -sub1 +sub1 NULL show create function sub2; Function sql_mode Create Function sub2 CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11) @@ -1182,6 +1182,43 @@ concat(@a, table_name) @a table_name .t1 . t1 .t2 . t2 drop table t1,t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 RETURN @a + 1 +p1 SET @a= 1 +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +SET @a= 1 +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) +RETURN @a + 1 +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 NULL +p1 NULL +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 NULL +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 NULL +CALL p1(); +SELECT f1(); +f1() +2 +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; +End of 5.0 tests. select * from information_schema.engines WHERE ENGINE="MyISAM"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO @@ -1190,3 +1227,4 @@ select user,db from information_schema.processlist; user db user3148 test drop user user3148@localhost; +End of 5.1 tests. From cfc65ef720dba90fbc9b81a214a5dc0b8e053105 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Sat, 15 Jul 2006 03:38:34 -0400 Subject: [PATCH 14/22] BUG#20389: Crash when using index scan in reverse order --- mysql-test/r/partition_order.result | 56 +++++++++++++++++++++++++++-- mysql-test/t/partition_order.test | 20 +++++++++-- sql/ha_myisam.cc | 3 +- sql/ha_partition.cc | 30 +++++++++++----- sql/ha_partition.h | 5 +-- 5 files changed, 99 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/partition_order.result b/mysql-test/r/partition_order.result index 7a1ab1d6dc8..78ff7cd3121 100644 --- a/mysql-test/r/partition_order.result +++ b/mysql-test/r/partition_order.result @@ -718,7 +718,11 @@ partitions 2 partition x2 values less than (100)); INSERT into t1 values (1, 1); INSERT into t1 values (5, NULL); -INSERT into t1 values (2, 5); +INSERT into t1 values (2, 4); +INSERT into t1 values (3, 3); +INSERT into t1 values (4, 5); +INSERT into t1 values (7, 1); +INSERT into t1 values (6, 6); INSERT into t1 values (30, 4); INSERT into t1 values (35, 2); INSERT into t1 values (40, NULL); @@ -727,7 +731,55 @@ a b 5 NULL 40 NULL 1 1 +7 1 35 2 +3 3 +2 4 30 4 -2 5 +4 5 +6 6 +select * from t1 force index (b) where b < 10 ORDER BY b; +a b +1 1 +7 1 +35 2 +3 3 +2 4 +30 4 +4 5 +6 6 +select * from t1 force index (b) where b < 10 ORDER BY b DESC; +a b +6 6 +4 5 +2 4 +30 4 +3 3 +35 2 +7 1 +1 1 +drop table t1; +create table t1 (a int not null, b int, c varchar(20), key (a,b,c)) +partition by range (b) +(partition p0 values less than (5), +partition p1 values less than (10)); +INSERT into t1 values (1,1,'1'),(2,2,'2'),(1,3,'3'),(2,4,'4'),(1,5,'5'); +INSERT into t1 values (2,6,'6'),(1,7,'7'),(2,8,'8'),(1,9,'9'); +INSERT into t1 values (1, NULL, NULL), (2, NULL, '10'); +select * from t1 where a = 1 order by a desc, b desc; +a b c +1 9 9 +1 7 7 +1 5 5 +1 3 3 +1 1 1 +1 NULL NULL +select * from t1 where a = 1 order by b desc; +a b c +1 9 9 +1 7 7 +1 5 5 +1 3 3 +1 1 1 +1 NULL NULL drop table t1; diff --git a/mysql-test/t/partition_order.test b/mysql-test/t/partition_order.test index 1e1b3339d64..ad956361d00 100644 --- a/mysql-test/t/partition_order.test +++ b/mysql-test/t/partition_order.test @@ -818,11 +818,27 @@ partitions 2 # Insert a couple of tuples INSERT into t1 values (1, 1); INSERT into t1 values (5, NULL); -INSERT into t1 values (2, 5); +INSERT into t1 values (2, 4); +INSERT into t1 values (3, 3); +INSERT into t1 values (4, 5); +INSERT into t1 values (7, 1); +INSERT into t1 values (6, 6); INSERT into t1 values (30, 4); INSERT into t1 values (35, 2); INSERT into t1 values (40, NULL); select * from t1 force index (b) where b < 10 OR b IS NULL order by b; - +select * from t1 force index (b) where b < 10 ORDER BY b; +select * from t1 force index (b) where b < 10 ORDER BY b DESC; +drop table t1; + +create table t1 (a int not null, b int, c varchar(20), key (a,b,c)) +partition by range (b) +(partition p0 values less than (5), + partition p1 values less than (10)); +INSERT into t1 values (1,1,'1'),(2,2,'2'),(1,3,'3'),(2,4,'4'),(1,5,'5'); +INSERT into t1 values (2,6,'6'),(1,7,'7'),(2,8,'8'),(1,9,'9'); +INSERT into t1 values (1, NULL, NULL), (2, NULL, '10'); +select * from t1 where a = 1 order by a desc, b desc; +select * from t1 where a = 1 order by b desc; drop table t1; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2d097c34f97..2acc1f4ed7d 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1202,12 +1202,13 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key, int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len) { + DBUG_ENTER("ha_myisam::index_read_last"); DBUG_ASSERT(inited==INDEX); statistic_increment(table->in_use->status_var.ha_read_key_count, &LOCK_status); int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST); table->status=error ? STATUS_NOT_FOUND: 0; - return error; + DBUG_RETURN(error); } int ha_myisam::index_next(byte * buf) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..3d7f8fc5fb2 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3265,6 +3265,7 @@ int ha_partition::index_read(byte * buf, const byte * key, DBUG_ENTER("ha_partition::index_read"); end_range= 0; + m_index_scan_type= partition_index_read; DBUG_RETURN(common_index_read(buf, key, key_len, find_flag)); } @@ -3282,18 +3283,24 @@ int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len, enum ha_rkey_function find_flag) { int error; + bool reverse_order= FALSE; DBUG_ENTER("ha_partition::common_index_read"); memcpy((void*)m_start_key.key, key, key_len); m_start_key.length= key_len; m_start_key.flag= find_flag; - m_index_scan_type= partition_index_read; if ((error= partition_scan_set_up(buf, TRUE))) { DBUG_RETURN(error); } - + if (find_flag == HA_READ_PREFIX_LAST || + find_flag == HA_READ_PREFIX_LAST_OR_PREV || + find_flag == HA_READ_BEFORE_KEY) + { + reverse_order= TRUE; + m_ordered_scan_ongoing= TRUE; + } if (!m_ordered_scan_ongoing || (find_flag == HA_READ_KEY_EXACT && (key_len >= m_curr_key_info->key_length || @@ -3319,7 +3326,7 @@ int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len, In all other cases we will use the ordered index scan. This will use the partition set created by the get_partition_set method. */ - error= handle_ordered_index_scan(buf); + error= handle_ordered_index_scan(buf, reverse_order); } DBUG_RETURN(error); } @@ -3403,7 +3410,7 @@ int ha_partition::common_first_last(byte *buf) if (!m_ordered_scan_ongoing && m_index_scan_type != partition_index_last) return handle_unordered_scan_next_partition(buf); - return handle_ordered_index_scan(buf); + return handle_ordered_index_scan(buf, FALSE); } @@ -3457,7 +3464,9 @@ int ha_partition::index_read_last(byte *buf, const byte *key, uint keylen) DBUG_ENTER("ha_partition::index_read_last"); m_ordered= TRUE; // Safety measure - DBUG_RETURN(index_read(buf, key, keylen, HA_READ_PREFIX_LAST)); + end_range= 0; + m_index_scan_type= partition_index_read_last; + DBUG_RETURN(common_index_read(buf, key, keylen, HA_READ_PREFIX_LAST)); } @@ -3597,6 +3606,7 @@ int ha_partition::read_range_first(const key_range *start_key, } else { + m_index_scan_type= partition_index_read; error= common_index_read(m_rec0, start_key->key, start_key->length, start_key->flag); @@ -3855,12 +3865,11 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf) entries. */ -int ha_partition::handle_ordered_index_scan(byte *buf) +int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) { uint i; uint j= 0; bool found= FALSE; - bool reverse_order= FALSE; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); m_top_entry= NO_CURRENT_PART_ID; @@ -3881,7 +3890,6 @@ int ha_partition::handle_ordered_index_scan(byte *buf) m_start_key.key, m_start_key.length, m_start_key.flag); - reverse_order= FALSE; break; case partition_index_first: error= file->index_first(rec_buf_ptr); @@ -3891,6 +3899,12 @@ int ha_partition::handle_ordered_index_scan(byte *buf) error= file->index_last(rec_buf_ptr); reverse_order= TRUE; break; + case partition_index_read_last: + error= file->index_read_last(rec_buf_ptr, + m_start_key.key, + m_start_key.length); + reverse_order= TRUE; + break; default: DBUG_ASSERT(FALSE); DBUG_RETURN(HA_ERR_END_OF_FILE); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4c627cd50f8..b838bc599f0 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -46,7 +46,8 @@ private: partition_index_read= 0, partition_index_first= 1, partition_index_last= 2, - partition_no_index_scan= 3 + partition_index_read_last= 3, + partition_no_index_scan= 4 }; /* Data for the partition handler */ int m_mode; // Open mode @@ -429,7 +430,7 @@ private: return (queue_buf(part_id) + PARTITION_BYTES_IN_POS); } - int handle_ordered_index_scan(byte * buf); + int handle_ordered_index_scan(byte * buf, bool reverse_order); int handle_ordered_next(byte * buf, bool next_same); int handle_ordered_prev(byte * buf); void return_top_record(byte * buf); From cc545cc6cf0e742ec17c92f7ec4a7113b77bf4da Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Sat, 15 Jul 2006 07:28:31 -0400 Subject: [PATCH 15/22] Fixes to make tests work in conjunction with other tests --- mysql-test/r/partition.result | 6 ++++++ mysql-test/t/partition.test | 14 ++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 26969d1ad5d..cbf45bdb40d 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1087,14 +1087,17 @@ partition by range (a) subpartition by hash (a) (partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' (SUBPARTITION subpart00, SUBPARTITION subpart01)); +hello/master-data/test: t1#P#p0#SP#subpart00.MYD t1#P#p0#SP#subpart00.MYI t1#P#p0#SP#subpart01.MYD t1#P#p0#SP#subpart01.MYI t1.frm t1.par +hello/master-data/tmpdata: t1#P#p0#SP#subpart00.MYD t1#P#p0#SP#subpart01.MYD +hello/master-data/tmpinx: t1#P#p0#SP#subpart00.MYI t1#P#p0#SP#subpart01.MYI ALTER TABLE t1 REORGANIZE PARTITION p0 INTO @@ -1102,6 +1105,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p0 INTO (SUBPARTITION subpart10, SUBPARTITION subpart11), partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' (SUBPARTITION subpart20, SUBPARTITION subpart21)); +hello/master-data/test: t1#P#p1#SP#subpart10.MYD t1#P#p1#SP#subpart10.MYI t1#P#p1#SP#subpart11.MYD @@ -1112,10 +1116,12 @@ t1#P#p2#SP#subpart21.MYD t1#P#p2#SP#subpart21.MYI t1.frm t1.par +hello/master-data/tmpdata: t1#P#p1#SP#subpart10.MYD t1#P#p1#SP#subpart11.MYD t1#P#p2#SP#subpart20.MYD t1#P#p2#SP#subpart21.MYD +hello/master-data/tmpinx: t1#P#p1#SP#subpart10.MYI t1#P#p1#SP#subpart11.MYI t1#P#p2#SP#subpart20.MYI diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 1c606c47183..7d88174304d 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1283,11 +1283,11 @@ subpartition by hash (a) (SUBPARTITION subpart00, SUBPARTITION subpart01)); --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test || true +--exec ls $MYSQLTEST_VARDIR/master-data/test t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpdata || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpinx || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx t1* || true --replace_result $MYSQLTEST_VARDIR "hello" eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO @@ -1297,11 +1297,13 @@ eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO (SUBPARTITION subpart20, SUBPARTITION subpart21)); --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test || true +--exec ls $MYSQLTEST_VARDIR/master-data/test t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpdata || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpinx || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx t1* || true drop table t1; +--exec rmdir $MYSQLTEST_VARDIR/master-data/tmpdata || true +--exec rmdir $MYSQLTEST_VARDIR/master-data/tmpinx || true --echo End of 5.1 tests From 54571ec6ad69105b4e9b0cc0096af6e934b5e6f7 Mon Sep 17 00:00:00 2001 From: "pekka@orca.ndb.mysql.com" <> Date: Sat, 15 Jul 2006 17:53:57 +0200 Subject: [PATCH 16/22] ndb - ndb_restore: print some dd errors at right verbosity --- storage/ndb/tools/restore/consumer_restore.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 6f9b025222c..44f4b770b05 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -485,7 +485,8 @@ BackupRestore::object(Uint32 type, const void * ptr) if (ret) { NdbError errobj= dict->getNdbError(); - info << "FAILED " << errobj << endl; + info << "FAILED" << endl; + err << "Create tablespace failed: " << old.getName() << ": " << errobj << endl; return false; } info << "done" << endl; @@ -523,7 +524,8 @@ BackupRestore::object(Uint32 type, const void * ptr) if (ret) { NdbError errobj= dict->getNdbError(); - info << "FAILED" << errobj << endl; + info << "FAILED" << endl; + err << "Create logfile group failed: " << old.getName() << ": " << errobj << endl; return false; } info << "done" << endl; @@ -564,7 +566,9 @@ BackupRestore::object(Uint32 type, const void * ptr) info << "Creating datafile \"" << old.getPath() << "\"..." << flush; if (dict->createDatafile(old)) { - info << "FAILED " << dict->getNdbError() << endl; + NdbError errobj= dict->getNdbError(); + info << "FAILED" << endl; + err << "Create datafile failed: " << old.getPath() << ": " << errobj << endl; return false; } info << "done" << endl; @@ -588,7 +592,9 @@ BackupRestore::object(Uint32 type, const void * ptr) info << "Creating undofile \"" << old.getPath() << "\"..." << flush; if (dict->createUndofile(old)) { - info << "FAILED " << dict->getNdbError() << endl; + NdbError errobj= dict->getNdbError(); + info << "FAILED" << endl; + err << "Create undofile failed: " << old.getPath() << ": " << errobj << endl; return false; } info << "done" << endl; From 1c1a1316756fe8741a4b664681b5a21620c8ae2a Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Sat, 15 Jul 2006 12:01:46 -0400 Subject: [PATCH 17/22] Remove files that tests leave behind --- mysql-test/t/ndb_alter_table.test | 1 + mysql-test/t/partition.test | 1 + mysql-test/t/rpl_ndb_bank.test | 1 + mysql-test/t/rpl_ndb_dd_advance.test | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 73c612b203f..fde9f1479f8 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -389,6 +389,7 @@ drop index i1 on t1; --disable_warnings --exec $NDB_TOOLS_DIR/ndb_show_tables --p > $MYSQLTEST_VARDIR/master-data/test/tmp.dat LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables; +--exec rm $MYSQLTEST_VARDIR/master-data/test/tmp.dat || true --enable_warnings select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%'; diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 7d88174304d..1495c4f1c6d 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -7,6 +7,7 @@ --disable_warnings drop table if exists t1; +--exec rm $MYSQLTEST_VARDIR/test/db.opt || true --enable_warnings # diff --git a/mysql-test/t/rpl_ndb_bank.test b/mysql-test/t/rpl_ndb_bank.test index 3601c841c54..d6a10e4ccac 100644 --- a/mysql-test/t/rpl_ndb_bank.test +++ b/mysql-test/t/rpl_ndb_bank.test @@ -121,6 +121,7 @@ RESET MASTER; CREATE TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP; DELETE FROM cluster.backup_info; LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; +--exec rm $MYSQLTEST_VARDIR/tmp.dat || true --replace_column 1 SELECT @the_backup_id:=backup_id FROM cluster.backup_info; let the_backup_id=`select @the_backup_id`; diff --git a/mysql-test/t/rpl_ndb_dd_advance.test b/mysql-test/t/rpl_ndb_dd_advance.test index 30d5deb47ad..1fe36ecd8a1 100644 --- a/mysql-test/t/rpl_ndb_dd_advance.test +++ b/mysql-test/t/rpl_ndb_dd_advance.test @@ -441,7 +441,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) DELETE FROM cluster.backup_info; LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; - +--exec rm $MYSQLTEST_VARDIR/tmp.dat || true --replace_column 1 SELECT @the_backup_id:=backup_id FROM cluster.backup_info; From 3d442310645f76f76aa506dd919eb5343882314d Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Sat, 15 Jul 2006 17:05:47 -0400 Subject: [PATCH 18/22] Minor fix --- mysql-test/t/partition.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 1495c4f1c6d..af6bce276d3 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -7,7 +7,6 @@ --disable_warnings drop table if exists t1; ---exec rm $MYSQLTEST_VARDIR/test/db.opt || true --enable_warnings # @@ -1267,6 +1266,7 @@ drop table t1; # doesn't remove old directory # --disable_query_log +--exec rm $MYSQLTEST_VARDIR/test/db.opt || true --exec mkdir $MYSQLTEST_VARDIR/master-data/tmpdata || true eval SET @data_dir = 'DATA DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpdata'''; let $data_directory = `select @data_dir`; From 6019ac9b71df96a8f8213432f23fe081d0d7cfb9 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 17 Jul 2006 06:41:12 -0400 Subject: [PATCH 19/22] Fixes for strange appearance of db.opt file --- mysql-test/t/partition.test | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index af6bce276d3..6deb8f77a58 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1266,7 +1266,6 @@ drop table t1; # doesn't remove old directory # --disable_query_log ---exec rm $MYSQLTEST_VARDIR/test/db.opt || true --exec mkdir $MYSQLTEST_VARDIR/master-data/tmpdata || true eval SET @data_dir = 'DATA DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpdata'''; let $data_directory = `select @data_dir`; @@ -1284,11 +1283,11 @@ subpartition by hash (a) (SUBPARTITION subpart00, SUBPARTITION subpart01)); --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test t1* || true +--exec ls $MYSQLTEST_VARDIR/master-data/test/t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpdata t1* || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata/t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpinx t1* || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx/t1* || true --replace_result $MYSQLTEST_VARDIR "hello" eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO @@ -1298,11 +1297,11 @@ eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO (SUBPARTITION subpart20, SUBPARTITION subpart21)); --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test t1* || true +--exec ls $MYSQLTEST_VARDIR/master-data/test/t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpdata t1* || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata/t1* || true --replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/tmpinx t1* || true +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx/t1* || true drop table t1; --exec rmdir $MYSQLTEST_VARDIR/master-data/tmpdata || true From bae61f209dc2460b53dcdb2b5a66aa53ff41a236 Mon Sep 17 00:00:00 2001 From: "mikael/pappa@dator5.(none)" <> Date: Mon, 17 Jul 2006 06:53:46 -0400 Subject: [PATCH 20/22] Fixed test case --- mysql-test/r/partition.result | 62 ++++++++++++++++------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index cbf45bdb40d..875358100b6 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1087,44 +1087,38 @@ partition by range (a) subpartition by hash (a) (partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' (SUBPARTITION subpart00, SUBPARTITION subpart01)); -hello/master-data/test: -t1#P#p0#SP#subpart00.MYD -t1#P#p0#SP#subpart00.MYI -t1#P#p0#SP#subpart01.MYD -t1#P#p0#SP#subpart01.MYI -t1.frm -t1.par -hello/master-data/tmpdata: -t1#P#p0#SP#subpart00.MYD -t1#P#p0#SP#subpart01.MYD -hello/master-data/tmpinx: -t1#P#p0#SP#subpart00.MYI -t1#P#p0#SP#subpart01.MYI +hello/master-data/test/t1#P#p0#SP#subpart00.MYD +hello/master-data/test/t1#P#p0#SP#subpart00.MYI +hello/master-data/test/t1#P#p0#SP#subpart01.MYD +hello/master-data/test/t1#P#p0#SP#subpart01.MYI +hello/master-data/test/t1.frm +hello/master-data/test/t1.par +hello/master-data/tmpdata/t1#P#p0#SP#subpart00.MYD +hello/master-data/tmpdata/t1#P#p0#SP#subpart01.MYD +hello/master-data/tmpinx/t1#P#p0#SP#subpart00.MYI +hello/master-data/tmpinx/t1#P#p0#SP#subpart01.MYI ALTER TABLE t1 REORGANIZE PARTITION p0 INTO (partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' (SUBPARTITION subpart10, SUBPARTITION subpart11), partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' (SUBPARTITION subpart20, SUBPARTITION subpart21)); -hello/master-data/test: -t1#P#p1#SP#subpart10.MYD -t1#P#p1#SP#subpart10.MYI -t1#P#p1#SP#subpart11.MYD -t1#P#p1#SP#subpart11.MYI -t1#P#p2#SP#subpart20.MYD -t1#P#p2#SP#subpart20.MYI -t1#P#p2#SP#subpart21.MYD -t1#P#p2#SP#subpart21.MYI -t1.frm -t1.par -hello/master-data/tmpdata: -t1#P#p1#SP#subpart10.MYD -t1#P#p1#SP#subpart11.MYD -t1#P#p2#SP#subpart20.MYD -t1#P#p2#SP#subpart21.MYD -hello/master-data/tmpinx: -t1#P#p1#SP#subpart10.MYI -t1#P#p1#SP#subpart11.MYI -t1#P#p2#SP#subpart20.MYI -t1#P#p2#SP#subpart21.MYI +hello/master-data/test/t1#P#p1#SP#subpart10.MYD +hello/master-data/test/t1#P#p1#SP#subpart10.MYI +hello/master-data/test/t1#P#p1#SP#subpart11.MYD +hello/master-data/test/t1#P#p1#SP#subpart11.MYI +hello/master-data/test/t1#P#p2#SP#subpart20.MYD +hello/master-data/test/t1#P#p2#SP#subpart20.MYI +hello/master-data/test/t1#P#p2#SP#subpart21.MYD +hello/master-data/test/t1#P#p2#SP#subpart21.MYI +hello/master-data/test/t1.frm +hello/master-data/test/t1.par +hello/master-data/tmpdata/t1#P#p1#SP#subpart10.MYD +hello/master-data/tmpdata/t1#P#p1#SP#subpart11.MYD +hello/master-data/tmpdata/t1#P#p2#SP#subpart20.MYD +hello/master-data/tmpdata/t1#P#p2#SP#subpart21.MYD +hello/master-data/tmpinx/t1#P#p1#SP#subpart10.MYI +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; End of 5.1 tests From 7c0930c4ae2fd0d78d5b874c3dcb3d6cadf97a64 Mon Sep 17 00:00:00 2001 From: "gluh@mysql.com/vva.(none)" <> Date: Tue, 18 Jul 2006 20:13:13 +0500 Subject: [PATCH 21/22] after merge fix --- mysql-test/r/strict.result | 2 +- sql/handler.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 169b885fa3d..dd96dc6d983 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -1341,6 +1341,6 @@ comment '123456789*123456789*123456789*123456789*123456789*123456789*'; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `i` int(11) default NULL + `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='123456789*123456789*123456789*123456789*123456789*123456789*' drop table t1; diff --git a/sql/handler.h b/sql/handler.h index 0b55eebd21a..b4572d449e5 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -727,7 +727,6 @@ typedef struct st_ha_create_information LEX_STRING connect_string; const char *password, *tablespace; LEX_STRING comment; - const char *password; const char *data_file_name, *index_file_name; const char *alias; ulonglong max_rows,min_rows; From a68400dd9850f20827f3becfd29d52a2601c4c07 Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Tue, 18 Jul 2006 23:08:13 +0200 Subject: [PATCH 22/22] Fix windows build of libmysqld. Curious why pushbuild did not catch that. Stale CMakeLists.txt --- libmysqld/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 69d8b6e0f67..ddb52ce9014 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -28,7 +28,7 @@ ADD_LIBRARY(mysqldemb emb_qcache.cc libmysqld.c lib_sql.cc ../client/get_password.c ../libmysql/errmsg.c ../libmysql/libmysql.c ../sql/password.c ../sql-common/client.c ../sql-common/my_time.c ../sql-common/my_user.c - ../sql-common/pack.c ../sql/derror.cc ../sql/event_executor.cc + ../sql-common/pack.c ../sql/derror.cc ../sql/event_scheduler.cc ../sql/event_timed.cc ../sql/events.cc ../sql/discover.cc ../sql/field_conv.cc ../sql/field.cc ../sql/filesort.cc ../sql/gstream.cc ../sql/ha_heap.cc ../sql/ha_myisam.cc