From f3c3c9c34189a5ccdacf62aec50e55c197223148 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Jun 2006 16:59:52 -0700 Subject: [PATCH 01/18] Bug #16494: Updates that set a column to NULL fail sometimes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building the UPDATE query to send to the remote server, the federated storage engine built the query incorrectly if it was updating a field to be NULL. Thanks to Bjšrn Steinbrink for an initial patch for the problem. mysql-test/r/federated.result: Add new results mysql-test/t/federated.test: Add new regression test sql/ha_federated.cc: Fix logic of how fields are added to SET and WHERE clauses of an UPDATE statement. Fields that were NULL were being handled incorrectly. Also reorganizes the code a little bit so the update of the two clauses is consistent. --- mysql-test/r/federated.result | 16 ++++++++++++++++ mysql-test/t/federated.test | 17 +++++++++++++++++ sql/ha_federated.cc | 17 +++++++---------- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index f11da4ee62f..48f20625826 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1601,6 +1601,22 @@ fld_cid fld_name fld_parentid fld_delt 5 Torkel 0 0 DROP TABLE federated.t1; DROP TABLE federated.bug_17377_table; +create table t1 (id int not null auto_increment primary key, val int); +create table t1 +(id int not null auto_increment primary key, val int) engine=federated +connection='mysql://root@127.0.0.1:9308/test/t1'; +insert into t1 values (1,0),(2,0); +update t1 set val = NULL where id = 1; +select * from t1; +id val +1 NULL +2 0 +select * from t1; +id val +1 NULL +2 0 +drop table t1; +drop table t1; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 80b31c610a2..d24caf1aa08 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1309,5 +1309,22 @@ DROP TABLE federated.t1; connection slave; DROP TABLE federated.bug_17377_table; +# +# Bug #16494: Updates that set a column to NULL fail sometimes +# +connection slave; +create table t1 (id int not null auto_increment primary key, val int); +connection master; +eval create table t1 + (id int not null auto_increment primary key, val int) engine=federated + connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +insert into t1 values (1,0),(2,0); +update t1 set val = NULL where id = 1; +select * from t1; +connection slave; +select * from t1; +drop table t1; +connection master; +drop table t1; source include/federated_cleanup.inc; diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index c6d5c77803b..9e9c23c0ccc 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1857,8 +1857,8 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) In this loop, we want to match column names to values being inserted (while building INSERT statement). - Iterate through table->field (new data) and share->old_filed (old_data) - using the same index to created an SQL UPDATE statement, new data is + Iterate through table->field (new data) and share->old_field (old_data) + using the same index to create an SQL UPDATE statement. New data is used to create SET field=value and old data is used to create WHERE field=oldvalue */ @@ -1870,30 +1870,28 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) update_string.append(FEDERATED_EQ); if ((*field)->is_null()) - new_field_value.append(FEDERATED_NULL); + update_string.append(FEDERATED_NULL); else { /* otherwise = */ (*field)->val_str(&new_field_value); (*field)->quote_data(&new_field_value); - - if (!field_in_record_is_null(table, *field, (char*) old_data)) - where_string.append(FEDERATED_EQ); + update_string.append(new_field_value); + new_field_value.length(0); } if (field_in_record_is_null(table, *field, (char*) old_data)) where_string.append(FEDERATED_ISNULL); else { + where_string.append(FEDERATED_EQ); (*field)->val_str(&old_field_value, (char*) (old_data + (*field)->offset())); (*field)->quote_data(&old_field_value); where_string.append(old_field_value); + old_field_value.length(0); } - update_string.append(new_field_value); - new_field_value.length(0); - /* Only append conjunctions if we have another field in which to iterate @@ -1903,7 +1901,6 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) update_string.append(FEDERATED_COMMA); where_string.append(FEDERATED_AND); } - old_field_value.length(0); } update_string.append(FEDERATED_WHERE); update_string.append(where_string); From 12e62a8e89c2c37268e7a0d845fa4029c7dd3e40 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Jun 2006 12:11:52 -0700 Subject: [PATCH 02/18] Optimize stack usage of ha_federated::update_row(). sql/ha_federated.cc: We only need one string buffer for fields in ::update_row() --- sql/ha_federated.cc | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 9e9c23c0ccc..c4e1549183a 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1817,19 +1817,13 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) /* buffers for following strings */ - char old_field_value_buffer[STRING_BUFFER_USUAL_SIZE]; - char new_field_value_buffer[STRING_BUFFER_USUAL_SIZE]; + char field_value_buffer[STRING_BUFFER_USUAL_SIZE]; char update_buffer[FEDERATED_QUERY_BUFFER_SIZE]; char where_buffer[FEDERATED_QUERY_BUFFER_SIZE]; - /* stores the value to be replaced of the field were are updating */ - String old_field_value(old_field_value_buffer, - sizeof(old_field_value_buffer), - &my_charset_bin); - /* stores the new value of the field */ - String new_field_value(new_field_value_buffer, - sizeof(new_field_value_buffer), - &my_charset_bin); + /* Work area for field values */ + String field_value(field_value_buffer, sizeof(field_value_buffer), + &my_charset_bin); /* stores the update query */ String update_string(update_buffer, sizeof(update_buffer), @@ -1842,8 +1836,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) /* set string lengths to 0 to avoid misc chars in string */ - old_field_value.length(0); - new_field_value.length(0); + field_value.length(0); update_string.length(0); where_string.length(0); @@ -1874,10 +1867,10 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) else { /* otherwise = */ - (*field)->val_str(&new_field_value); - (*field)->quote_data(&new_field_value); - update_string.append(new_field_value); - new_field_value.length(0); + (*field)->val_str(&field_value); + (*field)->quote_data(&field_value); + update_string.append(field_value); + field_value.length(0); } if (field_in_record_is_null(table, *field, (char*) old_data)) @@ -1885,11 +1878,11 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) else { where_string.append(FEDERATED_EQ); - (*field)->val_str(&old_field_value, + (*field)->val_str(&field_value, (char*) (old_data + (*field)->offset())); - (*field)->quote_data(&old_field_value); - where_string.append(old_field_value); - old_field_value.length(0); + (*field)->quote_data(&field_value); + where_string.append(field_value); + field_value.length(0); } /* From 728371c56e3e0a3f421425a9db9e5bab289670cc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Jun 2006 15:50:44 +0500 Subject: [PATCH 03/18] 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: Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context test case mysql-test/t/sp_notembedded.test: Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context test case sql/mysql_priv.h: Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context new get_current_user(THD *thd, LEX_USER *user) function sql/sql_acl.cc: Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context user name is calculated using get_current_user() function sql/sql_parse.cc: Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context new get_current_user() function user name is calculated using get_current_user() function sql/sql_yacc.yy: Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context empty LEX_USER struct for CURRENT USER, user name is calculated on function execution 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 a7f9f7ae743efca9b1f405773416d19f9ebaf3c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Jun 2006 16:52:46 +0500 Subject: [PATCH 04/18] 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: Bug#19671 mysql_list_fields returns incorrect table name for VIEWs new Item_ident_for_show class which correctly sets view db and table names for Send_field. sql/item.h: Bug#19671 mysql_list_fields returns incorrect table name for VIEWs new Item_ident_for_show class which correctly sets view db and table names for Send_field. sql/sql_show.cc: Bug#19671 mysql_list_fields returns incorrect table name for VIEWs new Item_ident_for_show is used for views tests/mysql_client_test.c: Bug#19671 mysql_list_fields returns incorrect table name for VIEWs test case --- 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 16d2ad61c318bd8211094de32a65449647ac1829 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Jun 2006 14:03:53 +0200 Subject: [PATCH 05/18] Fixed yet another forgotten port number replacement. --- mysql-test/r/federated.result | 2 +- mysql-test/t/federated.test | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index b8723027c9d..a08e9beec11 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1692,7 +1692,7 @@ drop table federated.t1, federated.t2; create table t1 (id int not null auto_increment primary key, val int); create table t1 (id int not null auto_increment primary key, val int) engine=federated -connection='mysql://root@127.0.0.1:9308/test/t1'; +connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; insert into t1 values (1,0),(2,0); update t1 set val = NULL where id = 1; select * from t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 479cb2ac770..9010489ad4d 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1371,6 +1371,7 @@ drop table federated.t1, federated.t2; connection slave; create table t1 (id int not null auto_increment primary key, val int); connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT eval create table t1 (id int not null auto_increment primary key, val int) engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; From 8703b22e167c706d5a8c77a1e24948b4db3fafb3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Jun 2006 18:39:34 +0500 Subject: [PATCH 06/18] 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: test case mysql-test/t/strict.test: test case sql/handler.h: Table 'comment' is changed from char* to LEX_STRING sql/sql_show.cc: Table 'comment' is changed from char* to LEX_STRING sql/sql_table.cc: Table 'comment' is changed from char* to LEX_STRING sql/sql_yacc.yy: Table 'comment' is changed from char* to LEX_STRING sql/table.cc: Table 'comment' is changed from char* to LEX_STRING sql/table.h: Table 'comment' is changed from char* to LEX_STRING sql/unireg.cc: 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 --- 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 2b380332609e82c5129c05d4c04d44ecef0fcdb0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 30 Jun 2006 19:37:11 +0200 Subject: [PATCH 07/18] Manual transfer of the following changeset into the 5.0.23 release clone: 1.2525 06/06/30 18:29:27 monty@mysql.com +3 -0 Reverted wrong bug fix (Bug#11228) mysql-test/r/key.result: Manual transfer of the following fix into the 5.0.23 release clone: 1.27 06/06/30 18:29:25 monty@mysql.com +9 -1 Fixed result after removing wrong bug fix mysql-test/t/key.test: Manual transfer of the following fix into the 5.0.23 release clone: 1.24 06/06/30 18:29:25 monty@mysql.com +1 -0 Added SHOW CREATE TABLE, which is the proper way to check for table definitions sql/table.cc: Manual transfer of the following fix into the 5.0.23 release clone: 1.135 06/06/30 18:29:25 monty@mysql.com +21 -0 Reverted wrong bug fix. ... --- mysql-test/r/key.result | 10 +++++++++- mysql-test/t/key.test | 1 + sql/table.cc | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index a6f05143b3e..0174ea45935 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -336,8 +336,16 @@ UNIQUE i1idx (i1), UNIQUE i2idx (i2)); desc t1; Field Type Null Key Default Extra -i1 int(11) NO UNI +i1 int(11) NO PRI i2 int(11) NO UNI +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i1` int(11) NOT NULL, + `i2` int(11) NOT NULL, + UNIQUE KEY `i1idx` (`i1`), + UNIQUE KEY `i2idx` (`i2`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 ( c1 int, diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index e7072ae29f6..3767f5f885e 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -334,6 +334,7 @@ create table t1 ( UNIQUE i1idx (i1), UNIQUE i2idx (i2)); desc t1; +show create table t1; drop table t1; # diff --git a/sql/table.cc b/sql/table.cc index 9ec9463c33c..cfdb9bd93aa 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -678,6 +678,27 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (outparam->key_info[key].flags & HA_FULLTEXT) outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT; + if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) + { + /* + If the UNIQUE key doesn't have NULL columns and is not a part key + declare this as a primary key. + */ + primary_key=key; + for (i=0 ; i < keyinfo->key_parts ;i++) + { + uint fieldnr= key_part[i].fieldnr; + if (!fieldnr || + outparam->field[fieldnr-1]->null_ptr || + outparam->field[fieldnr-1]->key_length() != + key_part[i].length) + { + primary_key=MAX_KEY; // Can't be used + break; + } + } + } + for (i=0 ; i < keyinfo->key_parts ; key_part++,i++) { if (new_field_pack_flag <= 1) From 805e85548cab8b9e1c6b853f5514c4da7136228c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Jul 2006 15:11:59 +0200 Subject: [PATCH 08/18] my_sys.h: Added missing parameter type change for _my_strdup_with_length() include/my_sys.h: Added missing parameter type change for _my_strdup_with_length() --- include/my_sys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_sys.h b/include/my_sys.h index b00b59c4779..9b283ace029 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -597,7 +597,7 @@ extern gptr _my_memdup(const byte *from,uint length, const char *sFile, uint uLine,myf MyFlag); extern my_string _my_strdup(const char *from, const char *sFile, uint uLine, myf MyFlag); -extern char *_my_strdup_with_length(const byte *from, uint length, +extern char *_my_strdup_with_length(const char *from, uint length, const char *sFile, uint uLine, myf MyFlag); From 84e72c2bdeae3fb70f159966959b4b8f0b7afdfe Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Jul 2006 23:52:19 +0200 Subject: [PATCH 09/18] mysqld.vcproj: Don't define __NT__ for 'Max' target VC++Files/sql/mysqld.vcproj: Don't define __NT__ for 'Max' target --- VC++Files/sql/mysqld.vcproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VC++Files/sql/mysqld.vcproj b/VC++Files/sql/mysqld.vcproj index c9675f3fd8a..36e1b1ea3ac 100644 --- a/VC++Files/sql/mysqld.vcproj +++ b/VC++Files/sql/mysqld.vcproj @@ -85,7 +85,7 @@ InlineFunctionExpansion="1" OptimizeForProcessor="2" AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib" - PreprocessorDefinitions="__NT__;NDEBUG;DBUG_OFF;USE_SYMDIR;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" + PreprocessorDefinitions="USE_SYMDIR;NDEBUG;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" StringPooling="TRUE" RuntimeLibrary="0" EnableFunctionLevelLinking="TRUE" @@ -145,7 +145,7 @@ InlineFunctionExpansion="1" OptimizeForProcessor="2" AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib" - PreprocessorDefinitions="NDEBUG;__NT__;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" + PreprocessorDefinitions="__NT__;NDEBUG;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" StringPooling="TRUE" RuntimeLibrary="0" EnableFunctionLevelLinking="TRUE" From 97c2188812ee3aa9b6480d412e20ecb71740bc0b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Jul 2006 10:56:19 +0200 Subject: [PATCH 10/18] Makefile.am: Avoid duplicate symbol errors on Netware mwldnlm, mwccnlm, mwasmnlm: Filter garbage characters from output netware/BUILD/mwasmnlm: Filter garbage characters from output netware/BUILD/mwccnlm: Filter garbage characters from output netware/BUILD/mwldnlm: Filter garbage characters from output tests/Makefile.am: Avoid duplicate symbol errors on Netware --- netware/BUILD/mwasmnlm | 2 +- netware/BUILD/mwccnlm | 2 +- netware/BUILD/mwldnlm | 2 +- tests/Makefile.am | 6 ++++++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/netware/BUILD/mwasmnlm b/netware/BUILD/mwasmnlm index 381f84ec0c8..7f2378871c6 100755 --- a/netware/BUILD/mwasmnlm +++ b/netware/BUILD/mwasmnlm @@ -5,4 +5,4 @@ set -e args=" $*" -wine --debugmsg -all -- mwasmnlm $args +wine --debugmsg -all -- mwasmnlm $args 2>&1 | sed -e 's/^[[:cntrl:]].*[[:cntrl:]]>//' diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm index cb2d62fe8cf..44cbe810922 100755 --- a/netware/BUILD/mwccnlm +++ b/netware/BUILD/mwccnlm @@ -7,4 +7,4 @@ set -e # convert it to "-I../include" args=" "`echo $* | sed -e 's/-I.\/../-I../g'` -wine --debugmsg -all -- mwccnlm $args +wine --debugmsg -all -- mwccnlm $args 2>&1 | sed -e 's/^[[:cntrl:]].*[[:cntrl:]]>//' diff --git a/netware/BUILD/mwldnlm b/netware/BUILD/mwldnlm index 28566fc5cb1..08df0e69e12 100755 --- a/netware/BUILD/mwldnlm +++ b/netware/BUILD/mwldnlm @@ -5,4 +5,4 @@ set -e args=" $*" -wine --debugmsg -all -- mwldnlm $args +wine --debugmsg -all -- mwldnlm $args 2>&1 | sed -e 's/^[[:cntrl:]].*[[:cntrl:]]>//' diff --git a/tests/Makefile.am b/tests/Makefile.am index ebe97393045..ab747d6e4ec 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,8 +42,14 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la +if HAVE_NETWARE +mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) +mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) \ + ../mysys/my_memmem.c +else mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) -L../mysys -lmysys mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) +endif insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix) select_test_SOURCES= select_test.c $(yassl_dummy_link_fix) insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) From 9ecc01a9e37cae5087eb4fd5baa96bf8e693d3a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Jul 2006 16:44:17 +0200 Subject: [PATCH 11/18] mwldnlm, mwccnlm, mwasmnlm: Use Perl for filtering, do more filtering netware/BUILD/mwasmnlm: Use Perl for filtering, do more filtering netware/BUILD/mwccnlm: Use Perl for filtering, do more filtering netware/BUILD/mwldnlm: Use Perl for filtering, do more filtering --- netware/BUILD/mwasmnlm | 5 ++++- netware/BUILD/mwccnlm | 5 ++++- netware/BUILD/mwldnlm | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/netware/BUILD/mwasmnlm b/netware/BUILD/mwasmnlm index 7f2378871c6..11fc2bc3842 100755 --- a/netware/BUILD/mwasmnlm +++ b/netware/BUILD/mwasmnlm @@ -5,4 +5,7 @@ set -e args=" $*" -wine --debugmsg -all -- mwasmnlm $args 2>&1 | sed -e 's/^[[:cntrl:]].*[[:cntrl:]]>//' +# NOTE: Option 'pipefail' is not standard sh +set -o pipefail +wine --debugmsg -all -- mwasmnlm $args | \ +perl -pe 's/\r//g; s/^\e.*\e(\[J|>)?//; s/[[^:print:]]//g' diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm index 44cbe810922..e6840e781f8 100755 --- a/netware/BUILD/mwccnlm +++ b/netware/BUILD/mwccnlm @@ -7,4 +7,7 @@ set -e # convert it to "-I../include" args=" "`echo $* | sed -e 's/-I.\/../-I../g'` -wine --debugmsg -all -- mwccnlm $args 2>&1 | sed -e 's/^[[:cntrl:]].*[[:cntrl:]]>//' +# NOTE: Option 'pipefail' is not standard sh +set -o pipefail +wine --debugmsg -all -- mwccnlm $args | \ +perl -pe 's/\r//g; s/^\e.*\e(\[J|>)?//; s/[[^:print:]]//g' diff --git a/netware/BUILD/mwldnlm b/netware/BUILD/mwldnlm index 08df0e69e12..cc8c9e63c6e 100755 --- a/netware/BUILD/mwldnlm +++ b/netware/BUILD/mwldnlm @@ -5,4 +5,7 @@ set -e args=" $*" -wine --debugmsg -all -- mwldnlm $args 2>&1 | sed -e 's/^[[:cntrl:]].*[[:cntrl:]]>//' +# NOTE: Option 'pipefail' is not standard sh +set -o pipefail +wine --debugmsg -all -- mwldnlm $args | \ +perl -pe 's/\r//g; s/^\e.*\e(\[J|>)?//; s/[[^:print:]]//g' From e34b9cfb4a295ef767dd543acc42fefea6b0bc11 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Jul 2006 20:08:38 +0200 Subject: [PATCH 12/18] client.c: Define 'mysql_get_ssl_cipher' even if no SSL built in, it is referenced in libmysql.def sql-common/client.c: Define 'mysql_get_ssl_cipher' even if no SSL built in, it is referenced in libmysql.def --- sql-common/client.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sql-common/client.c b/sql-common/client.c index 56a5862c90e..31e85475f08 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1514,6 +1514,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , */ #ifdef HAVE_OPENSSL + static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { @@ -1538,6 +1539,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) DBUG_VOID_RETURN; } +#endif /* HAVE_OPENSSL */ /* Return the SSL cipher (if any) used for current @@ -1553,8 +1555,10 @@ const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql) { DBUG_ENTER("mysql_get_ssl_cipher"); +#ifdef HAVE_OPENSSL if (mysql->net.vio && mysql->net.vio->ssl_arg) DBUG_RETURN(SSL_get_cipher_name((SSL*)mysql->net.vio->ssl_arg)); +#endif /* HAVE_OPENSSL */ DBUG_RETURN(NULL); } @@ -1573,6 +1577,9 @@ mysql_get_ssl_cipher(MYSQL *mysql) 1 Failed to validate server */ + +#ifdef HAVE_OPENSSL + static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) { SSL *ssl; From c3ef02679edb4dccba74b8a54323cfc999137865 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Jul 2006 21:41:15 +0200 Subject: [PATCH 13/18] Bug#20783: Valgrind uninitialised warning in test case ctype_uca Two functions have different ideas of what a string should look like; one of them reads memory it assumes the other one may have written. And "if you assume ..." We now use a more defensive variety of the assuming function, this fixes a warning thrown by the valgrind tool. sql/item_cmpfunc.cc: c_ptr() makes incorrect assumptions about the string we get from out of args[0]->val_str(&tmp); c_str_safe() is more defensive. --- sql/item_cmpfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index ffacddd534a..98453899375 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3303,7 +3303,7 @@ longlong Item_func_regex::val_int() } } null_value=0; - return my_regexec(&preg,res->c_ptr(),0,(my_regmatch_t*) 0,0) ? 0 : 1; + return my_regexec(&preg,res->c_ptr_safe(),0,(my_regmatch_t*) 0,0) ? 0 : 1; } From 95e37a4ad5d0eed8d41be7879d8fbb7e422d8b79 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Jul 2006 16:54:07 +0200 Subject: [PATCH 14/18] ndb - ps_7ndb as discovered by pb fix race in scan close ndb/src/ndbapi/NdbScanOperation.cpp: Fix race in scan close --- ndb/src/ndbapi/NdbScanOperation.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index a36d47c3471..caf6cf755bb 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -1550,7 +1550,10 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ * If no receiver is outstanding... * set it to 1 as execCLOSE_SCAN_REP resets it */ - m_sent_receivers_count = m_sent_receivers_count ? m_sent_receivers_count : 1; + if (m_sent_receivers_count < theParallelism) + m_sent_receivers_count++; + else + m_conf_receivers_count++; while(theError.code == 0 && (m_sent_receivers_count + m_conf_receivers_count)) { From 410a26210e9fa0719250382f618fe271f0e11f0c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Jul 2006 20:13:13 +0500 Subject: [PATCH 15/18] 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 d090462abc2925a22a4d2dee4c87d679a9ad32f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Jul 2006 23:08:13 +0200 Subject: [PATCH 16/18] Fix windows build of libmysqld. Curious why pushbuild did not catch that. Stale CMakeLists.txt libmysqld/CMakeLists.txt: event_executor.cc is no more since a lot of time. it has been superseeded by event_scheduler.cc --- 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 From d3b743ae18801473af91d13a83297bcc0b02fae0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Jul 2006 05:28:16 -0400 Subject: [PATCH 17/18] BUG20733: Bug in partition pruning with zerofill field Problem was with handling NULL values in ranges mysql-test/r/partition_hash.result: New partition pruning test cases mysql-test/r/partition_list.result: New partition pruning test cases mysql-test/r/partition_pruning.result: New partition pruning test cases mysql-test/r/partition_range.result: New partition pruning test cases mysql-test/t/partition_hash.test: New partition pruning test cases mysql-test/t/partition_list.test: New partition pruning test cases mysql-test/t/partition_pruning.test: New partition pruning test cases mysql-test/t/partition_range.test: New partition pruning test cases sql/opt_range.cc: Added comment sql/sql_partition.cc: Partition pruning didn't handle ranges with NULL values in a proper manner --- mysql-test/r/partition_hash.result | 84 ++++++++++++++++++++++++ mysql-test/r/partition_list.result | 94 +++++++++++++++++++++++++++ mysql-test/r/partition_pruning.result | 78 ++++++++++++++++++++++ mysql-test/r/partition_range.result | 78 ++++++++++++++++++++++ mysql-test/t/partition_hash.test | 30 +++++++++ mysql-test/t/partition_list.test | 44 +++++++++++++ mysql-test/t/partition_pruning.test | 52 +++++++++++++++ mysql-test/t/partition_range.test | 44 +++++++++++++ sql/opt_range.cc | 7 +- sql/sql_partition.cc | 11 ++++ 10 files changed, 521 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/partition_hash.result b/mysql-test/r/partition_hash.result index 08faccd024e..9a82a36d902 100644 --- a/mysql-test/r/partition_hash.result +++ b/mysql-test/r/partition_hash.result @@ -1,4 +1,88 @@ drop table if exists t1; +create table t1 (a int unsigned) +partition by hash(a div 2) +partitions 4; +insert into t1 values (null),(0),(1),(2),(3),(4),(5),(6),(7); +select * from t1 where a < 0; +a +select * from t1 where a is null or (a >= 5 and a <= 7); +a +NULL +5 +6 +7 +select * from t1 where a is null; +a +NULL +select * from t1 where a is not null; +a +0 +1 +2 +3 +4 +5 +6 +7 +select * from t1 where a >= 1 and a < 3; +a +1 +2 +select * from t1 where a >= 3 and a <= 5; +a +3 +4 +5 +select * from t1 where a > 2 and a < 4; +a +3 +select * from t1 where a > 3 and a <= 6; +a +4 +5 +6 +select * from t1 where a > 5; +a +6 +7 +select * from t1 where a >= 1 and a <= 5; +a +1 +2 +3 +4 +5 +explain partitions select * from t1 where a < 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where +explain partitions select * from t1 where a is null or (a >= 5 and a <= 7); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p2,p3 ALL NULL NULL NULL NULL 7 Using where +explain partitions select * from t1 where a is null; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where +explain partitions select * from t1 where a is not null; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where +explain partitions select * from t1 where a >= 1 and a < 3; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 5 Using where +explain partitions select * from t1 where a >= 3 and a <= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 4 Using where +explain partitions select * from t1 where a > 2 and a < 4; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t1 where a > 3 and a <= 6; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p2,p3 ALL NULL NULL NULL NULL 4 Using where +explain partitions select * from t1 where a > 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where +explain partitions select * from t1 where a >= 1 and a <= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where +drop table t1; CREATE TABLE t1 ( a int not null, b int not null, diff --git a/mysql-test/r/partition_list.result b/mysql-test/r/partition_list.result index c722a3c6be3..e64a7a8d154 100644 --- a/mysql-test/r/partition_list.result +++ b/mysql-test/r/partition_list.result @@ -1,4 +1,98 @@ drop table if exists t1; +create table t1 (a int unsigned) +partition by list (a) +(partition p0 values in (0), +partition p1 values in (1), +partition pnull values in (null), +partition p2 values in (2)); +insert into t1 values (null),(0),(1),(2); +select * from t1 where a < 2; +a +0 +1 +select * from t1 where a <= 0; +a +0 +select * from t1 where a < 1; +a +0 +select * from t1 where a > 0; +a +1 +2 +select * from t1 where a > 1; +a +2 +select * from t1 where a >= 0; +a +0 +1 +2 +select * from t1 where a >= 1; +a +1 +2 +select * from t1 where a is null; +a +NULL +select * from t1 where a is not null; +a +0 +1 +2 +select * from t1 where a is null or a > 0; +a +1 +NULL +2 +drop table t1; +create table t1 (a int unsigned, b int) +partition by list (a) +subpartition by hash (b) +subpartitions 2 +(partition p0 values in (0), +partition p1 values in (1), +partition pnull values in (null, 2), +partition p3 values in (3)); +insert into t1 values (0,0),(0,1),(1,0),(1,1),(null,0),(null,1); +insert into t1 values (2,0),(2,1),(3,0),(3,1); +explain partitions select * from t1 where a is null; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 4 Using where +select * from t1 where a is null; +a b +NULL 0 +NULL 1 +explain partitions select * from t1 where a = 2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 4 Using where +select * from t1 where a = 2; +a b +2 0 +2 1 +select * from t1 where a <= 0; +a b +0 0 +0 1 +select * from t1 where a < 3; +a b +0 0 +0 1 +1 0 +1 1 +2 0 +2 1 +select * from t1 where a >= 1 or a is null; +a b +1 0 +1 1 +NULL 0 +2 0 +NULL 1 +2 1 +3 0 +3 1 +drop table t1; CREATE TABLE t1 ( a int not null, b int not null, diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index ee294242bf7..bf7888bfd99 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -149,6 +149,48 @@ id select_type table partitions type possible_keys key key_len ref rows Extra explain partitions select * from t6 where a > 3 and a < 5; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +drop table t6; +create table t6 (a int unsigned not null) partition by LIST(a) ( +partition p1 values in (1), +partition p3 values in (3), +partition p5 values in (5), +partition p7 values in (7), +partition p9 values in (9) +); +insert into t6 values (1),(3),(5); +explain partitions select * from t6 where a < 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t6 where a <= 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t6 p1 system NULL NULL NULL NULL 1 +explain partitions select * from t6 where a > 9; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t6 where a >= 9; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t6 where a > 0 and a < 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t6 p1,p3 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t6 where a > 5 and a < 12; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t6 where a > 3 and a < 8 ; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t6 p5,p7 system NULL NULL NULL NULL 1 +explain partitions select * from t6 where a >= 0 and a <= 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t6 p1,p3,p5 ALL NULL NULL NULL NULL 3 Using where +explain partitions select * from t6 where a >= 5 and a <= 12; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t6 p5,p7,p9 system NULL NULL NULL NULL 1 +explain partitions select * from t6 where a >= 3 and a <= 8; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t6 where a > 3 and a < 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables create table t7 (a int not null) partition by RANGE(a) ( partition p10 values less than (10), partition p30 values less than (30), @@ -184,6 +226,42 @@ id select_type table partitions type possible_keys key key_len ref rows Extra explain partitions select * from t7 where a > 11 and a < 29; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +drop table t7; +create table t7 (a int unsigned not null) partition by RANGE(a) ( +partition p10 values less than (10), +partition p30 values less than (30), +partition p50 values less than (50), +partition p70 values less than (70), +partition p90 values less than (90) +); +insert into t7 values (10),(30),(50); +explain partitions select * from t7 where a < 5; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t7 where a < 10; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t7 where a <= 10; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t7 p10,p30 system NULL NULL NULL NULL 1 +explain partitions select * from t7 where a = 10; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t7 p30 system NULL NULL NULL NULL 1 +explain partitions select * from t7 where a < 90; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t7 p10,p30,p50,p70,p90 ALL NULL NULL NULL NULL 3 Using where +explain partitions select * from t7 where a = 90; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t7 where a > 90; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t7 where a >= 90; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t7 where a > 11 and a < 29; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables create table t8 (a date not null) partition by RANGE(YEAR(a)) ( partition p0 values less than (1980), partition p1 values less than (1990), diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 9123c894f32..9812c80040b 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -1,4 +1,82 @@ drop table if exists t1; +create table t1 (a int unsigned) +partition by range (a) +(partition pnull values less than (0), +partition p0 values less than (1), +partition p1 values less than(2)); +insert into t1 values (null),(0),(1); +select * from t1 where a is null; +a +NULL +select * from t1 where a >= 0; +a +0 +1 +select * from t1 where a < 0; +a +select * from t1 where a <= 0; +a +0 +select * from t1 where a > 1; +a +explain partitions select * from t1 where a is null; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull system NULL NULL NULL NULL 1 +explain partitions select * from t1 where a >= 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t1 where a < 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +explain partitions select * from t1 where a <= 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull,p0 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t1 where a > 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +drop table t1; +create table t1 (a int unsigned, b int unsigned) +partition by range (a) +subpartition by hash (b) +subpartitions 2 +(partition pnull values less than (0), +partition p0 values less than (1), +partition p1 values less than(2)); +insert into t1 values (null,0),(null,1),(0,0),(0,1),(1,0),(1,1); +select * from t1 where a is null; +a b +NULL 0 +NULL 1 +select * from t1 where a >= 0; +a b +0 0 +0 1 +1 0 +1 1 +select * from t1 where a < 0; +a b +select * from t1 where a <= 0; +a b +0 0 +0 1 +select * from t1 where a > 1; +a b +explain partitions select * from t1 where a is null; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t1 where a >= 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0_p0sp0,p0_p0sp1,p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 4 Using where +explain partitions select * from t1 where a < 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1 ALL NULL NULL NULL NULL 2 Using where +explain partitions select * from t1 where a <= 0; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 pnull_pnullsp0,pnull_pnullsp1,p0_p0sp0,p0_p0sp1 ALL NULL NULL NULL NULL 4 Using where +explain partitions select * from t1 where a > 1; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p1_p1sp0,p1_p1sp1 ALL NULL NULL NULL NULL 2 Using where +drop table t1; CREATE TABLE t1 ( a int not null, b int not null, diff --git a/mysql-test/t/partition_hash.test b/mysql-test/t/partition_hash.test index 8494de98371..3304f30fb1a 100644 --- a/mysql-test/t/partition_hash.test +++ b/mysql-test/t/partition_hash.test @@ -9,6 +9,36 @@ drop table if exists t1; --enable_warnings +# +# More partition pruning tests, especially on interval walking +# +create table t1 (a int unsigned) +partition by hash(a div 2) +partitions 4; +insert into t1 values (null),(0),(1),(2),(3),(4),(5),(6),(7); +select * from t1 where a < 0; +select * from t1 where a is null or (a >= 5 and a <= 7); +select * from t1 where a is null; +select * from t1 where a is not null; +select * from t1 where a >= 1 and a < 3; +select * from t1 where a >= 3 and a <= 5; +select * from t1 where a > 2 and a < 4; +select * from t1 where a > 3 and a <= 6; +select * from t1 where a > 5; +select * from t1 where a >= 1 and a <= 5; +explain partitions select * from t1 where a < 0; +explain partitions select * from t1 where a is null or (a >= 5 and a <= 7); +explain partitions select * from t1 where a is null; +explain partitions select * from t1 where a is not null; +explain partitions select * from t1 where a >= 1 and a < 3; +explain partitions select * from t1 where a >= 3 and a <= 5; +explain partitions select * from t1 where a > 2 and a < 4; +explain partitions select * from t1 where a > 3 and a <= 6; +explain partitions select * from t1 where a > 5; +explain partitions select * from t1 where a >= 1 and a <= 5; + +drop table t1; + # # Partition by hash, basic # diff --git a/mysql-test/t/partition_list.test b/mysql-test/t/partition_list.test index e243ec468e1..1e420cfe6ed 100644 --- a/mysql-test/t/partition_list.test +++ b/mysql-test/t/partition_list.test @@ -9,6 +9,49 @@ drop table if exists t1; --enable_warnings +# +# Bug 20733: Zerofill columns gives wrong result with partitioned tables +# +create table t1 (a int unsigned) +partition by list (a) +(partition p0 values in (0), + partition p1 values in (1), + partition pnull values in (null), + partition p2 values in (2)); + +insert into t1 values (null),(0),(1),(2); +select * from t1 where a < 2; +select * from t1 where a <= 0; +select * from t1 where a < 1; +select * from t1 where a > 0; +select * from t1 where a > 1; +select * from t1 where a >= 0; +select * from t1 where a >= 1; +select * from t1 where a is null; +select * from t1 where a is not null; +select * from t1 where a is null or a > 0; +drop table t1; + +create table t1 (a int unsigned, b int) +partition by list (a) +subpartition by hash (b) +subpartitions 2 +(partition p0 values in (0), + partition p1 values in (1), + partition pnull values in (null, 2), + partition p3 values in (3)); +insert into t1 values (0,0),(0,1),(1,0),(1,1),(null,0),(null,1); +insert into t1 values (2,0),(2,1),(3,0),(3,1); + +explain partitions select * from t1 where a is null; +select * from t1 where a is null; +explain partitions select * from t1 where a = 2; +select * from t1 where a = 2; +select * from t1 where a <= 0; +select * from t1 where a < 3; +select * from t1 where a >= 1 or a is null; +drop table t1; + # # Test ordinary list partitioning that it works ok # @@ -136,3 +179,4 @@ insert into t1 values (null); select * from t1; drop table t1; + diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index 976466e1578..dd79e8d3acb 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -137,6 +137,32 @@ explain partitions select * from t6 where a >= 3 and a <= 8; explain partitions select * from t6 where a > 3 and a < 5; +drop table t6; + +create table t6 (a int unsigned not null) partition by LIST(a) ( + partition p1 values in (1), + partition p3 values in (3), + partition p5 values in (5), + partition p7 values in (7), + partition p9 values in (9) +); +insert into t6 values (1),(3),(5); + +explain partitions select * from t6 where a < 1; +explain partitions select * from t6 where a <= 1; +explain partitions select * from t6 where a > 9; +explain partitions select * from t6 where a >= 9; + +explain partitions select * from t6 where a > 0 and a < 5; +explain partitions select * from t6 where a > 5 and a < 12; +explain partitions select * from t6 where a > 3 and a < 8 ; + +explain partitions select * from t6 where a >= 0 and a <= 5; +explain partitions select * from t6 where a >= 5 and a <= 12; +explain partitions select * from t6 where a >= 3 and a <= 8; + +explain partitions select * from t6 where a > 3 and a < 5; + # RANGE(field) partitioning, interval analysis. create table t7 (a int not null) partition by RANGE(a) ( partition p10 values less than (10), @@ -162,6 +188,32 @@ explain partitions select * from t7 where a >= 90; # misc intervals explain partitions select * from t7 where a > 11 and a < 29; +drop table t7; + +create table t7 (a int unsigned not null) partition by RANGE(a) ( + partition p10 values less than (10), + partition p30 values less than (30), + partition p50 values less than (50), + partition p70 values less than (70), + partition p90 values less than (90) +); +insert into t7 values (10),(30),(50); + +# leftmost intervals +explain partitions select * from t7 where a < 5; +explain partitions select * from t7 where a < 10; +explain partitions select * from t7 where a <= 10; +explain partitions select * from t7 where a = 10; + +#rightmost intervals +explain partitions select * from t7 where a < 90; +explain partitions select * from t7 where a = 90; +explain partitions select * from t7 where a > 90; +explain partitions select * from t7 where a >= 90; + +# misc intervals +explain partitions select * from t7 where a > 11 and a < 29; + # LIST(monontonic_func) partitioning create table t8 (a date not null) partition by RANGE(YEAR(a)) ( partition p0 values less than (1980), diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 38142a9d485..670b9333ab9 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -9,6 +9,50 @@ drop table if exists t1; --enable_warnings +# +# More checks for partition pruning +# +create table t1 (a int unsigned) +partition by range (a) +(partition pnull values less than (0), + partition p0 values less than (1), + partition p1 values less than(2)); +insert into t1 values (null),(0),(1); + +select * from t1 where a is null; +select * from t1 where a >= 0; +select * from t1 where a < 0; +select * from t1 where a <= 0; +select * from t1 where a > 1; +explain partitions select * from t1 where a is null; +explain partitions select * from t1 where a >= 0; +explain partitions select * from t1 where a < 0; +explain partitions select * from t1 where a <= 0; +explain partitions select * from t1 where a > 1; +drop table t1; + +create table t1 (a int unsigned, b int unsigned) +partition by range (a) +subpartition by hash (b) +subpartitions 2 +(partition pnull values less than (0), + partition p0 values less than (1), + partition p1 values less than(2)); +insert into t1 values (null,0),(null,1),(0,0),(0,1),(1,0),(1,1); + +select * from t1 where a is null; +select * from t1 where a >= 0; +select * from t1 where a < 0; +select * from t1 where a <= 0; +select * from t1 where a > 1; +explain partitions select * from t1 where a is null; +explain partitions select * from t1 where a >= 0; +explain partitions select * from t1 where a < 0; +explain partitions select * from t1 where a <= 0; +explain partitions select * from t1 where a > 1; + +drop table t1; + # # Partition by range, basic # diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d62cb134209..956e23a09aa 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3203,7 +3203,12 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar) ppar->is_part_keypart[part]= !in_subpart_fields; ppar->is_subpart_keypart[part]= in_subpart_fields; - + + /* + Check if this was last field in this array, in this case we + switch to subpartitioning fields. (This will only happens if + there are subpartitioning fields to cater for). + */ if (!*(++field)) { field= part_info->subpart_field_array; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 44c0b8ffcd9..3f1572ee676 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2415,6 +2415,10 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_list_array_idx_for_endpoint"); + if (part_info->part_expr->null_value) + { + DBUG_RETURN(0); + } if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; DBUG_ASSERT(part_info->no_list_values); @@ -2539,6 +2543,13 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_range_for_endpoint"); + if (part_info->part_expr->null_value) + { + uint32 ret_part_id= 0; + if (!left_endpoint && include_endpoint) + ret_part_id= 1; + DBUG_RETURN(ret_part_id); + } if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; while (max_part_id > min_part_id) From 3e2dfa97050e5d0246c5e5aa2915272c61030ded Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 21 Jul 2006 10:43:10 +0200 Subject: [PATCH 18/18] After merge fixes. --- mysql-test/r/federated.result | 32 ++++++++++++++++---------------- mysql-test/t/federated.test | 1 + sql/ha_federated.cc | 21 ++++++++++----------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index efdad257172..b7b3af7d60a 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1603,6 +1603,22 @@ fld_cid fld_name fld_parentid fld_delt 5 Torkel 0 0 DROP TABLE federated.t1; DROP TABLE federated.bug_17377_table; +create table t1 (id int not null auto_increment primary key, val int); +create table t1 +(id int not null auto_increment primary key, val int) engine=federated +connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +insert into t1 values (1,0),(2,0); +update t1 set val = NULL where id = 1; +select * from t1; +id val +1 NULL +2 0 +select * from t1; +id val +1 NULL +2 0 +drop table t1; +drop table t1; drop table if exists federated.t1; create table federated.t1 (a int, b int, c int); drop table if exists federated.t1; @@ -1717,22 +1733,6 @@ id c1 c2 9 abc ppc drop table federated.t1, federated.t2; drop table federated.t1, federated.t2; -create table t1 (id int not null auto_increment primary key, val int); -create table t1 -(id int not null auto_increment primary key, val int) engine=federated -connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; -insert into t1 values (1,0),(2,0); -update t1 set val = NULL where id = 1; -select * from t1; -id val -1 NULL -2 0 -select * from t1; -id val -1 NULL -2 0 -drop table t1; -drop table t1; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 717fca4b158..7f7b2a4261b 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1396,6 +1396,7 @@ drop table t1; # for ON INSERT triggers only. Tests for other types of triggers reside # in ndb_trigger.test. # +connection slave; --disable_warnings drop table if exists federated.t1; --enable_warnings diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index e2d545710f9..7fb5bf12016 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1775,7 +1775,7 @@ int ha_federated::repair(THD* thd, HA_CHECK_OPT* check_opt) it. Keep in mind that the server can do updates based on ordering if an ORDER BY - clause was used. Consecutive ordering is not guarenteed. + clause was used. Consecutive ordering is not guaranteed. Currently new_data will not have an updated auto_increament record, or and updated timestamp field. You can do these for federated by doing these: if (table->timestamp_on_update_now) @@ -1801,7 +1801,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) this. */ bool has_a_primary_key= test(table->s->primary_key != MAX_KEY); - /* + /* buffers for following strings */ char field_value_buffer[STRING_BUFFER_USUAL_SIZE]; @@ -1820,7 +1820,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) sizeof(where_buffer), &my_charset_bin); DBUG_ENTER("ha_federated::update_row"); - /* + /* set string lengths to 0 to avoid misc chars in string */ field_value.length(0); @@ -1847,6 +1847,9 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) { if (bitmap_is_set(table->write_set, (*field)->field_index)) { + update_string.append((*field)->field_name); + update_string.append(FEDERATED_EQ); + if ((*field)->is_null()) update_string.append(FEDERATED_NULL); else @@ -1859,11 +1862,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) field_value.length(0); tmp_restore_column_map(table->read_set, old_map); } - update_string.append((*field)->field_name); - update_string.append(FEDERATED_EQ); - update_string.append(new_field_value); update_string.append(FEDERATED_COMMA); - new_field_value.length(0); } if (bitmap_is_set(table->read_set, (*field)->field_index)) @@ -1874,11 +1873,11 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) else { where_string.append(FEDERATED_EQ); - (*field)->val_str(&old_field_value, + (*field)->val_str(&field_value, (char*) (old_data + (*field)->offset())); - (*field)->quote_data(&old_field_value); - where_string.append(old_field_value); - old_field_value.length(0); + (*field)->quote_data(&field_value); + where_string.append(field_value); + field_value.length(0); } where_string.append(FEDERATED_AND); }