From 5150fdcc04efca4e2dd7bb435bc0e3438cc2f5be Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Wed, 13 Jul 2005 13:00:17 +0500 Subject: [PATCH 01/39] ctype_utf8.result: adding test case sql_table.cc: sql_table.cc: - do not create a new item when charsets are the same - return ER_INVALID_DEFAULT if default value cannot be converted into the column character set. item.cc: - Allow conversion not only to Unicode, but also to and from "binary". - Adding safe_charset_converter() for Item_num and Item_varbinary, returning a fixed const Item. --- mysql-test/r/ctype_utf8.result | 4 ++++ mysql-test/t/ctype_utf8.test | 9 +++++++ sql/item.cc | 44 +++++++++++++++++++++++++++++++++- sql/item.h | 2 ++ sql/sql_table.cc | 11 ++++++--- 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 3a8265b01f7..290d6d93421 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -905,6 +905,10 @@ select * from t1 where city = 'Durban '; id city 2 Durban drop table t1; +create table t1 (x set('A', 'B') default 0) character set utf8; +ERROR 42000: Invalid default value for 'x' +create table t1 (x enum('A', 'B') default 0) character set utf8; +ERROR 42000: Invalid default value for 'x' SET NAMES UTF8; CREATE TABLE t1 ( `id` int(20) NOT NULL auto_increment, diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 0a847057258..638d1f1de5c 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -747,6 +747,15 @@ select * from t1 where city = 'Durban'; select * from t1 where city = 'Durban '; drop table t1; +# +# Bug #11819 CREATE TABLE with a SET DEFAULT 0 and UTF8 crashes server. +# +--error 1067 +create table t1 (x set('A', 'B') default 0) character set utf8; +--error 1067 +create table t1 (x enum('A', 'B') default 0) character set utf8; + + # # Test for bug #11167: join for utf8 varchar value longer than 255 bytes # diff --git a/sql/item.cc b/sql/item.cc index c96794ff482..ee78d596891 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -212,15 +212,43 @@ bool Item::eq(const Item *item, bool binary_cmp) const Item *Item::safe_charset_converter(CHARSET_INFO *tocs) { /* + Allow conversion from and to "binary". Don't allow automatic conversion to non-Unicode charsets, as it potentially loses data. */ - if (!(tocs->state & MY_CS_UNICODE)) + if (collation.collation != &my_charset_bin && + tocs != &my_charset_bin && + !(tocs->state & MY_CS_UNICODE)) return NULL; // safe conversion is not possible return new Item_func_conv_charset(this, tocs); } +/* + Created mostly for mysql_prepare_table(). Important + when a string ENUM/SET column is described with a numeric default value: + + CREATE TABLE t1(a SET('a') DEFAULT 1); + + We cannot use generic Item::safe_charset_converter(), because + the latter returns a non-fixed Item, so val_str() crashes afterwards. + Override Item_num method, to return a fixed item. +*/ +Item *Item_num::safe_charset_converter(CHARSET_INFO *tocs) +{ + Item_string *conv; + char buf[64]; + String *s, tmp(buf, sizeof(buf), &my_charset_bin); + s= val_str(&tmp); + if ((conv= new Item_string(s->ptr(), s->length(), s->charset()))) + { + conv->str_value.copy(); + conv->str_value.shrink_to_length(); + } + return conv; +} + + Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) { Item_string *conv; @@ -2151,6 +2179,20 @@ bool Item_varbinary::eq(const Item *arg, bool binary_cmp) const return FALSE; } + +Item *Item_varbinary::safe_charset_converter(CHARSET_INFO *tocs) +{ + Item_string *conv; + String tmp, *str= val_str(&tmp); + + if (!(conv= new Item_string(str->ptr(), str->length(), tocs))) + return NULL; + conv->str_value.copy(); + conv->str_value.shrink_to_length(); + return conv; +} + + /* Pack data in buffer for sending */ diff --git a/sql/item.h b/sql/item.h index 8de2adeb730..20d6718609c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -334,6 +334,7 @@ class Item_num: public Item { public: virtual Item_num *neg()= 0; + Item *safe_charset_converter(CHARSET_INFO *tocs); }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -835,6 +836,7 @@ public: // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; + virtual Item *safe_charset_converter(CHARSET_INFO *tocs); }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b68b20c32a3..e27cd7196ed 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -557,10 +557,15 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, Convert the default value from client character set into the column character set if necessary. */ - if (sql_field->def) + if (sql_field->def && cs != sql_field->def->collation.collation) { - sql_field->def= - sql_field->def->safe_charset_converter(cs); + if (!(sql_field->def= + sql_field->def->safe_charset_converter(cs))) + { + /* Could not convert */ + my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); + DBUG_RETURN(-1); + } } if (sql_field->sql_type == FIELD_TYPE_SET) From f334ea1fc6f4e9e5be334f4f4c62a3b25c365426 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Wed, 13 Jul 2005 13:48:13 +0400 Subject: [PATCH 02/39] Implementation of Monty's idea: Now we can open mysql.proc table for lookup of stored routines definitions even if we already have some tables open and locked. To avoid deadlocks in this case we have to put certain restrictions on locking of mysql.proc table. This allows to use stored routines safely under LOCK TABLES without explicitly mentioning mysql.proc in the list of locked tables. It also fixes bug #11554 "Server crashes on statement indirectly using non-cached function". --- mysql-test/r/sp-error.result | 15 +- mysql-test/r/sp-threads.result | 9 + mysql-test/t/sp-error.test | 33 +++- mysql-test/t/sp-threads.test | 19 +++ sql/lock.cc | 13 ++ sql/mysql_priv.h | 2 +- sql/share/errmsg.txt | 2 + sql/sp.cc | 296 ++++++++++++++++++++------------- sql/sp.h | 3 - sql/sql_base.cc | 61 +++++-- sql/sql_class.cc | 50 +++++- sql/sql_class.h | 144 +++++++++------- sql/sql_lex.cc | 2 +- sql/sql_lex.h | 1 - sql/sql_table.cc | 4 +- sql/table.h | 7 + 16 files changed, 459 insertions(+), 202 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 0d624b30d9e..742e79df9df 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -286,6 +286,19 @@ ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable call p(42, @tmp_y, 43)| ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable drop procedure p| +create procedure p() begin end| +lock table t1 read| +call p()| +unlock tables| +drop procedure p| +lock tables t1 read, mysql.proc write| +ERROR HY000: You can't combine write-locking of system 'mysql.proc' table with other tables +lock tables mysql.proc write, mysql.user write| +ERROR HY000: You can't combine write-locking of system 'mysql.proc' table with other tables +lock tables t1 read, mysql.proc read| +unlock tables| +lock tables mysql.proc write| +unlock tables| create procedure bug1965() begin declare c cursor for select val from t1 order by valname; @@ -477,7 +490,7 @@ begin select * from t1; end| lock table t1 read| -call bug9566()| +alter procedure bug9566 comment 'Some comment'| ERROR HY000: Table 'proc' was not locked with LOCK TABLES unlock tables| drop procedure bug9566| diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result index a9d50e6e697..e6b8128c336 100644 --- a/mysql-test/r/sp-threads.result +++ b/mysql-test/r/sp-threads.result @@ -55,3 +55,12 @@ call bug11158(); unlock tables; drop procedure bug11158; drop table t1, t2; +drop function if exists bug11554; +drop view if exists v1; +create table t1 (i int); +create function bug11554 () returns int return 1; +create view v1 as select bug11554() as f; +insert into t1 (select f from v1); +drop function bug11554; +drop table t1; +drop view v1; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index a61c082fb30..62890757045 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -386,6 +386,29 @@ call p(42, @tmp_y, 43)| drop procedure p| +# +# Let us test that we can access mysql.proc table for routines +# definitions lookup without locking it explicitly. +# +create procedure p() begin end| +lock table t1 read| +# This should succeed +call p()| +unlock tables| +drop procedure p| +# Let us check restrictions which this ability puts on mysql.proc locking. +--error ER_WRONG_LOCK_OF_SYSTEM_TABLE +lock tables t1 read, mysql.proc write| +--error ER_WRONG_LOCK_OF_SYSTEM_TABLE +lock tables mysql.proc write, mysql.user write| +# Locking for read should be OK +lock tables t1 read, mysql.proc read| +unlock tables| +# You also should be able lock only mysql.proc for write +lock tables mysql.proc write| +unlock tables| + + # # BUG#1965 # @@ -676,9 +699,7 @@ create procedure bug6600() # BUG#9566: explicit LOCK TABLE and store procedures result in illegal state # # We should not think that mysql.proc table does not exist if we are unable -# to open it under LOCK TABLE or in prelocked mode. Probably this test -# should be removed when Monty will allow access to mysql.proc without -# locking it. +# to open it under LOCK TABLE or in prelocked mode. # --disable_warnings drop procedure if exists bug9566| @@ -688,9 +709,11 @@ begin select * from t1; end| lock table t1 read| -# This should fail because we forgot to lock mysql.proc table explicitly +# This should fail since we forgot to lock mysql.proc for writing +# explicitly, and we can't open mysql.proc for _writing_ if there +# are locked tables. --error 1100 -call bug9566()| +alter procedure bug9566 comment 'Some comment'| unlock tables| # This should succeed drop procedure bug9566| diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test index 8fec5d14bc1..4c192f3e96f 100644 --- a/mysql-test/t/sp-threads.test +++ b/mysql-test/t/sp-threads.test @@ -111,6 +111,25 @@ connection con1root; drop procedure bug11158; drop table t1, t2; +# +# BUG#11554: Server crashes on statement indirectly using non-cached function +# +--disable_warnings +drop function if exists bug11554; +drop view if exists v1; +--enable_warnings +create table t1 (i int); +create function bug11554 () returns int return 1; +create view v1 as select bug11554() as f; +connection con2root; +# This should not crash server +insert into t1 (select f from v1); +# Clean-up +connection con1root; +drop function bug11554; +drop table t1; +drop view v1; + # # BUG#NNNN: New bug synopsis # diff --git a/sql/lock.cc b/sql/lock.cc index e0a75a42661..7f3fe5ac5da 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -425,6 +425,19 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, tables+=table_ptr[i]->file->lock_count(); lock_count++; } + /* + To be able to open and lock for reading system tables like 'mysql.proc', + when we already have some tables opened and locked, and avoid deadlocks + we have to disallow write-locking of these tables with any other tables. + */ + if (table_ptr[i]->s->system_table && + table_ptr[i]->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE && + count != 1) + { + my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table_ptr[i]->s->db, + table_ptr[i]->s->table_name); + return 0; + } } if (!(sql_lock= (MYSQL_LOCK*) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9a3684c3865..b1007ea30b2 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -735,7 +735,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok); bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem, - bool *refresh); + bool *refresh, uint flags); TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table); TABLE *find_locked_table(THD *thd, const char *db,const char *table_name); bool reopen_table(TABLE *table,bool locked); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index bdcd88a7205..cb5db72e6e7 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5362,3 +5362,5 @@ ER_NO_DEFAULT_FOR_VIEW_FIELD eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value" ER_SP_NO_RECURSION eng "Recursive stored routines are not allowed." +ER_WRONG_LOCK_OF_SYSTEM_TABLE + eng "You can't combine write-locking of system '%-.64s.%-.64s' table with other tables" diff --git a/sql/sp.cc b/sql/sp.cc index 456248db66b..0270ec86ca6 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -61,57 +61,152 @@ bool mysql_proc_table_exists= 1; /* Tells what SP_DEFAULT_ACCESS should be mapped to */ #define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL -/* *opened=true means we opened ourselves */ -static int -db_find_routine_aux(THD *thd, int type, sp_name *name, - enum thr_lock_type ltype, TABLE **tablep, bool *opened) -{ - TABLE *table; - byte key[NAME_LEN*2+4+1]; // db, name, optional key length type - DBUG_ENTER("db_find_routine_aux"); - DBUG_PRINT("enter", ("type: %d name: %*s", - type, name->m_name.length, name->m_name.str)); - *opened= FALSE; - *tablep= 0; +/* + Close mysql.proc, opened with open_proc_table_for_read(). + + SYNOPSIS + close_proc_table() + thd Thread context +*/ + +static void close_proc_table(THD *thd) +{ + close_thread_tables(thd); + thd->pop_open_tables_state(); +} + + +/* + Open the mysql.proc table for read. + + SYNOPSIS + open_proc_table_for_read() + thd Thread context + + NOTES + Thanks to restrictions which we put on opening and locking of + this table for writing, we can open and lock it for reading + even when we already have some other tables open and locked. + One must call close_proc_table() to close table opened with + this call. + + RETURN + 0 Error + # Pointer to TABLE object of mysql.proc +*/ + +static TABLE *open_proc_table_for_read(THD *thd) +{ + TABLE_LIST tables; + TABLE *table; + bool old_open_tables= thd->open_tables != 0; + bool refresh; + DBUG_ENTER("open_proc_table"); /* Speed up things if mysql.proc doesn't exists. mysql_proc_table_exists is set when we create or read stored procedure or on flush privileges. */ - if (!mysql_proc_table_exists && ltype == TL_READ) - DBUG_RETURN(SP_OPEN_TABLE_FAILED); + if (!mysql_proc_table_exists) + DBUG_RETURN(0); - if (thd->lex->proc_table) - table= thd->lex->proc_table->table; - else - { - for (table= thd->open_tables ; table ; table= table->next) - if (strcmp(table->s->db, "mysql") == 0 && - strcmp(table->s->table_name, "proc") == 0) - break; - } - if (!table) - { - TABLE_LIST tables; + if (thd->push_open_tables_state()) + DBUG_RETURN(0); - memset(&tables, 0, sizeof(tables)); - tables.db= (char*)"mysql"; - tables.table_name= tables.alias= (char*)"proc"; - if (! (table= open_ltable(thd, &tables, ltype))) - { - /* - Under explicit LOCK TABLES or in prelocked mode we should not - say that mysql.proc table does not exist if we are unable to - open it since this condition may be transient. - */ - if (!(thd->locked_tables || thd->prelocked_mode)) - mysql_proc_table_exists= 0; - DBUG_RETURN(SP_OPEN_TABLE_FAILED); - } - *opened= TRUE; + bzero((char*) &tables, sizeof(tables)); + tables.db= (char*) "mysql"; + tables.table_name= tables.alias= (char*)"proc"; + if (!(table= open_table(thd, &tables, thd->mem_root, &refresh, + MYSQL_LOCK_IGNORE_FLUSH))) + { + thd->pop_open_tables_state(); + mysql_proc_table_exists= 0; + DBUG_RETURN(0); } - mysql_proc_table_exists= 1; + + DBUG_ASSERT(table->s->system_table); + + table->reginfo.lock_type= TL_READ; + /* + If we have other tables opened, we have to ensure we are not blocked + by a flush tables or global read lock, as this could lead to a deadlock + */ + if (!(thd->lock= mysql_lock_tables(thd, &table, 1, + old_open_tables ? + (MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK | + MYSQL_LOCK_IGNORE_FLUSH) : 0))) + { + close_proc_table(thd); + DBUG_RETURN(0); + } + DBUG_RETURN(table); +} + + +/* + Open the mysql.proc table for update. + + SYNOPSIS + open_proc_table_for_update() + thd Thread context + + NOTES + Table opened with this call should closed using close_thread_tables(). + + RETURN + 0 Error + # Pointer to TABLE object of mysql.proc +*/ + +static TABLE *open_proc_table_for_update(THD *thd) +{ + TABLE_LIST tables; + TABLE *table; + DBUG_ENTER("open_proc_table"); + + bzero((char*) &tables, sizeof(tables)); + tables.db= (char*) "mysql"; + tables.table_name= tables.alias= (char*)"proc"; + tables.lock_type= TL_WRITE; + + table= open_ltable(thd, &tables, TL_WRITE); + + /* + Under explicit LOCK TABLES or in prelocked mode we should not + say that mysql.proc table does not exist if we are unable to + open and lock it for writing since this condition may be + transient. + */ + if (!(thd->locked_tables || thd->prelocked_mode) || table) + mysql_proc_table_exists= test(table); + + DBUG_RETURN(table); +} + + +/* + Find row in open mysql.proc table representing stored routine. + + SYNOPSIS + db_find_routine_aux() + thd Thread context + type Type of routine to find (function or procedure) + name Name of routine + table TABLE object for open mysql.proc table. + + RETURN VALUE + SP_OK - Routine found + SP_KEY_NOT_FOUND- No routine with given name +*/ + +static int +db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table) +{ + byte key[NAME_LEN*2+4+1]; // db, name, optional key length type + DBUG_ENTER("db_find_routine_aux"); + DBUG_PRINT("enter", ("type: %d name: %*s", + type, name->m_name.length, name->m_name.str)); /* Create key to find row. We have to use field->store() to be able to @@ -121,9 +216,7 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, same fields. */ if (name->m_name.length > table->field[1]->field_length) - { DBUG_RETURN(SP_KEY_NOT_FOUND); - } table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin); table->field[1]->store(name->m_name.str, name->m_name.length, &my_charset_bin); @@ -134,15 +227,33 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, if (table->file->index_read_idx(table->record[0], 0, key, table->key_info->key_length, HA_READ_KEY_EXACT)) - { DBUG_RETURN(SP_KEY_NOT_FOUND); - } - *tablep= table; DBUG_RETURN(SP_OK); } +/* + Find routine definition in mysql.proc table and create corresponding + sp_head object for it. + + SYNOPSIS + db_find_routine() + thd Thread context + type Type of routine (TYPE_ENUM_PROCEDURE/...) + name Name of routine + sphp Out parameter in which pointer to created sp_head + object is returned (0 in case of error). + + NOTE + This function may damage current LEX during execution, so it is good + idea to create temporary LEX and make it active before calling it. + + RETURN VALUE + 0 - Success + non-0 - Error (may be one of special codes like SP_KEY_NOT_FOUND) +*/ + static int db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) { @@ -150,7 +261,6 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) TABLE *table; const char *params, *returns, *body; int ret; - bool opened; const char *definer; longlong created; longlong modified; @@ -164,8 +274,11 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) DBUG_PRINT("enter", ("type: %d name: %*s", type, name->m_name.length, name->m_name.str)); - ret= db_find_routine_aux(thd, type, name, TL_READ, &table, &opened); - if (ret != SP_OK) + *sphp= 0; // In case of errors + if (!(table= open_proc_table_for_read(thd))) + DBUG_RETURN(SP_OPEN_TABLE_FAILED); + + if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK) goto done; if (table->s->fields != MYSQL_PROC_FIELD_COUNT) @@ -257,11 +370,8 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) chistics.comment.str= ptr; chistics.comment.length= length; - if (opened) - { - opened= FALSE; - close_thread_tables(thd, 0, 1); - } + close_proc_table(thd); + table= 0; { String defstr; @@ -337,9 +447,8 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) } done: - - if (opened) - close_thread_tables(thd); + if (table) + close_proc_table(thd); DBUG_RETURN(ret); } @@ -362,7 +471,6 @@ db_create_routine(THD *thd, int type, sp_head *sp) { int ret; TABLE *table; - TABLE_LIST tables; char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; char olddb[128]; bool dbchanged; @@ -377,11 +485,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) goto done; } - memset(&tables, 0, sizeof(tables)); - tables.db= (char*)"mysql"; - tables.table_name= tables.alias= (char*)"proc"; - - if (! (table= open_ltable(thd, &tables, TL_WRITE))) + if (!(table= open_proc_table_for_update(thd))) ret= SP_OPEN_TABLE_FAILED; else { @@ -491,20 +595,18 @@ db_drop_routine(THD *thd, int type, sp_name *name) { TABLE *table; int ret; - bool opened; DBUG_ENTER("db_drop_routine"); DBUG_PRINT("enter", ("type: %d name: %*s", type, name->m_name.length, name->m_name.str)); - ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened); - if (ret == SP_OK) + if (!(table= open_proc_table_for_update(thd))) + DBUG_RETURN(SP_OPEN_TABLE_FAILED); + if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK) { if (table->file->delete_row(table->record[0])) ret= SP_DELETE_ROW_FAILED; } - - if (opened) - close_thread_tables(thd); + close_thread_tables(thd); DBUG_RETURN(ret); } @@ -519,8 +621,9 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) DBUG_PRINT("enter", ("type: %d name: %*s", type, name->m_name.length, name->m_name.str)); - ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened); - if (ret == SP_OK) + if (!(table= open_proc_table_for_update(thd))) + DBUG_RETURN(SP_OPEN_TABLE_FAILED); + if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK) { store_record(table,record[1]); table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; @@ -538,8 +641,7 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if ((table->file->update_row(table->record[1],table->record[0]))) ret= SP_WRITE_ROW_FAILED; } - if (opened) - close_thread_tables(thd); + close_thread_tables(thd); DBUG_RETURN(ret); } @@ -741,20 +843,9 @@ sp_drop_db_routines(THD *thd, char *db) memset(key+keylen, (int)' ', 64-keylen); // Pad with space keylen= sizeof(key); - for (table= thd->open_tables ; table ; table= table->next) - if (strcmp(table->s->db, "mysql") == 0 && - strcmp(table->s->table_name, "proc") == 0) - break; - if (! table) - { - TABLE_LIST tables; - - memset(&tables, 0, sizeof(tables)); - tables.db= (char*)"mysql"; - tables.table_name= tables.alias= (char*)"proc"; - if (! (table= open_ltable(thd, &tables, TL_WRITE))) - DBUG_RETURN(SP_OPEN_TABLE_FAILED); - } + ret= SP_OPEN_TABLE_FAILED; + if (!(table= open_proc_table_for_update(thd))) + goto err; ret= SP_OK; table->file->ha_index_init(0); @@ -764,7 +855,8 @@ sp_drop_db_routines(THD *thd, char *db) int nxtres; bool deleted= FALSE; - do { + do + { if (! table->file->delete_row(table->record[0])) deleted= TRUE; /* We deleted something */ else @@ -784,6 +876,7 @@ sp_drop_db_routines(THD *thd, char *db) close_thread_tables(thd); +err: DBUG_RETURN(ret); } @@ -977,9 +1070,7 @@ sp_find_function(THD *thd, sp_name *name, bool cache_only) if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)) && !cache_only) { - if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) != SP_OK) - sp= NULL; - else + if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) == SP_OK) sp_cache_insert(&thd->sp_func_cache, sp); } DBUG_RETURN(sp); @@ -1057,26 +1148,6 @@ sp_show_status_function(THD *thd, const char *wild) } -bool -sp_function_exists(THD *thd, sp_name *name) -{ - TABLE *table; - bool ret= FALSE; - bool opened= FALSE; - DBUG_ENTER("sp_function_exists"); - - if (sp_cache_lookup(&thd->sp_func_cache, name) || - db_find_routine_aux(thd, TYPE_ENUM_FUNCTION, - name, TL_READ, - &table, &opened) == SP_OK) - ret= TRUE; - if (opened) - close_thread_tables(thd, 0, 1); - thd->clear_error(); - DBUG_RETURN(ret); -} - - byte * sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first) { @@ -1185,7 +1256,6 @@ sp_cache_routines(THD *thd, LEX *lex) thd->lex= newlex; /* Pass hint pointer to mysql.proc table */ - newlex->proc_table= oldlex->proc_table; newlex->current_select= NULL; name.m_name.str= strchr(name.m_qname.str, '.'); name.m_db.length= name.m_name.str - name.m_qname.str; diff --git a/sql/sp.h b/sql/sp.h index 16d79026132..499d2f3d38f 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -74,9 +74,6 @@ sp_show_create_function(THD *thd, sp_name *name); int sp_show_status_function(THD *thd, const char *wild); -bool -sp_function_exists(THD *thd, sp_name *name); - /* * For precaching of functions and procedures diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 383adcadc6a..f19252fbbdc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -542,10 +542,9 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived, bool close_thread_table(THD *thd, TABLE **table_ptr) { - DBUG_ENTER("close_thread_table"); - bool found_old_table= 0; TABLE *table= *table_ptr; + DBUG_ENTER("close_thread_table"); DBUG_ASSERT(table->key_read == 0); DBUG_ASSERT(table->file->inited == handler::NONE); @@ -972,18 +971,34 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) } -/****************************************************************************** -** open a table -** Uses a cache of open tables to find a table not in use. -** If refresh is a NULL pointer, then the is no version number checking and -** the table is not put in the thread-open-list -** If the return value is NULL and refresh is set then one must close -** all tables and retry the open -******************************************************************************/ +/* + Open a table. + + SYNOPSIS + open_table() + thd Thread context + table_list Open first table in list + refresh Pointer to memory that will be set to 1 if + we need to close all tables and reopen them + If this is a NULL pointer, then the is no version + number checking and the table is not put in the + thread-open-list + flags Bitmap of flags to modify how open works: + MYSQL_LOCK_IGNORE_FLUSH - Open table even if someone + has done a flush or namelock on it. + + IMPLEMENTATION + Uses a cache of open tables to find a table not in use. + + RETURN + NULL Open failed. If refresh is set then one should close + all other tables and retry the open + # Success. Pointer to TABLE object for open table. +*/ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, - bool *refresh) + bool *refresh, uint flags) { reg1 TABLE *table; char key[MAX_DBKEY_LENGTH]; @@ -1096,9 +1111,16 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, { if (table->s->version != refresh_version) { + if (flags & MYSQL_LOCK_IGNORE_FLUSH) + { + /* Force close at once after usage */ + thd->version= table->s->version; + continue; + } + /* - ** There is a refresh in progress for this table - ** Wait until the table is freed or the thread is killed. + There is a refresh in progress for this table + Wait until the table is freed or the thread is killed. */ close_old_data_files(thd,thd->open_tables,0,0); if (table->in_use != thd) @@ -1681,6 +1703,15 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, if (error == 5) DBUG_RETURN(0); // we have just opened VIEW + /* + We can't mark all tables in 'mysql' database as system since we don't + allow to lock such tables for writing with any other tables (even with + other system tables) and some privilege tables need this. + */ + if (!my_strcasecmp(system_charset_info, db, "mysql") && + !my_strcasecmp(system_charset_info, name, "proc")) + entry->s->system_table= 1; + if (Table_triggers_list::check_n_load(thd, db, name, entry)) goto err; @@ -1835,7 +1866,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter) } (*counter)++; if (!tables->table && - !(tables->table= open_table(thd, tables, &new_frm_mem, &refresh))) + !(tables->table= open_table(thd, tables, &new_frm_mem, &refresh, 0))) { free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); if (tables->view) @@ -2010,7 +2041,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) thd->current_tablenr= 0; /* open_ltable can be used only for BASIC TABLEs */ table_list->required_type= FRMTYPE_TABLE; - while (!(table= open_table(thd, table_list, thd->mem_root, &refresh)) && + while (!(table= open_table(thd, table_list, thd->mem_root, &refresh, 0)) && refresh) ; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index bf6f41d00ed..d0ac1a16f6b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -156,6 +156,14 @@ bool foreign_key_prefix(Key *a, Key *b) /**************************************************************************** ** Thread specific functions ****************************************************************************/ + +Open_tables_state::Open_tables_state() + :version(refresh_version) +{ + reset_open_tables_state(); +} + + /* Pass nominal parameters to Statement constructor only to ensure that the destructor works OK in case of error. The main_mem_root will be @@ -164,6 +172,7 @@ bool foreign_key_prefix(Key *a, Key *b) THD::THD() :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0), + Open_tables_state(), user_time(0), global_read_lock(0), is_fatal_error(0), rand_used(0), time_zone_used(0), last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0), @@ -181,10 +190,8 @@ THD::THD() db_length= col_access=0; query_error= tmp_table_used= 0; next_insert_id=last_insert_id=0; - open_tables= temporary_tables= handler_tables= derived_tables= 0; hash_clear(&handler_tables_hash); tmp_table=0; - lock=locked_tables=0; used_tables=0; cuted_fields= sent_row_count= 0L; limit_found_rows= 0; @@ -230,7 +237,6 @@ THD::THD() #ifndef NO_EMBEDDED_ACCESS_CHECKS db_access=NO_ACCESS; #endif - version=refresh_version; // For boot *scramble= '\0'; init(); @@ -259,7 +265,6 @@ THD::THD() tablespace_op=FALSE; ulong tmp=sql_rnd_with_mutex(); randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id); - prelocked_mode= NON_PRELOCKED; } @@ -1775,3 +1780,40 @@ void THD::set_status_var_init() { bzero((char*) &status_var, sizeof(status_var)); } + +/**************************************************************************** + Handling of open and locked tables states. + + This is used when we want to open/lock (and then close) some tables when + we already have a set of tables open and locked. We use these methods for + access to mysql.proc table to find definitions of stored routines. +****************************************************************************/ + +bool THD::push_open_tables_state() +{ + Open_tables_state *state; + DBUG_ENTER("push_open_table_state"); + /* Currently we only push things one level */ + DBUG_ASSERT(open_state_list.elements == 0); + + if (!(state= (Open_tables_state*) alloc(sizeof(*state)))) + DBUG_RETURN(1); // Fatal error is set + /* Store state for currently open tables */ + state->set_open_tables_state(this); + if (open_state_list.push_back(state, mem_root)) + DBUG_RETURN(1); // Fatal error is set + reset_open_tables_state(); + DBUG_RETURN(0); +} + +void THD::pop_open_tables_state() +{ + Open_tables_state *state; + DBUG_ENTER("pop_open_table_state"); + /* Currently we only push things one level */ + DBUG_ASSERT(open_state_list.elements == 1); + + state= open_state_list.pop(); + set_open_tables_state(state); + DBUG_VOID_RETURN; +} diff --git a/sql/sql_class.h b/sql/sql_class.h index 5642fa0d6af..625b9c27b44 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -932,13 +932,94 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1, PRELOCKED_UNDER_LOCK_TABLES= 2}; +/* + Class that holds information about tables which were open and locked + by the thread. It is also used to save/restore this information in + push_open_tables_state()/pop_open_tables_state(). +*/ + +class Open_tables_state +{ +public: + /* + open_tables - list of regular tables in use by this thread + temporary_tables - list of temp tables in use by this thread + handler_tables - list of tables that were opened with HANDLER OPEN + and are still in use by this thread + */ + TABLE *open_tables, *temporary_tables, *handler_tables, *derived_tables; + /* + During a MySQL session, one can lock tables in two modes: automatic + or manual. In automatic mode all necessary tables are locked just before + statement execution, and all acquired locks are stored in 'lock' + member. Unlocking takes place automatically as well, when the + statement ends. + Manual mode comes into play when a user issues a 'LOCK TABLES' + statement. In this mode the user can only use the locked tables. + Trying to use any other tables will give an error. The locked tables are + stored in 'locked_tables' member. Manual locking is described in + the 'LOCK_TABLES' chapter of the MySQL manual. + See also lock_tables() for details. + */ + MYSQL_LOCK *lock; + /* + Tables that were locked with explicit or implicit LOCK TABLES. + (Implicit LOCK TABLES happens when we are prelocking tables for + execution of statement which uses stored routines. See description + THD::prelocked_mode for more info.) + */ + MYSQL_LOCK *locked_tables; + /* + prelocked_mode_type enum and prelocked_mode member are used for + indicating whenever "prelocked mode" is on, and what type of + "prelocked mode" is it. + + Prelocked mode is used for execution of queries which explicitly + or implicitly (via views or triggers) use functions, thus may need + some additional tables (mentioned in query table list) for their + execution. + + First open_tables() call for such query will analyse all functions + used by it and add all additional tables to table its list. It will + also mark this query as requiring prelocking. After that lock_tables() + will issue implicit LOCK TABLES for the whole table list and change + thd::prelocked_mode to non-0. All queries called in functions invoked + by the main query will use prelocked tables. Non-0 prelocked_mode + will also surpress mentioned analysys in those queries thus saving + cycles. Prelocked mode will be turned off once close_thread_tables() + for the main query will be called. + + Note: Since not all "tables" present in table list are really locked + thd::prelocked_mode does not imply thd::locked_tables. + */ + prelocked_mode_type prelocked_mode; + ulong version; + uint current_tablenr; + + Open_tables_state(); + + void set_open_tables_state(Open_tables_state *state) + { + *this= *state; + } + + void reset_open_tables_state() + { + open_tables= temporary_tables= handler_tables= derived_tables= 0; + lock= locked_tables= 0; + prelocked_mode= NON_PRELOCKED; + } +}; + + /* For each client connection we create a separate thread with THD serving as a thread/connection descriptor */ class THD :public ilink, - public Statement + public Statement, + public Open_tables_state { public: #ifdef EMBEDDED_LIBRARY @@ -1006,34 +1087,6 @@ public: ulong master_access; /* Global privileges from mysql.user */ ulong db_access; /* Privileges for current db */ - /* - open_tables - list of regular tables in use by this thread - temporary_tables - list of temp tables in use by this thread - handler_tables - list of tables that were opened with HANDLER OPEN - and are still in use by this thread - */ - TABLE *open_tables,*temporary_tables, *handler_tables, *derived_tables; - /* - During a MySQL session, one can lock tables in two modes: automatic - or manual. In automatic mode all necessary tables are locked just before - statement execution, and all acquired locks are stored in 'lock' - member. Unlocking takes place automatically as well, when the - statement ends. - Manual mode comes into play when a user issues a 'LOCK TABLES' - statement. In this mode the user can only use the locked tables. - Trying to use any other tables will give an error. The locked tables are - stored in 'locked_tables' member. Manual locking is described in - the 'LOCK_TABLES' chapter of the MySQL manual. - See also lock_tables() for details. - */ - MYSQL_LOCK *lock; /* Current locks */ - /* - Tables that were locked with explicit or implicit LOCK TABLES. - (Implicit LOCK TABLES happens when we are prelocking tables for - execution of statement which uses stored routines. See description - THD::prelocked_mode for more info.) - */ - MYSQL_LOCK *locked_tables; HASH handler_tables_hash; /* One thread can hold up to one named user-level lock. This variable @@ -1150,6 +1203,7 @@ public: List warn_list; uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint total_warn_count; + List open_state_list; /* Id of current query. Statement can be reused to execute several queries query_id is global in context of the whole MySQL server. @@ -1159,7 +1213,7 @@ public: update auto-updatable fields (like auto_increment and timestamp). */ query_id_t query_id, warn_id; - ulong version, options, thread_id, col_access; + ulong options, thread_id, col_access; /* Statement id is thread-wide. This counter is used to generate ids */ ulong statement_id_counter; @@ -1167,7 +1221,7 @@ public: ulong row_count; // Row counter, mainly for errors and warnings long dbug_thread_id; pthread_t real_id; - uint current_tablenr,tmp_table,global_read_lock; + uint tmp_table, global_read_lock; uint server_status,open_options,system_thread; uint32 db_length; uint select_number; //number of select (used for EXPLAIN) @@ -1218,31 +1272,6 @@ public: long long_value; } sys_var_tmp; - /* - prelocked_mode_type enum and prelocked_mode member are used for - indicating whenever "prelocked mode" is on, and what type of - "prelocked mode" is it. - - Prelocked mode is used for execution of queries which explicitly - or implicitly (via views or triggers) use functions, thus may need - some additional tables (mentioned in query table list) for their - execution. - - First open_tables() call for such query will analyse all functions - used by it and add all additional tables to table its list. It will - also mark this query as requiring prelocking. After that lock_tables() - will issue implicit LOCK TABLES for the whole table list and change - thd::prelocked_mode to non-0. All queries called in functions invoked - by the main query will use prelocked tables. Non-0 prelocked_mode - will also surpress mentioned analysys in those queries thus saving - cycles. Prelocked mode will be turned off once close_thread_tables() - for the main query will be called. - - Note: Since not all "tables" present in table list are really locked - thd::relocked_mode does not imply thd::locked_tables. - */ - prelocked_mode_type prelocked_mode; - THD(); ~THD(); @@ -1428,8 +1457,11 @@ public: (variables.sql_mode & MODE_STRICT_ALL_TABLES))); } void set_status_var_init(); + bool push_open_tables_state(); + void pop_open_tables_state(); }; + #define tmp_disable_binlog(A) \ {ulong tmp_disable_binlog__save_options= (A)->options; \ (A)->options&= ~OPTION_BIN_LOG diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 20f5092c5ce..785da5e6e64 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -145,7 +145,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->found_semicolon= 0; lex->safe_to_cache_query= 1; lex->time_zone_tables_used= 0; - lex->leaf_tables_insert= lex->proc_table= lex->query_tables= 0; + lex->leaf_tables_insert= lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; lex->variables_used= 0; lex->select_lex.parent_lex= lex; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 15306ab5b34..f7e9c29828b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -719,7 +719,6 @@ typedef struct st_lex function) */ TABLE_LIST **query_tables_last; - TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */ /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5a93176b922..9e6d12eba13 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1760,7 +1760,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, create_info, *extra_fields, *keys, 0, select_field_count)) { - if (!(table= open_table(thd, create_table, thd->mem_root, (bool*) 0))) + if (!(table= open_table(thd, create_table, thd->mem_root, (bool*)0, 0))) quick_rm_table(create_info->db_type, create_table->db, table_case_name(create_info, create_table->table_name)); } @@ -3571,7 +3571,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, bzero((void*) &tbl, sizeof(tbl)); tbl.db= new_db; tbl.table_name= tbl.alias= tmp_name; - new_table= open_table(thd, &tbl, thd->mem_root, 0); + new_table= open_table(thd, &tbl, thd->mem_root, 0, 0); } else { diff --git a/sql/table.h b/sql/table.h index d0c998c4c10..e5653a1f213 100644 --- a/sql/table.h +++ b/sql/table.h @@ -163,6 +163,13 @@ typedef struct st_table_share my_bool crashed; my_bool is_view; my_bool name_lock, replace_with_name_lock; + /* + TRUE if this is a system table like 'mysql.proc', which we want to be + able to open and lock even when we already have some tables open and + locked. To avoid deadlocks we have to put certain restrictions on + locking of this table for writing. FALSE - otherwise. + */ + my_bool system_table; } TABLE_SHARE; From a37eea1993e41700f382f2f03d938208b8ed79b1 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Wed, 13 Jul 2005 16:22:36 +0400 Subject: [PATCH 03/39] Fixed trigger.test after fixing bug #11554 "Server crashes on statement indirectly using non-cached function". --- mysql-test/r/trigger.result | 12 +++++++++--- mysql-test/t/trigger.test | 25 +++++++++++-------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 746c900d743..60aa358a9f1 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -232,9 +232,6 @@ if new.id > f1() then set new.id:= f1(); end if; end| -select f1(); -f1() -10 insert into t1 values (1, "first"); insert into t1 values (f1(), "max"); select * from t1; @@ -573,3 +570,12 @@ i k ts 1 1 0000-00-00 00:00:00 2 2 0000-00-00 00:00:00 drop table t1, t2; +drop function if exists bug5893; +create table t1 (col1 int, col2 int); +insert into t1 values (1, 2); +create function bug5893 () returns int return 5; +create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); +drop function bug5893; +update t1 set col2 = 4; +ERROR 42000: FUNCTION test.bug5893 does not exist +drop table t1; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 229cbd3c79c..39638cc437e 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -244,8 +244,6 @@ begin end if; end| delimiter ;| -# Remove this once bug #11554 will be fixed. -select f1(); insert into t1 values (1, "first"); insert into t1 values (f1(), "max"); select * from t1; @@ -578,15 +576,14 @@ drop table t1, t2; # Test for bug #5893 "Triggers with dropped functions cause crashes" # Appropriate error should be reported instead of crash. -# Had to disable this test until bug #11554 will be fixed. -#--disable_warnings -#drop function if exists bug5893; -#--enable_warnings -#create table t1 (col1 int, col2 int); -#insert into t1 values (1, 2); -#create function bug5893 () returns int return 5; -#create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); -#drop function bug5893; -#--error 1305 -#update t1 set col2 = 4; -#drop table t1; +--disable_warnings +drop function if exists bug5893; +--enable_warnings +create table t1 (col1 int, col2 int); +insert into t1 values (1, 2); +create function bug5893 () returns int return 5; +create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); +drop function bug5893; +--error 1305 +update t1 set col2 = 4; +drop table t1; From bf7b47d92e3ebf3f9d9199a5442e87f1d16208d8 Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 13 Jul 2005 16:13:36 +0300 Subject: [PATCH 04/39] sql_update.cc: mysql_update(): Call handler::unlock_row() also in the first while loop. This patch is from Heikki, and it was approved by Sergei Golubchik. --- sql/sql_update.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ce4a7d6394e..8a5b4ad8eae 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -337,6 +337,8 @@ int mysql_update(THD *thd, break; } } + else + table->file->unlock_row(); } if (thd->killed && !error) error= 1; // Aborted From bef558b7ee2ebfd091949194354e4b4c33ef12fc Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Wed, 13 Jul 2005 17:38:55 +0400 Subject: [PATCH 05/39] - a fix for Bug#11458 "Prepared statement with subselects return random data": remove the fix for another bug (8807) that added OUTER_REF_TABLE_BIT to all subqueries that used a placeholder to prevent their evaluation at prepare. As this bit hanged in Item_subselect::used_tables_cache for ever, a constant subquery with a placeholder was never evaluated as such, which caused wrong choice of the execution plan for the statement. - to fix Bug#8807 backport a better fix from 5.0 - post-review fixes. --- mysql-test/r/ps.result | 57 +++++++++++++++++++++++++++++++++++ mysql-test/t/ps.test | 68 ++++++++++++++++++++++++++++++++++++++++++ sql/item.cc | 29 +----------------- sql/item.h | 1 - sql/item_subselect.h | 1 - sql/mysql_priv.h | 2 ++ sql/sql_lex.h | 1 + sql/sql_parse.cc | 8 +++++ sql/sql_prepare.cc | 13 +++++--- 9 files changed, 146 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index ca38f1c75cb..b1b06dc4019 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -563,3 +563,60 @@ execute stmt; execute stmt; deallocate prepare stmt; drop table t1; +create table t1 ( +id int(11) unsigned not null primary key auto_increment, +partner_id varchar(35) not null, +t1_status_id int(10) unsigned +); +insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"), +("3", "partner3", "10"), ("4", "partner4", "10"); +create table t2 ( +id int(11) unsigned not null default '0', +t1_line_id int(11) unsigned not null default '0', +article_id varchar(20), +sequence int(11) not null default '0', +primary key (id,t1_line_id) +); +insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"), +("2", "2", "sup", "2"), ("2", "3", "sup", "3"), +("2", "4", "imp", "4"), ("3", "1", "sup", "0"), +("4", "1", "sup", "0"); +create table t3 ( +id int(11) not null default '0', +preceeding_id int(11) not null default '0', +primary key (id,preceeding_id) +); +create table t4 ( +user_id varchar(50) not null, +article_id varchar(20) not null, +primary key (user_id,article_id) +); +insert into t4 values("nicke", "imp"); +prepare stmt from +'select distinct t1.partner_id +from t1 left join t3 on t1.id = t3.id + left join t1 pp on pp.id = t3.preceeding_id +where + exists ( + select * + from t2 as pl_inner + where pl_inner.id = t1.id + and pl_inner.sequence <= ( + select min(sequence) from t2 pl_seqnr + where pl_seqnr.id = t1.id + ) + and exists ( + select * from t4 + where t4.article_id = pl_inner.article_id + and t4.user_id = ? + ) + ) + and t1.id = ? +group by t1.id +having count(pp.id) = 0'; +set @user_id = 'nicke'; +set @id = '2'; +execute stmt using @user_id, @id; +partner_id +execute stmt using @user_id, @id; +partner_id diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index bb1052c7337..24276acf933 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -581,3 +581,71 @@ execute stmt; execute stmt; deallocate prepare stmt; drop table t1; + +# +# Bug#11458 "Prepared statement with subselects return random data": +# drop PARAM_TABLE_BIT from the list of tables used by a subquery +# +create table t1 ( + id int(11) unsigned not null primary key auto_increment, + partner_id varchar(35) not null, + t1_status_id int(10) unsigned +); + +insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"), + ("3", "partner3", "10"), ("4", "partner4", "10"); + +create table t2 ( + id int(11) unsigned not null default '0', + t1_line_id int(11) unsigned not null default '0', + article_id varchar(20), + sequence int(11) not null default '0', + primary key (id,t1_line_id) +); + +insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"), + ("2", "2", "sup", "2"), ("2", "3", "sup", "3"), + ("2", "4", "imp", "4"), ("3", "1", "sup", "0"), + ("4", "1", "sup", "0"); + +create table t3 ( + id int(11) not null default '0', + preceeding_id int(11) not null default '0', + primary key (id,preceeding_id) +); + +create table t4 ( + user_id varchar(50) not null, + article_id varchar(20) not null, + primary key (user_id,article_id) +); + +insert into t4 values("nicke", "imp"); + +prepare stmt from +'select distinct t1.partner_id +from t1 left join t3 on t1.id = t3.id + left join t1 pp on pp.id = t3.preceeding_id +where + exists ( + select * + from t2 as pl_inner + where pl_inner.id = t1.id + and pl_inner.sequence <= ( + select min(sequence) from t2 pl_seqnr + where pl_seqnr.id = t1.id + ) + and exists ( + select * from t4 + where t4.article_id = pl_inner.article_id + and t4.user_id = ? + ) + ) + and t1.id = ? +group by t1.id +having count(pp.id) = 0'; +set @user_id = 'nicke'; +set @id = '2'; +execute stmt using @user_id, @id; +execute stmt using @user_id, @id; + diff --git a/sql/item.cc b/sql/item.cc index 3bdaf856f2a..19b88c115b9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -889,6 +889,7 @@ void Item_param::set_null() max_length= 0; decimals= 0; state= NULL_VALUE; + item_type= Item::NULL_ITEM; DBUG_VOID_RETURN; } @@ -1339,34 +1340,6 @@ bool Item_param::convert_str_value(THD *thd) return rc; } -bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) -{ - DBUG_ASSERT(fixed == 0); - SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select; - - /* - Parameters in a subselect should mark the subselect as not constant - during prepare - */ - if (state == NO_VALUE) - { - /* - SELECT_LEX_UNIT::item set only for subqueries, so test of it presence - can be barrier to stop before derived table SELECT or very outer SELECT - */ - for(; - cursel->master_unit()->item; - cursel= cursel->outer_select()) - { - Item_subselect *subselect_item= cursel->master_unit()->item; - subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; - subselect_item->const_item_cache= 0; - } - } - fixed= 1; - return 0; -} - bool Item_param::basic_const_item() const { diff --git a/sql/item.h b/sql/item.h index 8de2adeb730..a8b0bfe9512 100644 --- a/sql/item.h +++ b/sql/item.h @@ -564,7 +564,6 @@ public: bool get_time(TIME *tm); bool get_date(TIME *tm, uint fuzzydate); int save_in_field(Field *field, bool no_conversions); - bool fix_fields(THD *, struct st_table_list *, Item **); void set_null(); void set_int(longlong i, uint32 max_length_arg); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 20ba838e61c..dec32398a80 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -119,7 +119,6 @@ public: friend class Item_in_optimizer; friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **); friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **); - friend bool Item_param::fix_fields(THD *, TABLE_LIST *, Item **); }; /* single value subselect */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index cc58e34d582..953bcf5585c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -251,6 +251,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define UNCACHEABLE_SIDEEFFECT 4 // forcing to save JOIN for explain #define UNCACHEABLE_EXPLAIN 8 +/* Don't evaluate subqueries in prepare even if they're not correlated */ +#define UNCACHEABLE_PREPARE 16 #ifdef EXTRA_DEBUG /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 927982e444f..07b5c9d8edf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -257,6 +257,7 @@ public: UNCACHEABLE_RAND UNCACHEABLE_SIDEEFFECT UNCACHEABLE_EXPLAIN + UNCACHEABLE_PREPARE */ uint8 uncacheable; enum sub_select_type linkage; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d7fd3239df5..dc55a842263 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4123,6 +4123,14 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->select_number= ++lex->thd->select_number; select_lex->init_query(); select_lex->init_select(); + /* + Don't evaluate this subquery during statement prepare even if + it's a constant one. The flag is switched off in the end of + mysql_stmt_prepare. + */ + if (lex->thd->current_arena->is_stmt_prepare()) + select_lex->uncacheable|= UNCACHEABLE_PREPARE; + if (move_down) { lex->subqueries= TRUE; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9e2612c5661..f7e2bd0467e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1657,13 +1657,18 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, { stmt->setup_set_params(); SELECT_LEX *sl= stmt->lex->all_selects_list; - /* - Save WHERE clause pointers, because they may be changed during query - optimisation. - */ for (; sl; sl= sl->next_select_in_list()) { + /* + Save WHERE clause pointers, because they may be changed + during query optimisation. + */ sl->prep_where= sl->where; + /* + Switch off a temporary flag that prevents evaluation of + subqueries in statement prepare. + */ + sl->uncacheable&= ~UNCACHEABLE_PREPARE; } stmt->state= Item_arena::PREPARED; } From ae949ccdd59255f7f52cc17d201a485e1eb871b6 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Wed, 13 Jul 2005 15:55:22 +0200 Subject: [PATCH 06/39] 4.1.13 has been cloned off --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 0889e9a3257..af7ce8b1c3d 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 4.1.13) +AM_INIT_AUTOMAKE(mysql, 4.1.14) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -16,7 +16,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=4 NDB_VERSION_MINOR=1 -NDB_VERSION_BUILD=13 +NDB_VERSION_BUILD=14 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 2dc2ec3ef75f618a2042d10d76c51735e3a2ae7c Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Wed, 13 Jul 2005 18:01:04 +0400 Subject: [PATCH 07/39] Cleanup after test for Bug#11458 --- mysql-test/r/ps.result | 2 ++ mysql-test/t/ps.test | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index b1b06dc4019..566dac07fd5 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -620,3 +620,5 @@ execute stmt using @user_id, @id; partner_id execute stmt using @user_id, @id; partner_id +deallocate prepare stmt; +drop table t1, t2, t3, t4; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 24276acf933..a25d4447c20 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -648,4 +648,5 @@ set @user_id = 'nicke'; set @id = '2'; execute stmt using @user_id, @id; execute stmt using @user_id, @id; - +deallocate prepare stmt; +drop table t1, t2, t3, t4; From 1755df76498e9ce0941800525a488ae45b841074 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Wed, 13 Jul 2005 23:43:46 +0400 Subject: [PATCH 08/39] A fix and a test case for Bug#9379 (collation of a parameter marker is binary). --- mysql-test/r/ps.result | 19 +++++++++++++++++++ mysql-test/t/ps.test | 16 ++++++++++++++++ sql/item.cc | 3 +++ sql/item_func.cc | 15 ++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 566dac07fd5..cdba113ae40 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -622,3 +622,22 @@ execute stmt using @user_id, @id; partner_id deallocate prepare stmt; drop table t1, t2, t3, t4; +prepare stmt from 'select ?=?'; +set @a='CHRISTINE '; +set @b='CHRISTINE'; +execute stmt using @a, @b; +?=? +1 +execute stmt using @a, @b; +?=? +1 +set @a=1, @b=2; +execute stmt using @a, @b; +?=? +0 +set @a='CHRISTINE '; +set @b='CHRISTINE'; +execute stmt using @a, @b; +?=? +1 +deallocate prepare stmt; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index a25d4447c20..0fa14024d11 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -650,3 +650,19 @@ execute stmt using @user_id, @id; execute stmt using @user_id, @id; deallocate prepare stmt; drop table t1, t2, t3, t4; + +# +# Bug#9379: make sure that Item::collation is reset when one sets +# a parameter marker from a string variable. +# +prepare stmt from 'select ?=?'; +set @a='CHRISTINE '; +set @b='CHRISTINE'; +execute stmt using @a, @b; +execute stmt using @a, @b; +set @a=1, @b=2; +execute stmt using @a, @b; +set @a='CHRISTINE '; +set @b='CHRISTINE'; +execute stmt using @a, @b; +deallocate prepare stmt; diff --git a/sql/item.cc b/sql/item.cc index 19b88c115b9..ed39fe177cd 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1089,6 +1089,7 @@ void Item_param::reset() to the binary log. */ str_value.set_charset(&my_charset_bin); + collation.set(&my_charset_bin, DERIVATION_COERCIBLE); state= NO_VALUE; maybe_null= 1; null_value= 0; @@ -1336,6 +1337,8 @@ bool Item_param::convert_str_value(THD *thd) */ str_value_ptr.set(str_value.ptr(), str_value.length(), str_value.charset()); + /* Synchronize item charset with value charset */ + collation.set(str_value.charset(), DERIVATION_COERCIBLE); } return rc; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 442ef15bba8..4e0b6d8813f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -188,7 +188,20 @@ bool Item_func::agg_arg_charsets(DTCollation &coll, break; // we cannot return here, we need to restore "arena". } conv->fix_fields(thd, 0, &conv); - *arg= conv; + /* + If in statement prepare, then we create a converter for two + constant items, do it once and then reuse it. + If we're in execution of a prepared statement, arena is NULL, + and the conv was created in runtime memory. This can be + the case only if the argument is a parameter marker ('?'), + because for all true constants the charset converter has already + been created in prepare. In this case register the change for + rollback. + */ + if (arena) + *arg= conv; + else + thd->change_item_tree(arg, conv); } if (arena) thd->restore_backup_item_arena(arena, &backup); From 14b93bf18ae7187f68c71c84102ef6ff2dd2078d Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Wed, 13 Jul 2005 23:51:09 +0400 Subject: [PATCH 09/39] Now when we create or drop trigger we will open only subject table and not all tables suggested by prelocking algorithm. Added test for bug #11889 "Server crashes when dropping trigger using stored routine" (which was fixed by previous patch). --- mysql-test/r/trigger.result | 3 ++- mysql-test/t/trigger.test | 6 +++++- sql/sql_trigger.cc | 7 ++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 60aa358a9f1..efd09ba08fc 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -297,7 +297,7 @@ drop trigger t1.trg; ERROR HY000: Trigger does not exist create view v1 as select * from t1; create trigger trg before insert on v1 for each row set @a:=1; -ERROR HY000: Trigger's 'v1' is view or temporary table +ERROR HY000: 'test.v1' is not BASE TABLE drop view v1; drop table t1; create temporary table t1 (i int); @@ -578,4 +578,5 @@ create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); drop function bug5893; update t1 set col2 = 4; ERROR 42000: FUNCTION test.bug5893 does not exist +drop trigger t1.t1_bu; drop table t1; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 39638cc437e..8a27636ed84 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -317,7 +317,7 @@ drop trigger t1.trg; drop trigger t1.trg; create view v1 as select * from t1; ---error 1361 +--error 1347 create trigger trg before insert on v1 for each row set @a:=1; drop view v1; @@ -576,6 +576,8 @@ drop table t1, t2; # Test for bug #5893 "Triggers with dropped functions cause crashes" # Appropriate error should be reported instead of crash. +# Also test for bug #11889 "Server crashes when dropping trigger +# using stored routine". --disable_warnings drop function if exists bug5893; --enable_warnings @@ -586,4 +588,6 @@ create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); drop function bug5893; --error 1305 update t1 set col2 = 4; +# This should not crash server too. +drop trigger t1.t1_bu; drop table t1; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index f058c306d42..fd79fc8b878 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -69,7 +69,10 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) But do we want this ? */ - if (open_and_lock_tables(thd, tables)) + /* We should have only one table in table list. */ + DBUG_ASSERT(tables->next_global == 0); + + if (!(table= open_ltable(thd, tables, tables->lock_type))) DBUG_RETURN(TRUE); /* @@ -80,8 +83,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) if (check_global_access(thd, SUPER_ACL)) DBUG_RETURN(TRUE); - table= tables->table; - /* We do not allow creation of triggers on views or temporary tables. We have to do this check here and not in From ef1e748ef1d8ac2735222dae9e89d2a7edb99fc6 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 00:15:23 +0400 Subject: [PATCH 10/39] A test case for Bug#9442 "Set parameter make query fail if column character set is UCS2". The bug is no longer repeatable. --- mysql-test/r/ps.result | 19 +++++++++++++++++++ mysql-test/t/ps.test | 13 +++++++++++++ 2 files changed, 32 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index cdba113ae40..ee558e0ea89 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -641,3 +641,22 @@ execute stmt using @a, @b; ?=? 1 deallocate prepare stmt; +create table t1 (utext varchar(20) character set ucs2); +insert into t1 values ("lily"); +insert into t1 values ("river"); +prepare stmt from 'select utext from t1 where utext like ?'; +set @param1='%%'; +execute stmt using @param1; +utext +lily +river +execute stmt using @param1; +utext +lily +river +select utext from t1 where utext like '%%'; +utext +lily +river +drop table t1; +deallocate prepare stmt; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 0fa14024d11..01d62a2e198 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -666,3 +666,16 @@ set @a='CHRISTINE '; set @b='CHRISTINE'; execute stmt using @a, @b; deallocate prepare stmt; +# +# Bug#9442 Set parameter make query fail if column character set is UCS2 +# +create table t1 (utext varchar(20) character set ucs2); +insert into t1 values ("lily"); +insert into t1 values ("river"); +prepare stmt from 'select utext from t1 where utext like ?'; +set @param1='%%'; +execute stmt using @param1; +execute stmt using @param1; +select utext from t1 where utext like '%%'; +drop table t1; +deallocate prepare stmt; From e0b9e35484ce917691a592cf0fa334326ce400c8 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 01:19:52 +0400 Subject: [PATCH 11/39] Post-merge fixes. --- tests/mysql_client_test.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ffb848a6ef2..bc30bf5f186 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13616,7 +13616,6 @@ static void test_bug11656() static void test_bug10214() { - MYSQL_RES* res ; int len; char out[8]; @@ -13639,18 +13638,21 @@ static void test_bug10214() static void test_client_character_set() { MY_CHARSET_INFO cs; - const char *csname; + char *csname; int rc; myheader("test_client_character_set"); - csname = "utf8"; - rc = mysql_set_character_set(mysql, csname); + csname= (char*) "utf8"; + rc= mysql_set_character_set(mysql, csname); DIE_UNLESS(rc == 0); mysql_get_character_set_info(mysql, &cs); DIE_UNLESS(!strcmp(cs.csname, "utf8")); DIE_UNLESS(!strcmp(cs.name, "utf8_general_ci")); + /* Restore the default character set */ + rc= mysql_query(mysql, "set names default"); + myquery(rc); } From 03a6d0c73176b8be8eab6c70f9821e77b4440241 Mon Sep 17 00:00:00 2001 From: "reggie@linux.site" <> Date: Thu, 14 Jul 2005 03:49:54 -0600 Subject: [PATCH 12/39] fixed function sig so it will compile with Visual C++ 8 --- regex/regerror.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/regex/regerror.c b/regex/regerror.c index 0a7b7c8da2c..9caa5b95a4c 100644 --- a/regex/regerror.c +++ b/regex/regerror.c @@ -56,11 +56,7 @@ static struct rerr { */ /* ARGSUSED */ size_t -regerror(errcode, preg, errbuf, errbuf_size) -int errcode; -const regex_t *preg; -char *errbuf; -size_t errbuf_size; +regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { register struct rerr *r; register size_t len; From f302759522a0238e25c32083f0ded42aee890371 Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Thu, 14 Jul 2005 15:42:36 +0500 Subject: [PATCH 13/39] valgrind error fix(uninitialiased variable) removed unnecessary operation --- sql/sql_lex.cc | 2 +- sql/sql_parse.cc | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2bf04273135..218410eed81 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -164,7 +164,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->current_select= &lex->select_lex; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); - lex->sql_command=SQLCOM_END; + lex->sql_command= lex->orig_sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; lex->ignore= 0; lex->sphead= NULL; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a2e5501ad7d..2e5cab4bb1c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5189,7 +5189,6 @@ mysql_init_select(LEX *lex) { SELECT_LEX *select_lex= lex->current_select; select_lex->init_select(); - lex->orig_sql_command= SQLCOM_END; lex->wild= 0; if (select_lex == &lex->select_lex) { From 62b8e6fdd153c62a1143a65be5b3c84d37bef890 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 15:13:23 +0400 Subject: [PATCH 14/39] A fix and a test case for Bug#9735. No separate typecode for MEDIUMTEXT/LONGTEXT is added, as we have no sound decision yet what typecodes and for what types are sent by the server (aka what constitutes a distinct type in MySQL). --- mysql-test/r/ps_2myisam.result | 20 ++++++++--------- mysql-test/r/ps_3innodb.result | 20 ++++++++--------- mysql-test/r/ps_4heap.result | 16 +++++++------- mysql-test/r/ps_5merge.result | 40 +++++++++++++++++----------------- mysql-test/r/ps_6bdb.result | 20 ++++++++--------- mysql-test/r/ps_7ndb.result | 20 ++++++++--------- sql/field.cc | 4 +++- tests/mysql_client_test.c | 31 +++++++++++++++++++++++++- 8 files changed, 101 insertions(+), 70 deletions(-) diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index c569c9842f7..4b655cfb854 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -77,8 +77,8 @@ def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c26 c26 252 65535 4 Y 16 0 8 def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63 def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8 -def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63 -def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8 +def test t9 t9 c29 c29 252 4294967295 8 Y 144 0 63 +def test t9 t9 c30 c30 252 4294967295 8 Y 16 0 8 def test t9 t9 c31 c31 254 5 3 Y 256 0 8 def test t9 t9 c32 c32 254 24 7 Y 2048 0 8 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 @@ -1812,17 +1812,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -1830,8 +1830,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 930aea2e381..4d2a62887d6 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -77,8 +77,8 @@ def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c26 c26 252 65535 4 Y 16 0 8 def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63 def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8 -def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63 -def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8 +def test t9 t9 c29 c29 252 4294967295 8 Y 144 0 63 +def test t9 t9 c30 c30 252 4294967295 8 Y 16 0 8 def test t9 t9 c31 c31 254 5 3 Y 256 0 8 def test t9 t9 c32 c32 254 24 7 Y 2048 0 8 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 @@ -1795,17 +1795,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -1813,8 +1813,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 083a4b221fe..a4919b664c4 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1796,17 +1796,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -1814,8 +1814,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 1edd617ffc6..f98cc1b3cdf 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -120,8 +120,8 @@ def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c26 c26 252 65535 4 Y 16 0 8 def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63 def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8 -def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63 -def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8 +def test t9 t9 c29 c29 252 4294967295 8 Y 144 0 63 +def test t9 t9 c30 c30 252 4294967295 8 Y 16 0 8 def test t9 t9 c31 c31 254 5 3 Y 256 0 8 def test t9 t9 c32 c32 254 24 7 Y 2048 0 8 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 @@ -1732,17 +1732,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -1750,8 +1750,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 @@ -3134,8 +3134,8 @@ def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c26 c26 252 65535 4 Y 16 0 8 def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63 def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8 -def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63 -def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8 +def test t9 t9 c29 c29 252 4294967295 8 Y 144 0 63 +def test t9 t9 c30 c30 252 4294967295 8 Y 16 0 8 def test t9 t9 c31 c31 254 5 3 Y 256 0 8 def test t9 t9 c32 c32 254 24 7 Y 2048 0 8 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 @@ -4746,17 +4746,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -4764,8 +4764,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 06be8750cc4..acd7f45de95 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -77,8 +77,8 @@ def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c26 c26 252 65535 4 Y 16 0 8 def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63 def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8 -def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63 -def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8 +def test t9 t9 c29 c29 252 4294967295 8 Y 144 0 63 +def test t9 t9 c30 c30 252 4294967295 8 Y 16 0 8 def test t9 t9 c31 c31 254 5 3 Y 256 0 8 def test t9 t9 c32 c32 254 24 7 Y 2048 0 8 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 @@ -1795,17 +1795,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -1813,8 +1813,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index f5750d947b5..27a1ea0925d 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -77,8 +77,8 @@ def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c26 c26 252 65535 4 Y 16 0 8 def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63 def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8 -def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63 -def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8 +def test t9 t9 c29 c29 252 4294967295 8 Y 144 0 63 +def test t9 t9 c30 c30 252 4294967295 8 Y 16 0 8 def test t9 t9 c31 c31 254 5 3 Y 256 0 8 def test t9 t9 c32 c32 254 24 7 Y 2048 0 8 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32 @@ -1795,17 +1795,17 @@ def test t5 t5 param02 param02 5 20 1 Y 32768 31 63 def test t5 t5 const03 const03 5 23 1 N 32769 31 63 def test t5 t5 param03 param03 5 20 1 Y 32768 31 63 def test t5 t5 const04 const04 254 3 3 N 1 0 8 -def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8 +def test t5 t5 param04 param04 252 4294967295 3 Y 16 0 8 def test t5 t5 const05 const05 254 3 3 N 129 0 63 -def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63 +def test t5 t5 param05 param05 252 4294967295 3 Y 144 0 63 def test t5 t5 const06 const06 253 10 10 N 1 0 8 -def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8 +def test t5 t5 param06 param06 252 4294967295 10 Y 16 0 8 def test t5 t5 const07 const07 10 10 10 Y 128 0 63 -def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63 +def test t5 t5 param07 param07 252 4294967295 10 Y 144 0 63 def test t5 t5 const08 const08 253 19 19 N 1 0 8 -def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8 +def test t5 t5 param08 param08 252 4294967295 19 Y 16 0 8 def test t5 t5 const09 const09 12 19 19 Y 128 0 63 -def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63 +def test t5 t5 param09 param09 252 4294967295 19 Y 144 0 63 def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 @@ -1813,8 +1813,8 @@ def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 -def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 -def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63 +def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8 +def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63 const01 8 param01 8 const02 8.0 diff --git a/sql/field.cc b/sql/field.cc index 64d5babd159..39a99830b14 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -47,6 +47,8 @@ uchar Field_null::null[1]={1}; const char field_separator=','; #define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320 +#define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \ +((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1))) /* Rules for merging different types of fields in UNION @@ -5445,7 +5447,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, CHARSET_INFO *cs) - :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L, + :Field_str(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length), null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, table_arg, cs), packlength(blob_pack_length) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index dbee6e77e4f..f874276a656 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -672,7 +672,7 @@ static void verify_prepare_field(MYSQL_RES *result, fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)", field->org_table, org_table); fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db); - fprintf(stdout, "\n length :`%ld`\t(expected: `%ld`)", + fprintf(stdout, "\n length :`%lu`\t(expected: `%lu`)", field->length, length * cs->mbmaxlen); fprintf(stdout, "\n maxlength:`%ld`", field->max_length); fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr); @@ -11670,6 +11670,34 @@ static void test_bug8378() #endif } + +/* Test correct max length for MEDIUMTEXT and LONGTEXT columns */ + +static void test_bug9735() +{ + MYSQL_RES *res; + int rc; + + myheader("test_bug9735"); + + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + rc= mysql_query(mysql, "create table t1 (a mediumtext, b longtext) " + "character set latin1"); + myquery(rc); + rc= mysql_query(mysql, "select * from t1"); + myquery(rc); + res= mysql_store_result(mysql); + verify_prepare_field(res, 0, "a", "a", MYSQL_TYPE_BLOB, + "t1", "t1", current_db, (1U << 24)-1, 0); + verify_prepare_field(res, 1, "b", "b", MYSQL_TYPE_BLOB, + "t1", "t1", current_db, ~0U, 0); + mysql_free_result(res); + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11884,6 +11912,7 @@ static struct my_tests_st my_tests[]= { { "test_bug8330", test_bug8330 }, { "test_bug7990", test_bug7990 }, { "test_bug8378", test_bug8378 }, + { "test_bug9735", test_bug9735 }, { 0, 0 } }; From 509531421c7aba1a4180652d1764c34b62cafd72 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 15:27:24 +0400 Subject: [PATCH 15/39] Implement MarkM optimization request to avoid redundnat packet exchange in cursors. --- libmysql/libmysql.c | 5 ++--- sql/sql_prepare.cc | 43 +++++++++++++++++++++++++++------------ sql/sql_select.cc | 6 ------ sql/sql_select.h | 2 +- tests/mysql_client_test.c | 23 +-------------------- 5 files changed, 34 insertions(+), 45 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 2074abd0f85..a896460beeb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -4907,13 +4907,12 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) { MYSQL *mysql= stmt->mysql; MYSQL_DATA *result= &stmt->result; - my_bool has_cursor= stmt->read_row_func == stmt_read_row_from_cursor; /* Reset stored result set if so was requested or it's a part of cursor fetch. */ - if (result->data && (has_cursor || (flags & RESET_STORE_RESULT))) + if (result->data && (flags & RESET_STORE_RESULT)) { /* Result buffered */ free_root(&result->alloc, MYF(MY_KEEP_PREALLOC)); @@ -4944,7 +4943,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) mysql->status= MYSQL_STATUS_READY; } } - if (has_cursor || (flags & RESET_SERVER_SIDE)) + if (flags & RESET_SERVER_SIDE) { /* Reset the server side statement and close the server side diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6d11518198c..e163e71e416 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -106,6 +106,7 @@ public: virtual ~Prepared_statement(); void setup_set_params(); virtual Query_arena::Type type() const; + virtual void close_cursor(); }; static void execute_stmt(THD *thd, Prepared_statement *stmt, @@ -1986,10 +1987,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) cursor= stmt->cursor; if (cursor && cursor->is_open()) - { - my_error(ER_EXEC_STMT_WITH_OPEN_CURSOR, MYF(0)); - DBUG_VOID_RETURN; - } + stmt->close_cursor(); DBUG_ASSERT(thd->free_list == NULL); mysql_reset_thd_for_next_command(thd); @@ -2284,6 +2282,7 @@ void mysql_stmt_reset(THD *thd, char *packet) if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) DBUG_VOID_RETURN; + stmt->close_cursor(); /* will reset statement params */ cursor= stmt->cursor; if (cursor && cursor->is_open()) { @@ -2295,12 +2294,6 @@ void mysql_stmt_reset(THD *thd, char *packet) stmt->state= Query_arena::PREPARED; - /* - Clear parameters from data which could be set by - mysql_stmt_send_long_data() call. - */ - reset_stmt_params(stmt); - mysql_reset_thd_for_next_command(thd); send_ok(thd); @@ -2448,10 +2441,17 @@ void Prepared_statement::setup_set_params() Prepared_statement::~Prepared_statement() { if (cursor) + { + if (cursor->is_open()) + { + cursor->close(FALSE); + free_items(); + free_root(cursor->mem_root, MYF(0)); + } cursor->Cursor::~Cursor(); - free_items(); - if (cursor) - free_root(cursor->mem_root, MYF(0)); + } + else + free_items(); delete lex->result; } @@ -2460,3 +2460,20 @@ Query_arena::Type Prepared_statement::type() const { return PREPARED_STATEMENT; } + + +void Prepared_statement::close_cursor() +{ + if (cursor && cursor->is_open()) + { + thd->change_list= cursor->change_list; + cursor->close(FALSE); + cleanup_stmt_and_thd_after_use(this, thd); + free_root(cursor->mem_root, MYF(0)); + } + /* + Clear parameters from data which could be set by + mysql_stmt_send_long_data() call. + */ + reset_stmt_params(this); +} diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 66e783a2103..524fc784422 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1915,12 +1915,6 @@ Cursor::close(bool is_active) } -Cursor::~Cursor() -{ - if (is_open()) - close(FALSE); -} - /*********************************************************************/ /* diff --git a/sql/sql_select.h b/sql/sql_select.h index ac3e8898cc6..9285e33be33 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -408,7 +408,7 @@ public: void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; } Cursor(THD *thd); - ~Cursor(); + ~Cursor() {} }; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index bc30bf5f186..0b88fa1b273 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13050,27 +13050,6 @@ static void test_bug9478() check_execute(stmt, rc); if (!opt_silent && i == 0) printf("Fetched row: %s\n", a); - /* - Although protocol-wise an attempt to execute a statement which - already has an open cursor associated with it will yield an error, - the client library behavior tested here is consistent with - the non-cursor execution scenario: mysql_stmt_execute will - silently close the cursor if necessary. - */ - { - char buff[9]; - /* Fill in the execute packet */ - int4store(buff, stmt->stmt_id); - buff[4]= 0; /* Flag */ - int4store(buff+5, 1); /* Reserved for array bind */ - rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_EXECUTE, buff, - sizeof(buff), 0,0,1) || - (*mysql->methods->read_query_result)(mysql)); - DIE_UNLESS(rc); - if (!opt_silent && i == 0) - printf("Got error (as expected): %s\n", mysql_error(mysql)); - } - rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); @@ -13429,7 +13408,7 @@ static void test_bug10794() bind[1].length= &a_len; rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); - for (i= 0; i < 34; i++) + for (i= 0; i < 42; i++) { id_val= (i+1)*10; sprintf(a, "a%d", i); From c64128cc580ed7c27c5a7668c96ae8eac559a2bb Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Thu, 14 Jul 2005 17:48:17 +0500 Subject: [PATCH 16/39] item.cc: After merge fix. --- sql/item.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index df4583fea3c..0a6c87e598c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3783,7 +3783,7 @@ bool Item_hex_string::eq(const Item *arg, bool binary_cmp) const } -Item *Item_varbinary::safe_charset_converter(CHARSET_INFO *tocs) +Item *Item_hex_string::safe_charset_converter(CHARSET_INFO *tocs) { Item_string *conv; String tmp, *str= val_str(&tmp); From 1969a1622ee1f2a16063d2b10121e89cb087db56 Mon Sep 17 00:00:00 2001 From: "hf@deer.(none)" <> Date: Thu, 14 Jul 2005 18:51:05 +0500 Subject: [PATCH 17/39] Fix for bug #10929 (type_newdecimal.test requires InnoDB) --- mysql-test/r/innodb.result | 9 +++++++++ mysql-test/r/type_newdecimal.result | 9 --------- mysql-test/t/innodb.test | 12 ++++++++++++ mysql-test/t/type_newdecimal.test | 12 ------------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index aab4eb696d2..2c73cbeeea4 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2466,3 +2466,12 @@ select * from t1; a val 2 1 drop table t1; +CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; +INSERT INTO t1 (GRADE) VALUES (151),(252),(343); +SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; +GRADE +252 +SELECT GRADE FROM t1 WHERE GRADE= 151; +GRADE +151 +DROP TABLE t1; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index aed2a478c0e..c1039189a43 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -876,15 +876,6 @@ SELECT * FROM t1; f1 f2 9999999999999999999999999999999999.00000000000000000000 0.00 DROP TABLE t1; -CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; -INSERT INTO t1 (GRADE) VALUES (151),(252),(343); -SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; -GRADE -252 -SELECT GRADE FROM t1 WHERE GRADE= 151; -GRADE -151 -DROP TABLE t1; select abs(10/0); abs(10/0) NULL diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 485eeec05d9..2d0e2a4dd65 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1381,3 +1381,15 @@ update t1 set a=2 where a=1; insert into t1 (val) values (1); select * from t1; drop table t1; +# +# Bug #10465 +# + +--disable_warnings +CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; +--enable_warnings +INSERT INTO t1 (GRADE) VALUES (151),(252),(343); +SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; +SELECT GRADE FROM t1 WHERE GRADE= 151; +DROP TABLE t1; + diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index f54c8d80f09..f295311fe4e 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -907,18 +907,6 @@ INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0); SELECT * FROM t1; DROP TABLE t1; -# -# Bug #10465 -# - ---disable_warnings -CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; ---enable_warnings -INSERT INTO t1 (GRADE) VALUES (151),(252),(343); -SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; -SELECT GRADE FROM t1 WHERE GRADE= 151; -DROP TABLE t1; - # # Bug #10599: problem with NULL # From e1273aec6dfcb163542e449a31bf2f8aa3e0fa63 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 14 Jul 2005 15:13:36 +0000 Subject: [PATCH 18/39] Fix for BUG#11700: in add_not_null_conds(), call full fix_fields() for the created NOT NULL. This is needed because in some cases range optimization is performed twice and added NOT NULL item must have correct const_table_map() value. --- mysql-test/r/select.result | 35 ++++++++++++++++++++++++++++++++ mysql-test/t/select.test | 41 ++++++++++++++++++++++++++++++++++++++ sql/sql_select.cc | 12 ++++++++--- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index abf5c8c87ad..8160c5a2f3d 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2524,3 +2524,38 @@ select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid id name gid uid ident level 1 fs NULL NULL 0 READ drop table t1,t2,t3; +CREATE TABLE t1 ( +acct_id int(11) NOT NULL default '0', +profile_id smallint(6) default NULL, +UNIQUE KEY t1$acct_id (acct_id), +KEY t1$profile_id (profile_id) +); +INSERT INTO t1 VALUES (132,17),(133,18); +CREATE TABLE t2 ( +profile_id smallint(6) default NULL, +queue_id int(11) default NULL, +seq int(11) default NULL, +KEY t2$queue_id (queue_id) +); +INSERT INTO t2 VALUES (17,31,4),(17,30,3),(17,36,2),(17,37,1); +CREATE TABLE t3 ( +id int(11) NOT NULL default '0', +qtype int(11) default NULL, +seq int(11) default NULL, +warn_lvl int(11) default NULL, +crit_lvl int(11) default NULL, +rr1 tinyint(4) NOT NULL default '0', +rr2 int(11) default NULL, +default_queue tinyint(4) NOT NULL default '0', +KEY t3$qtype (qtype), +KEY t3$id (id) +); +INSERT INTO t3 VALUES (30,1,29,NULL,NULL,0,NULL,0),(31,1,28,NULL,NULL,0,NULL,0), +(36,1,34,NULL,NULL,0,NULL,0),(37,1,35,NULL,NULL,0,121,0); +SELECT COUNT(*) FROM t1 a STRAIGHT_JOIN t2 pq STRAIGHT_JOIN t3 q +WHERE +(pq.profile_id = a.profile_id) AND (a.acct_id = 132) AND +(pq.queue_id = q.id) AND (q.rr1 <> 1); +COUNT(*) +4 +drop table t1,t2,t3; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index baaab6e4189..37e4324152b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2075,3 +2075,44 @@ INSERT INTO `t3` VALUES (1,'fs'); select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); drop table t1,t2,t3; + +# Test for BUG#11700 +CREATE TABLE t1 ( + acct_id int(11) NOT NULL default '0', + profile_id smallint(6) default NULL, + UNIQUE KEY t1$acct_id (acct_id), + KEY t1$profile_id (profile_id) +); +INSERT INTO t1 VALUES (132,17),(133,18); + +CREATE TABLE t2 ( + profile_id smallint(6) default NULL, + queue_id int(11) default NULL, + seq int(11) default NULL, + KEY t2$queue_id (queue_id) +); +INSERT INTO t2 VALUES (17,31,4),(17,30,3),(17,36,2),(17,37,1); + +CREATE TABLE t3 ( + id int(11) NOT NULL default '0', + qtype int(11) default NULL, + seq int(11) default NULL, + warn_lvl int(11) default NULL, + crit_lvl int(11) default NULL, + rr1 tinyint(4) NOT NULL default '0', + rr2 int(11) default NULL, + default_queue tinyint(4) NOT NULL default '0', + KEY t3$qtype (qtype), + KEY t3$id (id) +); + +INSERT INTO t3 VALUES (30,1,29,NULL,NULL,0,NULL,0),(31,1,28,NULL,NULL,0,NULL,0), + (36,1,34,NULL,NULL,0,NULL,0),(37,1,35,NULL,NULL,0,121,0); + +SELECT COUNT(*) FROM t1 a STRAIGHT_JOIN t2 pq STRAIGHT_JOIN t3 q +WHERE + (pq.profile_id = a.profile_id) AND (a.acct_id = 132) AND + (pq.queue_id = q.id) AND (q.rr1 <> 1); + +drop table t1,t2,t3; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 972fb4e0368..75fc189b21f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3539,11 +3539,17 @@ static void add_not_null_conds(JOIN *join) DBUG_ASSERT(item->type() == Item::FIELD_ITEM); Item_field *not_null_item= (Item_field*)item; JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab; - Item_func_isnotnull *notnull; + Item *notnull; if (!(notnull= new Item_func_isnotnull(not_null_item))) DBUG_VOID_RETURN; - - notnull->quick_fix_field(); + /* + We need to do full fix_fields() call here in order to have correct + notnull->const_item(). This is needed e.g. by test_quick_select + when it is called from make_join_select after this function is + called. + */ + if (notnull->fix_fields(join->thd, join->tables_list, ¬null)) + DBUG_VOID_RETURN; DBUG_EXECUTE("where",print_where(notnull, referred_tab->table->table_name);); add_cond_and_fix(&referred_tab->select_cond, notnull); From 0b3db181bf58e7d7b083eb6c790859d1975aece2 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Thu, 14 Jul 2005 15:19:26 +0000 Subject: [PATCH 19/39] Fix for BUG#11869: In Item_func_match::fix_index() handle the case when there is no source table present (this happens for ORDER BY after UNION) --- mysql-test/r/fulltext_order_by.result | 74 ++++++++++++++++++++++++ mysql-test/t/fulltext_order_by.test | 81 +++++++++++++++++++++++++++ sql/item_func.cc | 3 + 3 files changed, 158 insertions(+) diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result index dc51454f1d5..130d096e00f 100644 --- a/mysql-test/r/fulltext_order_by.result +++ b/mysql-test/r/fulltext_order_by.result @@ -86,3 +86,77 @@ a rel 1 1 2 2 drop table t1; +CREATE TABLE t1 ( +id int(11) NOT NULL auto_increment, +thread int(11) NOT NULL default '0', +beitrag longtext NOT NULL, +PRIMARY KEY (id), +KEY thread (thread), +FULLTEXT KEY beitrag (beitrag) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7923 ; +CREATE TABLE t2 ( +id int(11) NOT NULL auto_increment, +text varchar(100) NOT NULL default '', +PRIMARY KEY (id), +KEY text (text) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=63 ; +CREATE TABLE t3 ( +id int(11) NOT NULL auto_increment, +forum int(11) NOT NULL default '0', +betreff varchar(70) NOT NULL default '', +PRIMARY KEY (id), +KEY forum (forum), +FULLTEXT KEY betreff (betreff) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ; +select a.text, b.id, b.betreff +from +t2 a inner join t3 b on a.id = b.forum inner join +t1 c on b.id = c.thread +where +match(b.betreff) against ('+abc' in boolean mode) +group by a.text, b.id, b.betreff +union +select a.text, b.id, b.betreff +from +t2 a inner join t3 b on a.id = b.forum inner join +t1 c on b.id = c.thread +where +match(c.beitrag) against ('+abc' in boolean mode) +group by +a.text, b.id, b.betreff +order by +match(b.betreff) against ('+abc' in boolean mode) desc; +ERROR 42S02: Unknown table 'b' in order clause +select a.text, b.id, b.betreff +from +t2 a inner join t3 b on a.id = b.forum inner join +t1 c on b.id = c.thread +where +match(b.betreff) against ('+abc' in boolean mode) +union +select a.text, b.id, b.betreff +from +t2 a inner join t3 b on a.id = b.forum inner join +t1 c on b.id = c.thread +where +match(c.beitrag) against ('+abc' in boolean mode) +order by +match(b.betreff) against ('+abc' in boolean mode) desc; +ERROR 42S02: Unknown table 'b' in order clause +select a.text, b.id, b.betreff +from +t2 a inner join t3 b on a.id = b.forum inner join +t1 c on b.id = c.thread +where +match(b.betreff) against ('+abc' in boolean mode) +union +select a.text, b.id, b.betreff +from +t2 a inner join t3 b on a.id = b.forum inner join +t1 c on b.id = c.thread +where +match(c.beitrag) against ('+abc' in boolean mode) +order by +match(betreff) against ('+abc' in boolean mode) desc; +text id betreff +drop table t1,t2,t3; diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test index 5c1b4127d8c..6894f63fa77 100644 --- a/mysql-test/t/fulltext_order_by.test +++ b/mysql-test/t/fulltext_order_by.test @@ -54,3 +54,84 @@ SELECT a, MATCH (message) AGAINST ('t* f*' IN BOOLEAN MODE) as rel FROM t1; SELECT a, MATCH (message) AGAINST ('t* f*' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel,a; drop table t1; +# BUG#11869 +CREATE TABLE t1 ( + id int(11) NOT NULL auto_increment, + thread int(11) NOT NULL default '0', + beitrag longtext NOT NULL, + PRIMARY KEY (id), + KEY thread (thread), + FULLTEXT KEY beitrag (beitrag) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7923 ; + +CREATE TABLE t2 ( + id int(11) NOT NULL auto_increment, + text varchar(100) NOT NULL default '', + PRIMARY KEY (id), + KEY text (text) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=63 ; + +CREATE TABLE t3 ( + id int(11) NOT NULL auto_increment, + forum int(11) NOT NULL default '0', + betreff varchar(70) NOT NULL default '', + PRIMARY KEY (id), + KEY forum (forum), + FULLTEXT KEY betreff (betreff) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=996 ; + +--error 1109 +select a.text, b.id, b.betreff +from + t2 a inner join t3 b on a.id = b.forum inner join + t1 c on b.id = c.thread +where + match(b.betreff) against ('+abc' in boolean mode) +group by a.text, b.id, b.betreff +union +select a.text, b.id, b.betreff +from + t2 a inner join t3 b on a.id = b.forum inner join + t1 c on b.id = c.thread +where + match(c.beitrag) against ('+abc' in boolean mode) +group by + a.text, b.id, b.betreff +order by + match(b.betreff) against ('+abc' in boolean mode) desc; + +--error 1109 +select a.text, b.id, b.betreff +from + t2 a inner join t3 b on a.id = b.forum inner join + t1 c on b.id = c.thread +where + match(b.betreff) against ('+abc' in boolean mode) +union +select a.text, b.id, b.betreff +from + t2 a inner join t3 b on a.id = b.forum inner join + t1 c on b.id = c.thread +where + match(c.beitrag) against ('+abc' in boolean mode) +order by + match(b.betreff) against ('+abc' in boolean mode) desc; + +select a.text, b.id, b.betreff +from + t2 a inner join t3 b on a.id = b.forum inner join + t1 c on b.id = c.thread +where + match(b.betreff) against ('+abc' in boolean mode) +union +select a.text, b.id, b.betreff +from + t2 a inner join t3 b on a.id = b.forum inner join + t1 c on b.id = c.thread +where + match(c.beitrag) against ('+abc' in boolean mode) +order by + match(betreff) against ('+abc' in boolean mode) desc; + +drop table t1,t2,t3; + diff --git a/sql/item_func.cc b/sql/item_func.cc index 442ef15bba8..fd45323aae2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3196,6 +3196,9 @@ bool Item_func_match::fix_index() if (key == NO_SUCH_KEY) return 0; + + if (!table) + goto err; for (keynr=0 ; keynr < table->keys ; keynr++) { From be233935cc16ebc22b317e6da41f3f609c1d3874 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Thu, 14 Jul 2005 20:19:27 +0500 Subject: [PATCH 20/39] fix for #11808 backported. --- tests/mysql_client_test.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index dbee6e77e4f..94295eeb38a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -166,6 +166,14 @@ DIE_UNLESS(stmt == 0);\ #define mytest_r(x) if (x) {myerror(NULL);DIE_UNLESS(FALSE);} +/* A workaround for Sun Forte 5.6 on Solaris x86 */ + +static int cmp_double(double *a, double *b) +{ + return *a == *b; +} + + /* Print the error message */ static void print_error(const char *msg) @@ -1396,7 +1404,7 @@ static void test_prepare() DIE_UNLESS(real_data == o_real_data); DIE_UNLESS(length[5] == 4); - DIE_UNLESS(double_data == o_double_data); + DIE_UNLESS(cmp_double(&double_data, &o_double_data)); DIE_UNLESS(length[6] == 8); DIE_UNLESS(strcmp(data, str_data) == 0); @@ -9583,7 +9591,7 @@ static void test_bug3035() uint32 uint32_val; longlong int64_val; ulonglong uint64_val; - double double_val, udouble_val; + double double_val, udouble_val, double_tmp; char longlong_as_string[22], ulonglong_as_string[22]; /* mins and maxes */ @@ -9727,7 +9735,8 @@ static void test_bug3035() DIE_UNLESS(int64_val == int64_min); DIE_UNLESS(uint64_val == uint64_min); DIE_UNLESS(double_val == (longlong) uint64_min); - DIE_UNLESS(udouble_val == ulonglong2double(uint64_val)); + double_tmp= ulonglong2double(uint64_val); + DIE_UNLESS(cmp_double(&udouble_val, &double_tmp)); DIE_UNLESS(!strcmp(longlong_as_string, "0")); DIE_UNLESS(!strcmp(ulonglong_as_string, "0")); @@ -9743,7 +9752,8 @@ static void test_bug3035() DIE_UNLESS(int64_val == int64_max); DIE_UNLESS(uint64_val == uint64_max); DIE_UNLESS(double_val == (longlong) uint64_val); - DIE_UNLESS(udouble_val == ulonglong2double(uint64_val)); + double_tmp= ulonglong2double(uint64_val); + DIE_UNLESS(cmp_double(&udouble_val, &double_tmp)); DIE_UNLESS(!strcmp(longlong_as_string, "-1")); DIE_UNLESS(!strcmp(ulonglong_as_string, "18446744073709551615")); From 9c6f14aa3de16e34658f47cc78793547c27fe93b Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 19:42:56 +0400 Subject: [PATCH 21/39] Get rid of checking for ETIME return value of pthread_cond_timedwait. ETIME was returned by cond_timedwait (sic, the pre-POSIX1001b function) on Solaris 2.6 and 2.7. pthread_cond_timedwait on Solaris returns ETIMEDOUT. The standard requirement is that the only additional return value of pthred_cond_timedwait compared to pthread_cond_wait is ETIMEDOUT. Let us not bloat the application code with redundant checks, and if we're ever to work on a platform that returns a non-standard value, we should write a wrapper for that platform (like we do, e.g., for Windows). --- mysys/my_os2cond.c | 2 +- sql/item_func.cc | 10 +++++----- sql/slave.cc | 2 +- sql/sql_insert.cc | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysys/my_os2cond.c b/mysys/my_os2cond.c index e23afb89e66..83a03d62046 100644 --- a/mysys/my_os2cond.c +++ b/mysys/my_os2cond.c @@ -100,7 +100,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, rc = DosWaitEventSem(cond->semaphore, timeout); if (rc != 0) - rval = ETIME; + rval= ETIMEDOUT; if (mutex) pthread_mutex_lock(mutex); diff --git a/sql/item_func.cc b/sql/item_func.cc index 296083b256e..9e46aac0e25 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3157,7 +3157,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) THD* thd=current_thd; User_level_lock* ull; struct timespec abstime; - int lock_name_len,error=0; + int lock_name_len; lock_name_len=strlen(lock_name); pthread_mutex_lock(&LOCK_user_locks); @@ -3191,8 +3191,8 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) set_timespec(abstime,lock_timeout); while (!thd->killed && - (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime)) - != ETIME && error != ETIMEDOUT && ull->locked) ; + pthread_cond_timedwait(&ull->cond, &LOCK_user_locks, + &abstime) != ETIMEDOUT && ull->locked) ; if (ull->locked) { if (!--ull->count) @@ -3294,14 +3294,14 @@ longlong Item_func_get_lock::val_int() set_timespec(abstime,timeout); while (!thd->killed && (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime)) - != ETIME && error != ETIMEDOUT && error != EINVAL && ull->locked) ; + != ETIMEDOUT && error != EINVAL && ull->locked) ; if (thd->killed) error=EINTR; // Return NULL if (ull->locked) { if (!--ull->count) delete ull; // Should never happen - if (error != ETIME && error != ETIMEDOUT) + if (error != ETIMEDOUT) { error=1; null_value=1; // Return NULL diff --git a/sql/slave.cc b/sql/slave.cc index c6c0de7160b..a587ac5a118 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2753,7 +2753,7 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, else pthread_cond_wait(&data_cond, &data_lock); DBUG_PRINT("info",("Got signal of master update or timed out")); - if (error == ETIMEDOUT || error == ETIME) + if (error == ETIMEDOUT) { error= -1; break; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5d30cad2926..125390e4411 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1730,7 +1730,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) #endif if (thd->killed || di->status) break; - if (error == ETIME || error == ETIMEDOUT) + if (error == ETIMEDOUT) { thd->killed= THD::KILL_CONNECTION; break; From 63ffc745326b0205b6b994098f6db230671576f1 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Thu, 14 Jul 2005 17:50:33 +0200 Subject: [PATCH 22/39] - suppress warning when running this test with a "classic" build (which does not include InnoDB) --- mysql-test/t/ctype_utf8.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 737dcbcf1ed..dee41d0aa6e 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -776,12 +776,14 @@ INSERT INTO t1 VALUES (1,'blah','464','aaa','fkc1c9ilc20x0hgae7lx6j09','ERR','ERR Имри.Ðфимим.Ðеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ðд.Д имдимримрад.Ðдимримримрмдиримримримр м.Дадимфшьмримд им.Ðдимимрн имадми','ИМРИ.ÐФИМИМ.ÐЕИМИМРИМДМРИМРМРИРОР',3,'2005-06-01 17:30:43','1234567890'), (2,'blah','464','aaa','haxpl2ilc20x00bj4tt2m5ti','11','11 g','G',3,'2005-06-02 22:43:10','1234567890'); +--disable_warnings CREATE TABLE t2 ( `msisdn` varchar(15) NOT NULL default '', `operator_id` int(11) NOT NULL default '0', `created` datetime NOT NULL default '0000-00-00 00:00:00', UNIQUE KEY `PK_user` (`msisdn`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +--enable_warnings INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25'); From 96a80fd2206df3df0df4a713e0a0c6cbf55fc61d Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 14 Jul 2005 18:02:32 +0200 Subject: [PATCH 23/39] added debug prints --- ndb/include/portlib/NdbTCP.h | 12 ++++++++--- ndb/include/util/SocketServer.hpp | 8 ++++++- ndb/src/common/mgmcommon/ConfigRetriever.cpp | 9 ++++++-- ndb/src/common/mgmcommon/IPCConfig.cpp | 7 +++++-- ndb/src/common/portlib/NdbMutex.c | 16 ++++++++------ ndb/src/common/portlib/NdbTCP.cpp | 9 ++++++++ ndb/src/common/portlib/NdbThread.c | 16 ++++++++++---- .../transporter/TransporterRegistry.cpp | 12 +++++++++-- ndb/src/common/util/Parser.cpp | 21 +++++++++++-------- ndb/src/common/util/SocketClient.cpp | 2 ++ ndb/src/common/util/SocketServer.cpp | 4 ++++ 11 files changed, 87 insertions(+), 29 deletions(-) diff --git a/ndb/include/portlib/NdbTCP.h b/ndb/include/portlib/NdbTCP.h index 8138a2ef354..308a3833ffd 100644 --- a/ndb/include/portlib/NdbTCP.h +++ b/ndb/include/portlib/NdbTCP.h @@ -31,7 +31,7 @@ #define NDB_NONBLOCK FNDELAY #define NDB_SOCKET_TYPE int #define NDB_INVALID_SOCKET -1 -#define NDB_CLOSE_SOCKET(x) close(x) +#define _NDB_CLOSE_SOCKET(x) close(x) /** * socklen_t not defined in the header files of OSE @@ -52,7 +52,7 @@ typedef int socklen_t; #define EWOULDBLOCK WSAEWOULDBLOCK #define NDB_SOCKET_TYPE SOCKET #define NDB_INVALID_SOCKET INVALID_SOCKET -#define NDB_CLOSE_SOCKET(x) closesocket(x) +#define _NDB_CLOSE_SOCKET(x) closesocket(x) #else @@ -64,7 +64,7 @@ typedef int socklen_t; #define NDB_NONBLOCK O_NONBLOCK #define NDB_SOCKET_TYPE int #define NDB_INVALID_SOCKET -1 -#define NDB_CLOSE_SOCKET(x) ::close(x) +#define _NDB_CLOSE_SOCKET(x) ::close(x) #define InetErrno errno @@ -89,6 +89,12 @@ extern "C" { */ int Ndb_getInAddr(struct in_addr * dst, const char *address); +#ifdef DBUG_OFF +#define NDB_CLOSE_SOCKET(fd) _NDB_CLOSE_SOCKET(fd) +#else +int NDB_CLOSE_SOCKET(int fd); +#endif + #ifdef __cplusplus } #endif diff --git a/ndb/include/util/SocketServer.hpp b/ndb/include/util/SocketServer.hpp index 9d8af204391..ee2dd31c41f 100644 --- a/ndb/include/util/SocketServer.hpp +++ b/ndb/include/util/SocketServer.hpp @@ -41,7 +41,13 @@ public: protected: friend class SocketServer; friend void* sessionThread_C(void*); - Session(NDB_SOCKET_TYPE sock): m_socket(sock){ m_stop = m_stopped = false;} + Session(NDB_SOCKET_TYPE sock): m_socket(sock) + { + DBUG_ENTER("SocketServer::Session"); + DBUG_PRINT("enter",("NDB_SOCKET: %d", m_socket)); + m_stop = m_stopped = false; + DBUG_VOID_RETURN; + } bool m_stop; // Has the session been ordered to stop? bool m_stopped; // Has the session stopped? diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index 648f3b4a52c..f77f823f2a4 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -47,6 +47,8 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string, Uint32 version, Uint32 node_type) { + DBUG_ENTER("ConfigRetriever::ConfigRetriever"); + m_version = version; m_node_type = node_type; _ownNodeId= 0; @@ -55,23 +57,26 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string, if (m_handle == 0) { setError(CR_ERROR, "Unable to allocate mgm handle"); - return; + DBUG_VOID_RETURN; } if (ndb_mgm_set_connectstring(m_handle, _connect_string)) { setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); - return; + DBUG_VOID_RETURN; } resetError(); + DBUG_VOID_RETURN; } ConfigRetriever::~ConfigRetriever() { + DBUG_ENTER("ConfigRetriever::~ConfigRetriever"); if (m_handle) { ndb_mgm_disconnect(m_handle); ndb_mgm_destroy_handle(&m_handle); } + DBUG_VOID_RETURN; } Uint32 diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp index 86791490863..8cf5e6e8d45 100644 --- a/ndb/src/common/mgmcommon/IPCConfig.cpp +++ b/ndb/src/common/mgmcommon/IPCConfig.cpp @@ -114,7 +114,10 @@ IPCConfig::addRemoteNodeId(NodeId nodeId){ * Returns no of transporters configured */ int -IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry){ +IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry) +{ + DBUG_ENTER("IPCConfig::configureTransporters"); + int noOfTransportersCreated = 0; Uint32 noOfConnections; @@ -276,7 +279,7 @@ IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry){ continue; } } - return noOfTransportersCreated; + DBUG_RETURN(noOfTransportersCreated); } /** diff --git a/ndb/src/common/portlib/NdbMutex.c b/ndb/src/common/portlib/NdbMutex.c index d3d39ea8cf7..18f8548e4e6 100644 --- a/ndb/src/common/portlib/NdbMutex.c +++ b/ndb/src/common/portlib/NdbMutex.c @@ -23,33 +23,37 @@ NdbMutex* NdbMutex_Create(void) { + DBUG_ENTER("NdbMutex_Create"); NdbMutex* pNdbMutex; int result; pNdbMutex = (NdbMutex*)NdbMem_Allocate(sizeof(NdbMutex)); + DBUG_PRINT("info",("NdbMem_Allocate 0x%lx",pNdbMutex)); if (pNdbMutex == NULL) - return NULL; + DBUG_RETURN(NULL); result = pthread_mutex_init(pNdbMutex, NULL); assert(result == 0); - return pNdbMutex; - + DBUG_RETURN(pNdbMutex); } int NdbMutex_Destroy(NdbMutex* p_mutex) { + DBUG_ENTER("NdbMutex_Destroy"); int result; if (p_mutex == NULL) - return -1; + DBUG_RETURN(-1); result = pthread_mutex_destroy(p_mutex); - free(p_mutex); + + DBUG_PRINT("info",("NdbMem_Free 0x%lx",p_mutex)); + NdbMem_Free(p_mutex); - return result; + DBUG_RETURN(result); } diff --git a/ndb/src/common/portlib/NdbTCP.cpp b/ndb/src/common/portlib/NdbTCP.cpp index a63f5a7ba27..c7b9d33c5f6 100644 --- a/ndb/src/common/portlib/NdbTCP.cpp +++ b/ndb/src/common/portlib/NdbTCP.cpp @@ -54,6 +54,15 @@ Ndb_getInAddr(struct in_addr * dst, const char *address) { return -1; //DBUG_RETURN(-1); } +#ifndef DBUG_OFF +extern "C" +int NDB_CLOSE_SOCKET(int fd) +{ + DBUG_PRINT("info", ("NDB_CLOSE_SOCKET(%d)", fd)); + return _NDB_CLOSE_SOCKET(fd); +} +#endif + #if 0 int Ndb_getInAddr(struct in_addr * dst, const char *address) { diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c index aaee9b45069..cee4ec018a0 100644 --- a/ndb/src/common/portlib/NdbThread.c +++ b/ndb/src/common/portlib/NdbThread.c @@ -56,6 +56,7 @@ ndb_thread_wrapper(void* _ss){ void *ret; struct NdbThread * ss = (struct NdbThread *)_ss; ret= (* ss->func)(ss->object); + DBUG_POP(); NdbThread_Exit(ret); } /* will never be reached */ @@ -70,6 +71,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, const char* p_thread_name, NDB_THREAD_PRIO thread_prio) { + DBUG_ENTER("NdbThread_Create"); struct NdbThread* tmpThread; int result; pthread_attr_t thread_attr; @@ -77,11 +79,13 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, (void)thread_prio; /* remove warning for unused parameter */ if (p_thread_func == NULL) - return 0; + DBUG_RETURN(NULL); tmpThread = (struct NdbThread*)NdbMem_Allocate(sizeof(struct NdbThread)); if (tmpThread == NULL) - return NULL; + DBUG_RETURN(NULL); + + DBUG_PRINT("info",("thread_name: %s", p_thread_name)); strnmov(tmpThread->thread_name,p_thread_name,sizeof(tmpThread->thread_name)); @@ -108,16 +112,20 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, assert(result==0); pthread_attr_destroy(&thread_attr); - return tmpThread; + DBUG_PRINT("exit",("ret: %lx", tmpThread)); + DBUG_RETURN(tmpThread); } void NdbThread_Destroy(struct NdbThread** p_thread) { - if (*p_thread != NULL){ + DBUG_ENTER("NdbThread_Destroy"); + if (*p_thread != NULL){ + DBUG_PRINT("enter",("*p_thread: %lx", * p_thread)); free(* p_thread); * p_thread = 0; } + DBUG_VOID_RETURN; } diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp index ac6161b314e..3e2c105fa2e 100644 --- a/ndb/src/common/transporter/TransporterRegistry.cpp +++ b/ndb/src/common/transporter/TransporterRegistry.cpp @@ -70,7 +70,9 @@ SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd) TransporterRegistry::TransporterRegistry(void * callback, unsigned _maxTransporters, - unsigned sizeOfLongSignalMemory) { + unsigned sizeOfLongSignalMemory) +{ + DBUG_ENTER("TransporterRegistry::TransporterRegistry"); nodeIdSpecified = false; maxTransporters = _maxTransporters; @@ -107,9 +109,13 @@ TransporterRegistry::TransporterRegistry(void * callback, theOSEReceiver = 0; theOSEJunkSocketSend = 0; theOSEJunkSocketRecv = 0; + + DBUG_VOID_RETURN; } -TransporterRegistry::~TransporterRegistry() { +TransporterRegistry::~TransporterRegistry() +{ + DBUG_ENTER("TransporterRegistry::~TransporterRegistry"); removeAll(); @@ -129,6 +135,8 @@ TransporterRegistry::~TransporterRegistry() { theOSEReceiver = 0; } #endif + + DBUG_VOID_RETURN; } void diff --git a/ndb/src/common/util/Parser.cpp b/ndb/src/common/util/Parser.cpp index dea128ccf66..d692aa18392 100644 --- a/ndb/src/common/util/Parser.cpp +++ b/ndb/src/common/util/Parser.cpp @@ -141,7 +141,10 @@ split(char * buf, char ** name, char ** value){ bool ParserImpl::run(Context * ctx, const class Properties ** pDst, - volatile bool * stop) const { + volatile bool * stop) const +{ + DBUG_ENTER("ParserImpl::run"); + * pDst = 0; bool ownStop = false; if(stop == 0) @@ -153,24 +156,24 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst, ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz); if(Eof(ctx->m_currentToken)){ ctx->m_status = Parser::Eof; - return false; + DBUG_RETURN(false); } if(ctx->m_currentToken[0] == 0){ ctx->m_status = Parser::NoLine; - return false; + DBUG_RETURN(false); } if(Empty(ctx->m_currentToken)){ ctx->m_status = Parser::EmptyLine; - return false; + DBUG_RETURN(false); } trim(ctx->m_currentToken); ctx->m_currentCmd = matchCommand(ctx, ctx->m_currentToken, m_rows); if(ctx->m_currentCmd == 0){ ctx->m_status = Parser::UnknownCommand; - return false; + DBUG_RETURN(false); } Properties * p = new Properties(); @@ -200,19 +203,19 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst, tmp = input.gets(buf, sz); } while((! * stop) && !Eof(tmp) && !Empty(tmp)); } - return false; + DBUG_RETURN(false); } if(* stop){ delete p; ctx->m_status = Parser::ExternalStop; - return false; + DBUG_RETURN(false); } if(!checkMandatory(ctx, p)){ ctx->m_status = Parser::MissingMandatoryArgument; delete p; - return false; + DBUG_RETURN(false); } /** @@ -229,7 +232,7 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst, ctx->m_status = Parser::Ok; * pDst = p; - return true; + DBUG_RETURN(true); } const ParserImpl::DummyRow* diff --git a/ndb/src/common/util/SocketClient.cpp b/ndb/src/common/util/SocketClient.cpp index 38df1417eb8..821624eb5c4 100644 --- a/ndb/src/common/util/SocketClient.cpp +++ b/ndb/src/common/util/SocketClient.cpp @@ -57,6 +57,8 @@ SocketClient::init() return false; } + DBUG_PRINT("info",("NDB_SOCKET: %d", m_sockfd)); + return true; } diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp index da06389b5df..db5c03f925a 100644 --- a/ndb/src/common/util/SocketServer.cpp +++ b/ndb/src/common/util/SocketServer.cpp @@ -64,6 +64,8 @@ SocketServer::tryBind(unsigned short port, const char * intface) { return false; } + DBUG_PRINT("info",("NDB_SOCKET: %d", sock)); + const int on = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) { @@ -104,6 +106,8 @@ SocketServer::setup(SocketServer::Service * service, DBUG_RETURN(false); } + DBUG_PRINT("info",("NDB_SOCKET: %d", sock)); + const int on = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) { From 9be420ee105609aade80f1c84767605ba4306e0f Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 14 Jul 2005 18:02:33 +0200 Subject: [PATCH 24/39] stilled mem leak in usage on getVersionString added __LINE__ so systemErrorLab for better error printout --- ndb/include/ndb_version.h.in | 12 +++++- ndb/include/util/version.h | 3 +- ndb/src/common/util/version.c | 12 +++--- ndb/src/kernel/blocks/qmgr/Qmgr.hpp | 4 +- ndb/src/kernel/blocks/qmgr/QmgrMain.cpp | 51 ++++++++++++------------- ndb/tools/restore/restore_main.cpp | 3 +- 6 files changed, 48 insertions(+), 37 deletions(-) diff --git a/ndb/include/ndb_version.h.in b/ndb/include/ndb_version.h.in index d7f43eae40a..826f5124407 100644 --- a/ndb/include/ndb_version.h.in +++ b/ndb/include/ndb_version.h.in @@ -36,8 +36,16 @@ #define MAKE_VERSION(A,B,C) (((A) << 16) | ((B) << 8) | ((C) << 0)) #define NDB_VERSION_D MAKE_VERSION(NDB_VERSION_MAJOR, NDB_VERSION_MINOR, NDB_VERSION_BUILD) - -#define NDB_VERSION_STRING (getVersionString(NDB_VERSION, NDB_VERSION_STATUS)) +#define NDB_VERSION_STRING_BUF_SZ 100 +#ifdef __cplusplus +extern "C" +#else +extern +#endif +char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ]; +#define NDB_VERSION_STRING (getVersionString(NDB_VERSION, NDB_VERSION_STATUS, \ + ndb_version_string_buf, \ + sizeof(ndb_version_string_buf))) #define NDB_VERSION ndbGetOwnVersion() diff --git a/ndb/include/util/version.h b/ndb/include/util/version.h index 5459e44b818..62dc07d905a 100644 --- a/ndb/include/util/version.h +++ b/ndb/include/util/version.h @@ -30,7 +30,8 @@ extern "C" { Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build); - const char* getVersionString(Uint32 version, const char * status); + const char* getVersionString(Uint32 version, const char * status, + char *buf, unsigned sz); void ndbPrintVersion(); Uint32 ndbGetOwnVersion(); diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c index 7221dc48fa4..ba4bcf30516 100644 --- a/ndb/src/common/util/version.c +++ b/ndb/src/common/util/version.c @@ -38,22 +38,24 @@ Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build) { } -const char * getVersionString(Uint32 version, const char * status) { - char buff[100]; +char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ]; +const char * getVersionString(Uint32 version, const char * status, + char *buf, unsigned sz) +{ if (status && status[0] != 0) - basestring_snprintf(buff, sizeof(buff), + basestring_snprintf(buf, sz, "Version %d.%d.%d (%s)", getMajor(version), getMinor(version), getBuild(version), status); else - basestring_snprintf(buff, sizeof(buff), + basestring_snprintf(buf, sz, "Version %d.%d.%d", getMajor(version), getMinor(version), getBuild(version)); - return strdup(buff); + return buf; } typedef enum { diff --git a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp index 0ff7cea6d9f..6d22ed0e509 100644 --- a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp +++ b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp @@ -257,8 +257,8 @@ private: void hbReceivedLab(Signal* signal); void sendCmRegrefLab(Signal* signal, BlockReference ref, CmRegRef::ErrorCode); - void systemErrorBecauseOtherNodeFailed(Signal* signal, NodeId); - void systemErrorLab(Signal* signal, + void systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line, NodeId); + void systemErrorLab(Signal* signal, Uint32 line, const char* message = NULL); void prepFailReqLab(Signal* signal); void prepFailConfLab(Signal* signal); diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index da8596076ec..0337640d229 100644 --- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -76,7 +76,7 @@ void Qmgr::execCM_HEARTBEAT(Signal* signal) void Qmgr::execCM_NODEINFOREF(Signal* signal) { jamEntry(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); return; }//Qmgr::execCM_NODEINFOREF() @@ -121,7 +121,7 @@ void Qmgr::execCONTINUEB(Signal* signal) default: jam(); // ZCOULD_NOT_OCCUR_ERROR; - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); return; break; }//switch @@ -593,7 +593,7 @@ void Qmgr::execCM_REGCONF(Signal* signal) jam(); char buf[128]; BaseString::snprintf(buf,sizeof(buf),"incompatible version own=0x%x other=0x%x, shutting down", NDB_VERSION, cmRegConf->presidentVersion); - systemErrorLab(signal, buf); + systemErrorLab(signal, __LINE__, buf); return; } @@ -688,7 +688,7 @@ void Qmgr::execCM_REGREF(Signal* signal) switch (TrefuseReason) { case CmRegRef::ZINCOMPATIBLE_VERSION: jam(); - systemErrorLab(signal, "incompatible version, connection refused by running ndb node"); + systemErrorLab(signal, __LINE__, "incompatible version, connection refused by running ndb node"); break; case CmRegRef::ZBUSY: case CmRegRef::ZBUSY_TO_PRES: @@ -1751,7 +1751,7 @@ void Qmgr::execAPI_FAILCONF(Signal* signal) if (failedNodePtr.p->rcv[0] == failedNodePtr.p->rcv[1]) { jam(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); } else { jam(); failedNodePtr.p->rcv[0] = 0; @@ -1763,7 +1763,7 @@ void Qmgr::execAPI_FAILCONF(Signal* signal) ndbout << "failedNodePtr.p->failState = " << (Uint32)(failedNodePtr.p->failState) << endl; #endif - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); }//if return; }//Qmgr::execAPI_FAILCONF() @@ -1780,7 +1780,7 @@ void Qmgr::execNDB_FAILCONF(Signal* signal) failedNodePtr.p->failState = NORMAL; } else { jam(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); }//if if (cpresident == getOwnNodeId()) { jam(); @@ -1931,20 +1931,13 @@ void Qmgr::execAPI_REGREQ(Signal* signal) #endif bool compatability_check; - switch(getNodeInfo(apiNodePtr.i).getType()){ + NodeInfo::NodeType type= getNodeInfo(apiNodePtr.i).getType(); + switch(type){ case NodeInfo::API: compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version); - if (!compatability_check) - infoEvent("Connection attempt from api or mysqld id=%d with %s " - "incompatible with %s", apiNodePtr.i, - getVersionString(version,""), NDB_VERSION_STRING); break; case NodeInfo::MGM: compatability_check = ndbCompatible_ndb_mgmt(NDB_VERSION, version); - if (!compatability_check) - infoEvent("Connection attempt from management server id=%d with %s " - "incompatible with %s", apiNodePtr.i, - getVersionString(version,""), NDB_VERSION_STRING); break; case NodeInfo::REP: // compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version); @@ -1953,13 +1946,19 @@ void Qmgr::execAPI_REGREQ(Signal* signal) case NodeInfo::INVALID: default: sendApiRegRef(signal, ref, ApiRegRef::WrongType); - infoEvent("Invalid connection attempt with type %d", - getNodeInfo(apiNodePtr.i).getType()); + infoEvent("Invalid connection attempt with type %d", type); return; } if (!compatability_check) { jam(); + char buf[NDB_VERSION_STRING_BUF_SZ]; + infoEvent("Connection attempt from %s id=%d with %s " + "incompatible with %s", + type == NodeInfo::API ? "api or mysqld" : "management server", + apiNodePtr.i, + getVersionString(version,"",buf,sizeof(buf)), + NDB_VERSION_STRING); apiNodePtr.p->phase = ZAPI_INACTIVE; sendApiRegRef(signal, ref, ApiRegRef::UnsupportedVersion); return; @@ -2085,7 +2084,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec); if (failedNodePtr.i == getOwnNodeId()) { jam(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); return; }//if @@ -2093,7 +2092,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec); if (myNodePtr.p->phase != ZRUNNING) { jam(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); return; }//if TnoFailedNodes = cnoFailedNodes; @@ -2172,7 +2171,7 @@ void Qmgr::execPREP_FAILREQ(Signal* signal) ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec); if (myNodePtr.p->phase != ZRUNNING) { jam(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); return; }//if @@ -2675,7 +2674,7 @@ void Qmgr::execREAD_NODESREQ(Signal* signal) ReadNodesConf::SignalLength, JBB); }//Qmgr::execREAD_NODESREQ() -void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, +void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line, NodeId failedNodeId) { jam(); @@ -2687,11 +2686,11 @@ void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, "Node was shutdown during startup because node %d failed", failedNodeId); - progError(__LINE__, ERR_SR_OTHERNODEFAILED, buf); + progError(line, ERR_SR_OTHERNODEFAILED, buf); } -void Qmgr::systemErrorLab(Signal* signal, const char * message) +void Qmgr::systemErrorLab(Signal* signal, Uint32 line, const char * message) { jam(); // Broadcast that this node is failing to other nodes @@ -2699,7 +2698,7 @@ void Qmgr::systemErrorLab(Signal* signal, const char * message) // If it's known why shutdown occured // an error message has been passed to this function - progError(__LINE__, 0, message); + progError(line, 0, message); return; }//Qmgr::systemErrorLab() @@ -2867,7 +2866,7 @@ Uint16 Qmgr::translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId) }//for if (TtdiNodeId == ZNIL) { jam(); - systemErrorLab(signal); + systemErrorLab(signal, __LINE__); }//if return TtdiNodeId; }//Qmgr::translateDynamicIdToNodeId() diff --git a/ndb/tools/restore/restore_main.cpp b/ndb/tools/restore/restore_main.cpp index 84f9511fe2f..0c4419bb072 100644 --- a/ndb/tools/restore/restore_main.cpp +++ b/ndb/tools/restore/restore_main.cpp @@ -251,8 +251,9 @@ main(int argc, char** argv) const BackupFormat::FileHeader & tmp = metaData.getFileHeader(); const Uint32 version = tmp.NdbVersion; + char buf[NDB_VERSION_STRING_BUF_SZ]; ndbout << "Ndb version in backup files: " - << getVersionString(version, 0) << endl; + << getVersionString(version, 0, buf, sizeof(buf)) << endl; /** * check wheater we can restore the backup (right version). From a1270b65db4e017ca512fab9554e0d4961062c05 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 20:02:33 +0400 Subject: [PATCH 25/39] A fix and a test case for Bug#11183 "mysql_stmt_reset() doesn't reset information about error". --- libmysql/libmysql.c | 12 +++++++++++ tests/mysql_client_test.c | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 4d92db26406..d80b2ef0e39 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1834,6 +1834,17 @@ static void net_clear_error(NET *net) } } + +static void stmt_clear_error(MYSQL_STMT *stmt) +{ + if (stmt->last_errno) + { + stmt->last_errno= 0; + stmt->last_error[0]= '\0'; + strmov(stmt->sqlstate, not_error_sqlstate); + } +} + /* Set statement error code, sqlstate, and error message from given errcode and sqlstate. @@ -4625,6 +4636,7 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt) param < param_end; param++) param->long_data_used= 0; + stmt_clear_error(stmt); DBUG_RETURN(0); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index f874276a656..b7398494deb 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11697,6 +11697,50 @@ static void test_bug9735() myquery(rc); } +/* Bug#11183 "mysql_stmt_reset() doesn't reset information about error" */ + +static void test_bug11183() +{ + int rc; + MYSQL_STMT *stmt; + char bug_statement[]= "insert into t1 values (1)"; + + myheader("test_bug11183"); + + mysql_query(mysql, "drop table t1 if exists"); + mysql_query(mysql, "create table t1 (a int)"); + + stmt= mysql_stmt_init(mysql); + DIE_UNLESS(stmt != 0); + + rc= mysql_stmt_prepare(stmt, bug_statement, strlen(bug_statement)); + check_execute(stmt, rc); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); + + /* Trying to execute statement that should fail on execute stage */ + rc= mysql_stmt_execute(stmt); + DIE_UNLESS(rc); + + mysql_stmt_reset(stmt); + DIE_UNLESS(mysql_stmt_errno(stmt) == 0); + + mysql_query(mysql, "create table t1 (a int)"); + + /* Trying to execute statement that should pass ok */ + if (mysql_stmt_execute(stmt)) + { + mysql_stmt_reset(stmt); + DIE_UNLESS(mysql_stmt_errno(stmt) == 0); + } + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf @@ -11913,6 +11957,7 @@ static struct my_tests_st my_tests[]= { { "test_bug7990", test_bug7990 }, { "test_bug8378", test_bug8378 }, { "test_bug9735", test_bug9735 }, + { "test_bug11183", test_bug11183 }, { 0, 0 } }; From 36810d25f337394589d51bfcdd260f127c6d8eb7 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 14 Jul 2005 20:02:37 +0400 Subject: [PATCH 26/39] Post-merge fixes. --- mysql-test/r/fulltext_order_by.result | 2 +- mysql-test/t/fulltext_order_by.test | 2 ++ sql/sql_select.cc | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result index 130d096e00f..3b52be4b1f2 100644 --- a/mysql-test/r/fulltext_order_by.result +++ b/mysql-test/r/fulltext_order_by.result @@ -158,5 +158,5 @@ where match(c.beitrag) against ('+abc' in boolean mode) order by match(betreff) against ('+abc' in boolean mode) desc; -text id betreff +ERROR HY000: The used table type doesn't support FULLTEXT indexes drop table t1,t2,t3; diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test index 6894f63fa77..3101242613a 100644 --- a/mysql-test/t/fulltext_order_by.test +++ b/mysql-test/t/fulltext_order_by.test @@ -117,6 +117,8 @@ where order by match(b.betreff) against ('+abc' in boolean mode) desc; +-- todo psergey: fix +--error 1214 select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3d9315a2bd6..04a9126d8ed 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5178,7 +5178,7 @@ static void add_not_null_conds(JOIN *join) when it is called from make_join_select after this function is called. */ - if (notnull->fix_fields(join->thd, join->tables_list, ¬null)) + if (notnull->fix_fields(join->thd, ¬null)) DBUG_VOID_RETURN; DBUG_EXECUTE("where",print_where(notnull, referred_tab->table->alias);); From 8afeb337f04b2f50687c7b364b2884a331ea17a9 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 14 Jul 2005 18:04:44 +0200 Subject: [PATCH 27/39] BUG#11898 ndb_mgmd not releasing resources, added "ping" on add_listener + added close of some fd's + debug prints --- ndb/src/mgmclient/CommandInterpreter.cpp | 34 +++++++-- ndb/src/mgmsrv/MgmtSrvr.hpp | 11 +-- ndb/src/mgmsrv/Services.cpp | 93 +++++++++++++++++++----- 3 files changed, 105 insertions(+), 33 deletions(-) diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 34fe57d1fca..e1619917de5 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -455,11 +455,13 @@ static int do_event_thread; static void* event_thread_run(void* m) { + DBUG_ENTER("event_thread_run"); + NdbMgmHandle handle= *(NdbMgmHandle*)m; int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 }; int fd = ndb_mgm_listen_event(handle, filter); - if (fd > 0) + if (fd != NDB_INVALID_SOCKET) { do_event_thread= 1; char *tmp= 0; @@ -468,20 +470,26 @@ event_thread_run(void* m) do { if (tmp == 0) NdbSleep_MilliSleep(10); if((tmp = in.gets(buf, 1024))) - ndbout << tmp; + { + const char ping_token[]= ""; + if (memcmp(ping_token,tmp,sizeof(ping_token)-1)) + ndbout << tmp; + } } while(do_event_thread); + NDB_CLOSE_SOCKET(fd); } else { do_event_thread= -1; } - return NULL; + DBUG_RETURN(NULL); } bool CommandInterpreter::connect() { + DBUG_ENTER("CommandInterpreter::connect"); if(!m_connected) { if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) @@ -512,8 +520,19 @@ CommandInterpreter::connect() do_event_thread == 0 || do_event_thread == -1) { - printf("Warning, event thread startup failed, degraded printouts as result\n"); + DBUG_PRINT("info",("Warning, event thread startup failed, " + "degraded printouts as result, errno=%d", + errno)); + printf("Warning, event thread startup failed, " + "degraded printouts as result, errno=%d\n", errno); do_event_thread= 0; + if (m_event_thread) + { + void *res; + NdbThread_WaitFor(m_event_thread, &res); + NdbThread_Destroy(&m_event_thread); + } + ndb_mgm_disconnect(m_mgmsrv2); } } else @@ -521,6 +540,8 @@ CommandInterpreter::connect() printf("Warning, event connect failed, degraded printouts as result\n"); } m_connected= true; + DBUG_PRINT("info",("Connected to Management Server at: %s:%d", + host,port)); if (m_verbose) { printf("Connected to Management Server at: %s:%d\n", @@ -528,12 +549,13 @@ CommandInterpreter::connect() } } } - return m_connected; + DBUG_RETURN(m_connected); } bool CommandInterpreter::disconnect() { + DBUG_ENTER("CommandInterpreter::disconnect"); if (m_event_thread) { void *res; do_event_thread= 0; @@ -550,7 +572,7 @@ CommandInterpreter::disconnect() } m_connected= false; } - return true; + DBUG_RETURN(true); } //***************************************************************************** diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index ce78983b3c3..423668fbd0e 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -60,6 +60,7 @@ public: } void add_listener(const Event_listener&); + void check_listeners(); void update_max_log_level(const LogLevel&); void update_log_level(const LogLevel&); @@ -764,16 +765,6 @@ private: int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type); ConfigRetriever *m_config_retriever; - -public: - /** - * This method does not exist - */ - struct Area51 { - class TransporterFacade * theFacade; - class TransporterRegistry * theRegistry; - }; - Area51 getStuff(); }; inline diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 8ba8c2fe87e..00cf6390c73 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -253,15 +253,19 @@ ParserRow commands[] = { }; MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock) - : SocketServer::Session(sock), m_mgmsrv(mgm) { + : SocketServer::Session(sock), m_mgmsrv(mgm) +{ + DBUG_ENTER("MgmApiSession::MgmApiSession"); m_input = new SocketInputStream(sock); m_output = new SocketOutputStream(sock); m_parser = new Parser_t(commands, *m_input, true, true, true); m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); + DBUG_VOID_RETURN; } MgmApiSession::~MgmApiSession() { + DBUG_ENTER("MgmApiSession::~MgmApiSession"); if (m_input) delete m_input; if (m_output) @@ -270,10 +274,19 @@ MgmApiSession::~MgmApiSession() delete m_parser; if (m_allocated_resources) delete m_allocated_resources; + if(m_socket != NDB_INVALID_SOCKET) + { + NDB_CLOSE_SOCKET(m_socket); + m_socket= NDB_INVALID_SOCKET; + } + DBUG_VOID_RETURN; } void -MgmApiSession::runSession() { +MgmApiSession::runSession() +{ + DBUG_ENTER("MgmApiSession::runSession"); + Parser_t::Context ctx; while(!m_stop) { m_parser->run(ctx, *this); @@ -301,8 +314,13 @@ MgmApiSession::runSession() { break; } } - if(m_socket >= 0) + if(m_socket != NDB_INVALID_SOCKET) + { NDB_CLOSE_SOCKET(m_socket); + m_socket= NDB_INVALID_SOCKET; + } + + DBUG_VOID_RETURN; } #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT @@ -1236,7 +1254,7 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) Uint32 threshold; LogLevel::EventCategory cat; Logger::LoggerLevel severity; - int i; + int i, n; DBUG_ENTER("Ndb_mgmd_event_service::log"); DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId)); @@ -1248,28 +1266,30 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) Vector copy; m_clients.lock(); - for(i = m_clients.size() - 1; i >= 0; i--){ - if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)){ - if(m_clients[i].m_socket != NDB_INVALID_SOCKET && - println_socket(m_clients[i].m_socket, - MAX_WRITE_TIMEOUT, m_text) == -1){ - copy.push_back(m_clients[i].m_socket); + for(i = m_clients.size() - 1; i >= 0; i--) + { + if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)) + { + int fd= m_clients[i].m_socket; + if(fd != NDB_INVALID_SOCKET && + println_socket(fd, MAX_WRITE_TIMEOUT, m_text) == -1) + { + copy.push_back(fd); m_clients.erase(i, false); } } } m_clients.unlock(); - for(i = 0; (unsigned)i < copy.size(); i++){ - NDB_CLOSE_SOCKET(copy[i]); - } + if ((n= (int)copy.size())) + { + for(i= 0; i < n; i++) + NDB_CLOSE_SOCKET(copy[i]); - if(copy.size()){ LogLevel tmp; tmp.clear(); m_clients.lock(); - for(i = 0; (unsigned)i < m_clients.size(); i++){ + for(i= m_clients.size() - 1; i >= 0; i--) tmp.set_max(m_clients[i].m_logLevel); - } m_clients.unlock(); update_log_level(tmp); } @@ -1297,9 +1317,48 @@ Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp) } void -Ndb_mgmd_event_service::add_listener(const Event_listener& client){ +Ndb_mgmd_event_service::check_listeners() +{ + int i, n= 0; + DBUG_ENTER("Ndb_mgmd_event_service::check_listeners"); + m_clients.lock(); + for(i= m_clients.size() - 1; i >= 0; i--) + { + int fd= m_clients[i].m_socket; + DBUG_PRINT("info",("%d %d",i,fd)); + char buf[1]; + buf[0]=0; + if (fd != NDB_INVALID_SOCKET && + println_socket(fd,MAX_WRITE_TIMEOUT,"") == -1) + { + NDB_CLOSE_SOCKET(fd); + m_clients.erase(i, false); + n=1; + } + } + if (n) + { + LogLevel tmp; tmp.clear(); + for(i= m_clients.size() - 1; i >= 0; i--) + tmp.set_max(m_clients[i].m_logLevel); + update_log_level(tmp); + } + m_clients.unlock(); + DBUG_VOID_RETURN; +} + +void +Ndb_mgmd_event_service::add_listener(const Event_listener& client) +{ + DBUG_ENTER("Ndb_mgmd_event_service::add_listener"); + DBUG_PRINT("enter",("client.m_socket: %d", client.m_socket)); + + check_listeners(); + m_clients.push_back(client); update_max_log_level(client.m_logLevel); + + DBUG_VOID_RETURN; } void From ec52d680d23ed13a1f1799301f77dc0da2eeae72 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 14 Jul 2005 18:08:01 +0200 Subject: [PATCH 28/39] misc (memleak) fixes: added using ndb_end and showing mem allocation stat at exit added init of variable added destruction of LocalConfig to still memleak added delete of theFacade on exit stopSessions(true) on socket server to ensure destuction of threads added destruction of arbit manager thread added true option to stopSessions in transporter facade to ensure destructions of threads --- ndb/include/util/ndb_opts.h | 2 + ndb/src/common/logger/LogHandler.cpp | 1 + ndb/src/mgmapi/mgmapi.cpp | 19 +++++- ndb/src/mgmclient/main.cpp | 8 ++- ndb/src/mgmsrv/MgmtSrvr.cpp | 25 ++----- ndb/src/mgmsrv/main.cpp | 99 ++++++++++++++-------------- ndb/src/ndbapi/ClusterMgr.cpp | 18 +++-- ndb/src/ndbapi/TransporterFacade.cpp | 25 ++++--- 8 files changed, 112 insertions(+), 85 deletions(-) diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h index aa7a02f58ae..ca4ca5eac83 100644 --- a/ndb/include/util/ndb_opts.h +++ b/ndb/include/util/ndb_opts.h @@ -28,6 +28,7 @@ const char *opt_connect_str= 0;\ my_bool opt_ndb_optimized_node_selection +bool opt_endinfo= 0; my_bool opt_ndb_shm; #define OPT_NDB_CONNECTSTRING 'c' @@ -93,6 +94,7 @@ ndb_std_get_one_option(int optid, { DBUG_PUSH(argument); } + opt_endinfo= 1; break; case 'V': ndb_std_print_version(); diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp index ec4137297f1..a9d4512112f 100644 --- a/ndb/src/common/logger/LogHandler.cpp +++ b/ndb/src/common/logger/LogHandler.cpp @@ -31,6 +31,7 @@ LogHandler::LogHandler() : m_last_message[0]= 0; m_last_log_time= 0; m_now= 0; + m_last_level= (Logger::LoggerLevel)-1; } LogHandler::~LogHandler() diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 863f54ce51a..6a949c6006d 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -143,6 +143,7 @@ extern "C" NdbMgmHandle ndb_mgm_create_handle() { + DBUG_ENTER("ndb_mgm_create_handle"); NdbMgmHandle h = (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME)); h->connected = 0; @@ -162,17 +163,20 @@ ndb_mgm_create_handle() h->logfile = 0; #endif - return h; + DBUG_PRINT("exit",("ret: %lx", h)); + DBUG_RETURN(h); } extern "C" int ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv) { + handle->cfg.~LocalConfig(); new (&(handle->cfg)) LocalConfig; if (!handle->cfg.init(mgmsrv, 0) || handle->cfg.ids.size() == 0) { + handle->cfg.~LocalConfig(); new (&(handle->cfg)) LocalConfig; handle->cfg.init(0, 0); /* reset the LocalCongig */ SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, ""); @@ -189,8 +193,11 @@ extern "C" void ndb_mgm_destroy_handle(NdbMgmHandle * handle) { + DBUG_ENTER("ndb_mgm_destroy_handle"); if(!handle) return; + DBUG_PRINT("enter",("*handle: %lx", *handle)); + if((* handle)->connected){ ndb_mgm_disconnect(* handle); } @@ -203,6 +210,7 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle) (*handle)->cfg.~LocalConfig(); my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR)); * handle = 0; + DBUG_VOID_RETURN; } /***************************************************************************** @@ -251,6 +259,9 @@ static const Properties * ndb_mgm_call(NdbMgmHandle handle, const ParserRow *command_reply, const char *cmd, const Properties *cmd_args) { + DBUG_ENTER("ndb_mgm_call"); + DBUG_PRINT("enter",("handle->socket: %d, cmd: %s", + handle->socket, cmd)); SocketOutputStream out(handle->socket); SocketInputStream in(handle->socket, handle->read_timeout); @@ -310,6 +321,8 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow *command_reply, /** * Print some info about why the parser returns NULL */ + DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s", + ctx.m_status, ctx.m_currentToken)); //ndbout << " status=" << ctx.m_status << ", curr=" //<< ctx.m_currentToken << endl; } @@ -321,9 +334,9 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow *command_reply, p->print(handle->logfile, "IN: "); } #endif - return p; + DBUG_RETURN(p); #else - return parser.parse(ctx, session); + DBUG_RETURN(parser.parse(ctx, session)); #endif } diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp index 73f0bad86c0..9128df4f978 100644 --- a/ndb/src/mgmclient/main.cpp +++ b/ndb/src/mgmclient/main.cpp @@ -44,7 +44,9 @@ static Ndb_mgmclient* com; extern "C" void -handler(int sig){ +handler(int sig) +{ + DBUG_ENTER("handler"); switch(sig){ case SIGPIPE: /** @@ -54,6 +56,7 @@ handler(int sig){ com->disconnect(); break; } + DBUG_VOID_RETURN; } NDB_STD_OPTS_VARS; @@ -166,7 +169,8 @@ int main(int argc, char** argv){ com->execute(opt_execute_str,_try_reconnect, &ret); } delete com; - + + ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); return ret; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index ceaedc9955b..34bc8d433cc 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -571,10 +571,11 @@ MgmtSrvr::check_start() bool MgmtSrvr::start(BaseString &error_string) { + DBUG_ENTER("MgmtSrvr::start"); if (_props == NULL) { if (!check_start()) { error_string.append("MgmtSrvr.cpp: check_start() failed."); - return false; + DBUG_RETURN(false); } } theFacade= TransporterFacade::theFacadeInstance= new TransporterFacade(); @@ -582,12 +583,12 @@ MgmtSrvr::start(BaseString &error_string) if(theFacade == 0) { DEBUG("MgmtSrvr.cpp: theFacade is NULL."); error_string.append("MgmtSrvr.cpp: theFacade is NULL."); - return false; + DBUG_RETURN(false); } if ( theFacade->start_instance (_ownNodeId, (ndb_mgm_configuration*)_config->m_configValues) < 0) { DEBUG("MgmtSrvr.cpp: TransporterFacade::start_instance < 0."); - return false; + DBUG_RETURN(false); } MGM_REQUIRE(_blockNumber == 1); @@ -603,7 +604,7 @@ MgmtSrvr::start(BaseString &error_string) error_string.append("MgmtSrvr.cpp: _blockNumber is -1."); theFacade->stop_instance(); theFacade = 0; - return false; + DBUG_RETURN(false); } _ownReference = numberToRef(_blockNumber, _ownNodeId); @@ -625,7 +626,7 @@ MgmtSrvr::start(BaseString &error_string) "MgmtSrvr_Service", NDB_THREAD_PRIO_LOW); - return true; + DBUG_RETURN(true); } @@ -639,6 +640,7 @@ MgmtSrvr::~MgmtSrvr() if(theFacade != 0){ theFacade->stop_instance(); + delete theFacade; theFacade = 0; } @@ -2583,19 +2585,6 @@ MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted) } -/***************************************************************************** - * Area 51 ??? - *****************************************************************************/ - -MgmtSrvr::Area51 -MgmtSrvr::getStuff() -{ - Area51 ret; - ret.theFacade = theFacade; - ret.theRegistry = theFacade->theTransporterRegistry; - return ret; -} - NodeId MgmtSrvr::getPrimaryNode() const { #if 0 diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index 61b83b86538..ffe58231eb3 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -53,16 +53,16 @@ const char progname[] = "mgmtsrvr"; * @struct MgmGlobals * @brief Global Variables used in the management server ******************************************************************************/ +/** Command line arguments */ +static int opt_daemon; // NOT bool, bool need not be int +static int opt_non_interactive; +static int opt_interactive; +static const char * opt_config_filename= 0; + struct MgmGlobals { MgmGlobals(); ~MgmGlobals(); - /** Command line arguments */ - int daemon; // NOT bool, bool need not be int - int non_interactive; - int interactive; - const char * config_filename; - /** Stuff found in environment or in local config */ NodeId localNodeId; bool use_specific_ip; @@ -77,7 +77,7 @@ struct MgmGlobals { }; int g_no_nodeid_checks= 0; -static MgmGlobals glob; +static MgmGlobals *glob= 0; /****************************************************************************** * Function prototypes @@ -108,14 +108,14 @@ static struct my_option my_long_options[] = { NDB_STD_OPTS("ndb_mgmd"), { "config-file", 'f', "Specify cluster configuration file", - (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, + (gptr*) &opt_config_filename, (gptr*) &opt_config_filename, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)", - (gptr*) &glob.daemon, (gptr*) &glob.daemon, 0, + (gptr*) &opt_daemon, (gptr*) &opt_daemon, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, { "interactive", OPT_INTERACTIVE, "Run interactive. Not supported but provided for testing purposes", - (gptr*) &glob.interactive, (gptr*) &glob.interactive, 0, + (gptr*) &opt_interactive, (gptr*) &opt_interactive, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { "no-nodeid-checks", OPT_NO_NODEID_CHECKS, "Do not provide any node id checks", @@ -123,13 +123,13 @@ static struct my_option my_long_options[] = GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { "nodaemon", OPT_NO_DAEMON, "Don't run as daemon, but don't read from stdin", - (gptr*) &glob.non_interactive, (gptr*) &glob.non_interactive, 0, + (gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, #if NDB_VERSION_MAJOR <= 4 { "config-file", 'c', "-c provided for backwards compatability, will be removed in 5.0." " Use -f instead", - (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, + (gptr*) &opt_config_filename, (gptr*) &opt_config_filename, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #endif { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -167,6 +167,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), int main(int argc, char** argv) { NDB_INIT(argv[0]); + glob= new MgmGlobals; /** * OSE specific. Enable shared ownership of file system resources. @@ -186,40 +187,40 @@ int main(int argc, char** argv) if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); - if (glob.interactive || - glob.non_interactive) { - glob.daemon= 0; + if (opt_interactive || + opt_non_interactive) { + opt_daemon= 0; } - glob.socketServer = new SocketServer(); + glob->socketServer = new SocketServer(); MgmApiService * mapi = new MgmApiService(); - glob.mgmObject = new MgmtSrvr(glob.socketServer, - glob.config_filename, + glob->mgmObject = new MgmtSrvr(glob->socketServer, + opt_config_filename, opt_connect_str); - if (glob.mgmObject->init()) + if (glob->mgmObject->init()) goto error_end; my_setwd(NdbConfig_get_path(0), MYF(0)); - glob.localNodeId= glob.mgmObject->getOwnNodeId(); - if (glob.localNodeId == 0) { + glob->localNodeId= glob->mgmObject->getOwnNodeId(); + if (glob->localNodeId == 0) { goto error_end; } - glob.port= glob.mgmObject->getPort(); + glob->port= glob->mgmObject->getPort(); - if (glob.port == 0) + if (glob->port == 0) goto error_end; - glob.interface_name = 0; - glob.use_specific_ip = false; + glob->interface_name = 0; + glob->use_specific_ip = false; - if(!glob.use_specific_ip){ + if(!glob->use_specific_ip){ int count= 5; // no of retries for tryBind - while(!glob.socketServer->tryBind(glob.port, glob.interface_name)){ + while(!glob->socketServer->tryBind(glob->port, glob->interface_name)){ if (--count > 0) { NdbSleep_MilliSleep(1000); continue; @@ -228,33 +229,33 @@ int main(int argc, char** argv) "Please check if the port is already used,\n" "(perhaps a ndb_mgmd is already running),\n" "and if you are executing on the correct computer", - (glob.interface_name ? glob.interface_name : "*"), glob.port); + (glob->interface_name ? glob->interface_name : "*"), glob->port); goto error_end; } - free(glob.interface_name); - glob.interface_name = 0; + free(glob->interface_name); + glob->interface_name = 0; } - if(!glob.socketServer->setup(mapi, glob.port, glob.interface_name)){ + if(!glob->socketServer->setup(mapi, glob->port, glob->interface_name)){ ndbout_c("Unable to setup management port: %d!\n" "Please check if the port is already used,\n" "(perhaps a ndb_mgmd is already running),\n" "and if you are executing on the correct computer", - glob.port); + glob->port); delete mapi; goto error_end; } - if(!glob.mgmObject->check_start()){ + if(!glob->mgmObject->check_start()){ ndbout_c("Unable to check start management server."); ndbout_c("Probably caused by illegal initial configuration file."); goto error_end; } - if (glob.daemon) { + if (opt_daemon) { // Become a daemon - char *lockfile= NdbConfig_PidFileName(glob.localNodeId); - char *logfile= NdbConfig_StdoutFileName(glob.localNodeId); + char *lockfile= NdbConfig_PidFileName(glob->localNodeId); + char *logfile= NdbConfig_StdoutFileName(glob->localNodeId); NdbAutoPtr tmp_aptr1(lockfile), tmp_aptr2(logfile); if (NdbDaemon_Make(lockfile, logfile, 0) == -1) { @@ -268,7 +269,7 @@ int main(int argc, char** argv) #endif { BaseString error_string; - if(!glob.mgmObject->start(error_string)){ + if(!glob->mgmObject->start(error_string)){ ndbout_c("Unable to start management server."); ndbout_c("Probably caused by illegal initial configuration file."); ndbout_c(error_string.c_str()); @@ -276,8 +277,8 @@ int main(int argc, char** argv) } } - //glob.mgmObject->saveConfig(); - mapi->setMgm(glob.mgmObject); + //glob->mgmObject->saveConfig(); + mapi->setMgm(glob->mgmObject); char msg[256]; BaseString::snprintf(msg, sizeof(msg), @@ -286,16 +287,16 @@ int main(int argc, char** argv) g_eventLogger.info(msg); BaseString::snprintf(msg, 256, "Id: %d, Command port: %d", - glob.localNodeId, glob.port); + glob->localNodeId, glob->port); ndbout_c(msg); g_eventLogger.info(msg); g_StopServer = false; - glob.socketServer->startServer(); + glob->socketServer->startServer(); #if ! defined NDB_OSE && ! defined NDB_SOFTOSE - if(glob.interactive) { - CommandInterpreter com(* glob.mgmObject); + if(opt_interactive) { + CommandInterpreter com(* glob->mgmObject); while(com.readAndExecute()); } else #endif @@ -305,22 +306,22 @@ int main(int argc, char** argv) } g_eventLogger.info("Shutting down server..."); - glob.socketServer->stopServer(); - glob.socketServer->stopSessions(); + glob->socketServer->stopServer(); + glob->socketServer->stopSessions(true); g_eventLogger.info("Shutdown complete"); + delete glob; + ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); return 0; error_end: + delete glob; + ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); return 1; } MgmGlobals::MgmGlobals(){ // Default values port = 0; - config_filename = NULL; interface_name = 0; - daemon = 1; - non_interactive = 0; - interactive = 0; socketServer = 0; mgmObject = 0; } diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp index 9603ddf7751..543bdf1155e 100644 --- a/ndb/src/ndbapi/ClusterMgr.cpp +++ b/ndb/src/ndbapi/ClusterMgr.cpp @@ -64,16 +64,21 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade): theStop(0), theFacade(_facade) { + DBUG_ENTER("ClusterMgr::ClusterMgr"); ndbSetOwnVersion(); clusterMgrThreadMutex = NdbMutex_Create(); noOfAliveNodes= 0; noOfConnectedNodes= 0; theClusterMgrThread= 0; + DBUG_VOID_RETURN; } -ClusterMgr::~ClusterMgr(){ +ClusterMgr::~ClusterMgr() +{ + DBUG_ENTER("ClusterMgr::~ClusterMgr"); doStop(); NdbMutex_Destroy(clusterMgrThreadMutex); + DBUG_VOID_RETURN; } void @@ -152,7 +157,6 @@ ClusterMgr::doStop( ){ if (theClusterMgrThread) { NdbThread_WaitFor(theClusterMgrThread, &status); NdbThread_Destroy(&theClusterMgrThread); - theClusterMgrThread= 0; } NdbMutex_Unlock(clusterMgrThreadMutex); DBUG_VOID_RETURN; @@ -468,6 +472,8 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){ ArbitMgr::ArbitMgr(TransporterFacade & _fac) : theFacade(_fac) { + DBUG_ENTER("ArbitMgr::ArbitMgr"); + theThreadMutex = NdbMutex_Create(); theInputCond = NdbCondition_Create(); theInputMutex = NdbMutex_Create(); @@ -485,13 +491,17 @@ ArbitMgr::ArbitMgr(TransporterFacade & _fac) memset(&theChooseReq1, 0, sizeof(theChooseReq1)); memset(&theChooseReq2, 0, sizeof(theChooseReq2)); memset(&theStopOrd, 0, sizeof(theStopOrd)); + + DBUG_VOID_RETURN; } ArbitMgr::~ArbitMgr() { + DBUG_ENTER("ArbitMgr::~ArbitMgr"); NdbMutex_Destroy(theThreadMutex); NdbCondition_Destroy(theInputCond); NdbMutex_Destroy(theInputMutex); + DBUG_VOID_RETURN; } // Start arbitrator thread. This is kernel request. @@ -508,7 +518,7 @@ ArbitMgr::doStart(const Uint32* theData) sendSignalToThread(aSignal); void* value; NdbThread_WaitFor(theThread, &value); - theThread = NULL; + NdbThread_Destroy(&theThread); theState = StateInit; theInputFull = false; } @@ -547,7 +557,7 @@ ArbitMgr::doStop(const Uint32* theData) sendSignalToThread(aSignal); void* value; NdbThread_WaitFor(theThread, &value); - theThread = NULL; + NdbThread_Destroy(&theThread); theState = StateInit; } NdbMutex_Unlock(theThreadMutex); diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp index 93cec59ada6..a06a8b588b1 100644 --- a/ndb/src/ndbapi/TransporterFacade.cpp +++ b/ndb/src/ndbapi/TransporterFacade.cpp @@ -395,12 +395,10 @@ TransporterFacade::doStop(){ if (theReceiveThread) { NdbThread_WaitFor(theReceiveThread, &status); NdbThread_Destroy(&theReceiveThread); - theReceiveThread= 0; } if (theSendThread) { NdbThread_WaitFor(theSendThread, &status); NdbThread_Destroy(&theSendThread); - theSendThread= 0; } DBUG_VOID_RETURN; } @@ -435,7 +433,7 @@ void TransporterFacade::threadMainSend(void) theTransporterRegistry->stopSending(); m_socket_server.stopServer(); - m_socket_server.stopSessions(); + m_socket_server.stopSessions(true); theTransporterRegistry->stop_clients(); } @@ -477,6 +475,8 @@ TransporterFacade::TransporterFacade() : theReceiveThread(NULL), m_fragmented_signal_id(0) { + DBUG_ENTER("TransporterFacade::TransporterFacade"); + theOwnId = 0; theMutexPtr = NdbMutex_Create(); @@ -493,11 +493,15 @@ TransporterFacade::TransporterFacade() : m_max_trans_id = 0; theClusterMgr = new ClusterMgr(* this); + + DBUG_VOID_RETURN; } bool TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) { + DBUG_ENTER("TransporterFacade::init"); + theOwnId = nodeId; theTransporterRegistry = new TransporterRegistry(this); @@ -506,7 +510,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) * theTransporterRegistry); if(res <= 0){ TRP_DEBUG( "configureTransporters returned 0 or less" ); - return false; + DBUG_RETURN(false); } ndb_mgm_configuration_iterator iter(* props, CFG_SECTION_NODE); @@ -524,7 +528,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) iter.first(); if(iter.find(CFG_NODE_ID, nodeId)){ TRP_DEBUG( "Node info missing from config." ); - return false; + DBUG_RETURN(false); } Uint32 rank = 0; @@ -553,7 +557,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) if (!theTransporterRegistry->start_service(m_socket_server)){ ndbout_c("Unable to start theTransporterRegistry->start_service"); - return false; + DBUG_RETURN(false); } theReceiveThread = NdbThread_Create(runReceiveResponse_C, @@ -573,7 +577,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) signalLogger.logOn(true, 0, SignalLoggerManager::LogInOut); #endif - return true; + DBUG_RETURN(true); } @@ -694,8 +698,10 @@ TransporterFacade::open(void* objRef, DBUG_RETURN(r); } -TransporterFacade::~TransporterFacade(){ - +TransporterFacade::~TransporterFacade() +{ + DBUG_ENTER("TransporterFacade::~TransporterFacade"); + NdbMutex_Lock(theMutexPtr); delete theClusterMgr; delete theArbitMgr; @@ -705,6 +711,7 @@ TransporterFacade::~TransporterFacade(){ #ifdef API_TRACE signalLogger.setOutputStream(0); #endif + DBUG_VOID_RETURN; } void From a2b11ff2664cf00fea3aa10bd98c6fbb14ff6fc7 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 15 Jul 2005 00:01:49 +0400 Subject: [PATCH 29/39] A fix and a test case for Bug#11299 "prepared statement makes wrong SQL syntax in binlog which stops replication": disallow the use of parameter markers which can lead to generation of malformed binlog queries. --- mysql-test/r/ps.result | 16 ++++++++++++++++ mysql-test/t/ps.test | 22 ++++++++++++++++++++++ sql/sql_lex.cc | 9 +++++++++ sql/sql_yacc.yy | 19 ++++++------------- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index ee558e0ea89..6cd32cbe8d0 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -660,3 +660,19 @@ lily river drop table t1; deallocate prepare stmt; +create table t1 (a int); +prepare stmt from "select ??"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 +prepare stmt from "select ?FROM t1"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?FROM t1' at line 1 +prepare stmt from "select FROM t1 WHERE?=1"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM t1 WHERE?=1' at line 1 +prepare stmt from "update t1 set a=a+?WHERE 1"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?WHERE 1' at line 1 +select ?; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 +select ??; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '??' at line 1 +select ? from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t1' at line 1 +drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 01d62a2e198..d08098606a1 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -679,3 +679,25 @@ execute stmt using @param1; select utext from t1 where utext like '%%'; drop table t1; deallocate prepare stmt; +# +# Bug#11299 "prepared statement makes wrong SQL syntax in binlog which stops +# replication": check that errouneous queries with placeholders are not +# allowed +# +create table t1 (a int); +--error 1064 +prepare stmt from "select ??"; +--error 1064 +prepare stmt from "select ?FROM t1"; +--error 1064 +prepare stmt from "select FROM t1 WHERE?=1"; +--error 1064 +prepare stmt from "update t1 set a=a+?WHERE 1"; +--error 1064 +select ?; +--error 1064 +select ??; +--error 1064 +select ? from t1; +drop table t1; +# diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 904b4675c74..42e3b678c09 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -554,6 +554,15 @@ int yylex(void *arg, void *yythd) lex->next_state= MY_LEX_START; // Allow signed numbers if (c == ',') lex->tok_start=lex->ptr; // Let tok_start point at next item + /* + Check for a placeholder: it should not precede a possible identifier + because of binlogging: when a placeholder is replaced with + its value in a query for the binlog, the query must stay + grammatically correct. + */ + else if (c == '?' && ((THD*) yythd)->command == COM_PREPARE && + !ident_map[cs, yyPeek()]) + return(PARAM_MARKER); return((int) c); case MY_LEX_IDENT_OR_NCHAR: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bc21649fe54..2587ce7e1a5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -528,6 +528,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token NOW_SYM %token OLD_PASSWORD %token PASSWORD +%token PARAM_MARKER %token POINTFROMTEXT %token POINT_SYM %token POLYFROMTEXT @@ -4857,23 +4858,15 @@ text_string: ; param_marker: - '?' + PARAM_MARKER { THD *thd=YYTHD; LEX *lex= thd->lex; - if (thd->command == COM_PREPARE) + Item_param *item= new Item_param((uint) (lex->tok_start - + (uchar *) thd->query)); + if (!($$= item) || lex->param_list.push_back(item)) { - Item_param *item= new Item_param((uint) (lex->tok_start - - (uchar *) thd->query)); - if (!($$= item) || lex->param_list.push_back(item)) - { - send_error(thd, ER_OUT_OF_RESOURCES); - YYABORT; - } - } - else - { - yyerror(ER(ER_SYNTAX_ERROR)); + send_error(thd, ER_OUT_OF_RESOURCES); YYABORT; } } From 7646850173643e84a2b252d4a5a8764403de9fd3 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 15 Jul 2005 00:26:19 +0400 Subject: [PATCH 30/39] Hastily remove an occasionally checked in symlink :( From 60e7d6ff37b496ad9d3b69978b6d3eea8f2ccaf9 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 15 Jul 2005 00:41:58 +0400 Subject: [PATCH 31/39] Post-merge fixes. --- mysql-test/r/ps.result | 16 ++++++++++++++++ mysql-test/t/ps.test | 1 - sql/sql_lex.cc | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index c105a3e36a8..1896db84de0 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -778,3 +778,19 @@ lily river drop table t1; deallocate prepare stmt; +create table t1 (a int); +prepare stmt from "select ??"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 +prepare stmt from "select ?FROM t1"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?FROM t1' at line 1 +prepare stmt from "select FROM t1 WHERE?=1"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM t1 WHERE?=1' at line 1 +prepare stmt from "update t1 set a=a+?WHERE 1"; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?WHERE 1' at line 1 +select ?; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 +select ??; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '??' at line 1 +select ? from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t1' at line 1 +drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c86a69ab45f..f9b6d27bacc 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -822,4 +822,3 @@ select ??; --error 1064 select ? from t1; drop table t1; -deallocate prepare stmt; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a4293fa76bd..630a7e950f7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -562,7 +562,7 @@ int yylex(void *arg, void *yythd) its value in a query for the binlog, the query must stay grammatically correct. */ - else if (c == '?' && ((THD*) yythd)->command == COM_PREPARE && + else if (c == '?' && ((THD*) yythd)->command == COM_STMT_PREPARE && !ident_map[cs, yyPeek()]) return(PARAM_MARKER); return((int) c); From a4a5bc42a6886d6865d95e2bb84349da53991348 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 15 Jul 2005 02:11:07 +0400 Subject: [PATCH 32/39] Fix ps.test in --ps-protocol --- mysql-test/t/ps.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d08098606a1..beae95d462a 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -693,11 +693,13 @@ prepare stmt from "select ?FROM t1"; prepare stmt from "select FROM t1 WHERE?=1"; --error 1064 prepare stmt from "update t1 set a=a+?WHERE 1"; +--disable_ps_protocol --error 1064 select ?; --error 1064 select ??; --error 1064 select ? from t1; +--enable_ps_protocol drop table t1; # From fd884fdd0a19e42aa6a71bf2d0ce053a1948107d Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 15 Jul 2005 02:31:13 +0200 Subject: [PATCH 33/39] merge, adopted structured event interface to filter out "PING" events c.f. BUG#11898, ndb_mgmd does not release resources --- ndb/src/mgmapi/ndb_logevent.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp index 2817abcfdbb..4188929c952 100644 --- a/ndb/src/mgmapi/ndb_logevent.cpp +++ b/ndb/src/mgmapi/ndb_logevent.cpp @@ -369,6 +369,9 @@ int ndb_logevent_get_next(const NdbLogEventHandle h, Properties p; char buf[256]; + struct timeval start_time; + gettimeofday(&start_time, 0); + /* header */ while (1) { if (in.gets(buf,sizeof(buf)) == 0) @@ -383,7 +386,23 @@ int ndb_logevent_get_next(const NdbLogEventHandle h, } if ( strcmp("log event reply\n", buf) == 0 ) break; - ndbout_c("skipped: %s", buf); + + if ( strcmp("\n", buf) ) + ndbout_c("skipped: %s", buf); + + struct timeval now; + gettimeofday(&now, 0); + unsigned elapsed_ms= + (now.tv_sec-start_time.tv_sec)*1000 + + (now.tv_usec-start_time.tv_usec)/1000; + + if (elapsed_ms >= timeout_in_milliseconds) + { + // timed out + return 0; + } + + new (&in) SocketInputStream(h->socket, timeout_in_milliseconds-elapsed_ms); } /* read name-value pairs into properties object */ From 07d4f27195efc64cba7af16cf07e54ea545599d2 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Fri, 15 Jul 2005 11:17:57 +0500 Subject: [PATCH 34/39] Jim's fix for the #10443. Fix handling of floats and doubles when using prepared statements API in the embedded server. --- sql/sql_prepare.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9e2612c5661..89f930fa735 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -306,24 +306,28 @@ static void set_param_int64(Item_param *param, uchar **pos, ulong len) static void set_param_float(Item_param *param, uchar **pos, ulong len) { + float data; #ifndef EMBEDDED_LIBRARY if (len < 4) return; -#endif - float data; float4get(data,*pos); +#else + data= *(float*) *pos; +#endif param->set_double((double) data); *pos+= 4; } static void set_param_double(Item_param *param, uchar **pos, ulong len) { + double data; #ifndef EMBEDDED_LIBRARY if (len < 8) return; -#endif - double data; float8get(data,*pos); +#else + data= *(double*) *pos; +#endif param->set_double((double) data); *pos+= 8; } From 0d7a2641b5c05a2e90ca04bb1002be1c7d63ab69 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Fri, 15 Jul 2005 08:54:11 +0200 Subject: [PATCH 35/39] RPM spec file improvements: - create a "mysql" user group and assign the mysql user account to that group in the server postinstall section. (BUG 10984) - backported some changes from the 4.1 RPM spec file (cleanups: removed the incomplete Brazilian translations, more consequent use of macros) --- support-files/mysql.spec.sh | 65 +++++++++++++++---------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 2354b44f4fa..ade774fb4e3 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1,7 +1,9 @@ %define mysql_version @VERSION@ %define release 0 +%define license GPL %define mysqld_user mysql %define server_suffix -standard +%define mysqldatadir /var/lib/mysql # We don't package all files installed into the build root by intention - # See BUG#998 for details. @@ -12,11 +14,9 @@ Name: MySQL Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases -Summary(pt_BR): MySQL: Um servidor SQL rápido e confiável. -Group(pt_BR): Aplicações/Banco_de_Dados Version: @MYSQL_NO_DASH_VERSION@ Release: %{release} -License: GPL +License: %{license} Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz URL: http://www.mysql.com/ Packager: Lenz Grimmer @@ -50,11 +50,8 @@ news and information about the MySQL software. Also please see the documentation and the manual for more information. %package server -Release: %{release} Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases -Summary(pt_BR): MySQL: Um servidor SQL rápido e confiável. -Group(pt_BR): Aplicações/Banco_de_Dados Requires: fileutils sh-utils Provides: msqlormysql mysql-server mysql MySQL Obsoletes: MySQL mysql mysql-server @@ -85,11 +82,8 @@ If you want to access and work with the database, you have to install package "MySQL-client" as well! %package client -Release: %{release} Summary: MySQL - Client Group: Applications/Databases -Summary(pt_BR): MySQL - Cliente -Group(pt_BR): Aplicações/Banco_de_Dados Obsoletes: mysql-client Provides: mysql-client @@ -98,16 +92,11 @@ This package contains the standard MySQL clients and administration tools. %{see_base} -%description client -l pt_BR -Este pacote contém os clientes padrão para o MySQL. %package bench -Release: %{release} Requires: %{name}-client perl-DBI perl Summary: MySQL - Benchmarks and test system Group: Applications/Databases -Summary(pt_BR): MySQL - Medições de desempenho -Group(pt_BR): Aplicações/Banco_de_Dados Provides: mysql-bench Obsoletes: mysql-bench @@ -116,15 +105,9 @@ This package contains MySQL benchmark scripts and data. %{see_base} -%description bench -l pt_BR -Este pacote contém medições de desempenho de scripts e dados do MySQL. - %package devel -Release: %{release} Summary: MySQL - Development header files and libraries Group: Applications/Databases -Summary(pt_BR): MySQL - Medições de desempenho -Group(pt_BR): Aplicações/Banco_de_Dados Provides: mysql-devel Obsoletes: mysql-devel @@ -134,12 +117,7 @@ necessary to develop MySQL client applications. %{see_base} -%description devel -l pt_BR -Este pacote contém os arquivos de cabeçalho (header files) e bibliotecas -necessárias para desenvolver aplicações clientes do MySQL. - %package shared -Release: %{release} Summary: MySQL - Shared libraries Group: Applications/Databases @@ -148,12 +126,11 @@ This package contains the shared libraries (*.so*) which certain languages and applications need to dynamically load and use MySQL. %package Max -Release: %{release} Summary: MySQL - server with Berkeley BD, RAID and UDF support Group: Applications/Databases Provides: mysql-Max Obsoletes: mysql-Max -Requires: MySQL-server >= 4.0 +Requires: MySQL-server >= @MYSQL_BASE_VERSION@ %description Max Optional MySQL server binary that supports additional features like @@ -164,12 +141,9 @@ the standard MySQL package. Please note that this is a dynamically linked binary! %package embedded -Release: %{release} Requires: %{name}-devel Summary: MySQL - embedded library Group: Applications/Databases -Summary(pt_BR): MySQL - Medições de desempenho -Group(pt_BR): Aplicações/Banco_de_Dados Obsoletes: mysql-embedded %description embedded @@ -216,7 +190,7 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --libdir=%{_libdir} \ --sysconfdir=%{_sysconfdir} \ --datadir=%{_datadir} \ - --localstatedir=/var/lib/mysql \ + --localstatedir=%{mysqldatadir} \ --infodir=%{_infodir} \ --includedir=%{_includedir} \ --mandir=%{_mandir} \ @@ -325,7 +299,7 @@ MBD=$RPM_BUILD_DIR/mysql-%{mysql_version} # Ensure that needed directories exists install -d $RBR%{_sysconfdir}/{logrotate.d,init.d} -install -d $RBR/var/lib/mysql/mysql +install -d $RBR%{mysqldatadir}/mysql install -d $RBR%{_datadir}/{sql-bench,mysql-test} install -d $RBR%{_includedir} install -d $RBR%{_libdir} @@ -377,7 +351,7 @@ then fi %post server -mysql_datadir=/var/lib/mysql +mysql_datadir=%{mysqldatadir} # Create data directory if needed if test ! -d $mysql_datadir; then mkdir -m755 $mysql_datadir; fi @@ -395,19 +369,20 @@ then /sbin/chkconfig --add mysql fi -# Create a MySQL user. Do not report any problems if it already -# exists. This is redhat specific and should be handled more portable -useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" mysql 2> /dev/null || true +# Create a MySQL user and group. Do not report any problems if it already +# exists. +groupadd -r -c "MySQL server" %{mysqld_user} 2> /dev/null || true +useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" -g %{mysqld_user} %{mysqld_user} 2> /dev/null || true # Change permissions so that the user that will run the MySQL daemon # owns all database files. -chown -R mysql $mysql_datadir +chown -R %{mysqld_user}:%{mysqld_user} $mysql_datadir # Initiate databases -mysql_install_db -IN-RPM --user=mysql +%{_bindir}/mysql_install_db -IN-RPM --user=%{mysqld_user} # Change permissions again to fix any new files. -chown -R mysql $mysql_datadir +chown -R %{mysqld_user}:%{mysqld_user} $mysql_datadir # Fix permissions for the permission database so that only the user # can read them. @@ -587,6 +562,18 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Jul 15 2005 Lenz Grimmer + +- create a "mysql" user group and assign the mysql user account to that group + in the server postinstall section. (BUG 10984) + +* Wed Jun 01 2005 Lenz Grimmer + +- use "mysqldatadir" variable instead of hard-coding the path multiple times +- use the "mysqld_user" variable on all occasions a user name is referenced +- removed (incomplete) Brazilian translations +- removed redundant release tags from the subpackage descriptions + * Wed May 25 2005 Joerg Bruehe - Added a "make clean" between separate calls to "BuildMySQL". From da6d1504537795504f4159adb85fe3f9ce618c92 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 15 Jul 2005 10:44:54 +0200 Subject: [PATCH 36/39] BUG#11596 (partial fix), IP addresses not shown in ndb_mgm SHOW command on second ndb_mgmd (or on ndb_mgmd restart) --- .../transporter/TransporterRegistry.hpp | 2 ++ ndb/src/common/transporter/Transporter.cpp | 15 +++++++++++++++ ndb/src/common/transporter/Transporter.hpp | 1 + .../common/transporter/TransporterRegistry.cpp | 6 ++++++ ndb/src/mgmsrv/MgmtSrvr.cpp | 18 ++++++++++++++++++ ndb/src/mgmsrv/MgmtSrvr.hpp | 2 +- 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/ndb/include/transporter/TransporterRegistry.hpp b/ndb/include/transporter/TransporterRegistry.hpp index 8bd1de39ed5..410f3e1dc12 100644 --- a/ndb/include/transporter/TransporterRegistry.hpp +++ b/ndb/include/transporter/TransporterRegistry.hpp @@ -238,6 +238,8 @@ public: }; Vector m_transporter_interface; void add_transporter_interface(const char *interf, unsigned short port); + + struct in_addr get_connect_address(NodeId node_id) const; protected: private: diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp index b84f8f6fb5e..328ce2816de 100644 --- a/ndb/src/common/transporter/Transporter.cpp +++ b/ndb/src/common/transporter/Transporter.cpp @@ -74,6 +74,7 @@ Transporter::Transporter(TransporterRegistry &t_reg, m_connected = false; m_timeOutMillis = 1000; + m_connect_address.s_addr= 0; if (isServer) m_socket_client= 0; else @@ -98,6 +99,13 @@ Transporter::connect_server(NDB_SOCKET_TYPE sockfd) { DBUG_RETURN(true); // TODO assert(0); } + { + struct sockaddr addr; + SOCKET_SIZE_TYPE addrlen= sizeof(addr); + int r= getpeername(sockfd, &addr, &addrlen); + m_connect_address= ((struct sockaddr_in *)&addr)->sin_addr; + } + bool res = connect_server_impl(sockfd); if(res){ m_connected = true; @@ -164,6 +172,13 @@ Transporter::connect_client() { g_eventLogger.warning("Unable to verify transporter compatability with node %d", nodeId); } + { + struct sockaddr addr; + SOCKET_SIZE_TYPE addrlen= sizeof(addr); + int r= getpeername(sockfd, &addr, &addrlen); + m_connect_address= ((struct sockaddr_in *)&addr)->sin_addr; + } + bool res = connect_client_impl(sockfd); if(res){ m_connected = true; diff --git a/ndb/src/common/transporter/Transporter.hpp b/ndb/src/common/transporter/Transporter.hpp index c3b0d144eaf..5f3f8063723 100644 --- a/ndb/src/common/transporter/Transporter.hpp +++ b/ndb/src/common/transporter/Transporter.hpp @@ -122,6 +122,7 @@ protected: private: SocketClient *m_socket_client; + struct in_addr m_connect_address; protected: Uint32 getErrorCount(); diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp index ac6161b314e..0efad6d1a1d 100644 --- a/ndb/src/common/transporter/TransporterRegistry.cpp +++ b/ndb/src/common/transporter/TransporterRegistry.cpp @@ -51,6 +51,12 @@ extern int g_ndb_shm_signum; #include extern EventLogger g_eventLogger; +struct in_addr +TransporterRegistry::get_connect_address(NodeId node_id) const +{ + return theTransporters[node_id]->m_connect_address; +} + SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd) { DBUG_ENTER("SocketServer::Session * TransporterService::newSession"); diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index ceaedc9955b..f17d2a41be1 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -2124,6 +2124,24 @@ MgmtSrvr::getNodeType(NodeId nodeId) const return nodeTypes[nodeId]; } +const char *MgmtSrvr::get_connect_address(Uint32 node_id) +{ + if (m_connect_address[node_id].s_addr == 0 && + theFacade && theFacade->theTransporterRegistry && + theFacade->theClusterMgr && + getNodeType(node_id) == NDB_MGM_NODE_TYPE_NDB) + { + const ClusterMgr::Node &node= + theFacade->theClusterMgr->getNodeInfo(node_id); + if (node.connected) + { + m_connect_address[node_id]= + theFacade->theTransporterRegistry->get_connect_address(node_id); + } + } + return inet_ntoa(m_connect_address[node_id]); +} + void MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const { diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index ce78983b3c3..9ed5c2eb1d4 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -508,7 +508,7 @@ public: int setDbParameter(int node, int parameter, const char * value, BaseString&); - const char *get_connect_address(Uint32 node_id) { return inet_ntoa(m_connect_address[node_id]); } + const char *get_connect_address(Uint32 node_id); void get_connected_nodes(NodeBitmask &connected_nodes) const; SocketServer *get_socket_server() { return m_socket_server; } From c9e320019b7acec906f12d28abb9b27d9db11cdd Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 15 Jul 2005 12:35:26 +0200 Subject: [PATCH 37/39] Bug #11132, reverted bug-fix, it introduces another bug. Ndbd's may get the same nodeid In 4.1 the connection to the management server _must_ stay, that is how we ensure that the nodeids are reserved correctly --- ndb/src/common/mgmcommon/ConfigRetriever.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index 648f3b4a52c..b73bcea1bcc 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -131,16 +131,14 @@ ConfigRetriever::getConfig() { } ndb_mgm_configuration * -ConfigRetriever::getConfig(NdbMgmHandle m_handle){ - +ConfigRetriever::getConfig(NdbMgmHandle m_handle) +{ ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version); - if(conf == 0){ + if(conf == 0) + { setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); return 0; } - - ndb_mgm_disconnect(m_handle); - return conf; } From ca75369663b2b79624b530b25aa519162caffdeb Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 15 Jul 2005 12:40:20 +0200 Subject: [PATCH 38/39] BUG#11898 ndb_mgmd not releasing resources, added "ping" on add_listener + added close of some fd's + debug prints --- ndb/src/mgmclient/CommandInterpreter.cpp | 34 +++++++-- ndb/src/mgmsrv/MgmtSrvr.hpp | 1 + ndb/src/mgmsrv/Services.cpp | 93 +++++++++++++++++++----- 3 files changed, 105 insertions(+), 23 deletions(-) diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 34fe57d1fca..e1619917de5 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -455,11 +455,13 @@ static int do_event_thread; static void* event_thread_run(void* m) { + DBUG_ENTER("event_thread_run"); + NdbMgmHandle handle= *(NdbMgmHandle*)m; int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 }; int fd = ndb_mgm_listen_event(handle, filter); - if (fd > 0) + if (fd != NDB_INVALID_SOCKET) { do_event_thread= 1; char *tmp= 0; @@ -468,20 +470,26 @@ event_thread_run(void* m) do { if (tmp == 0) NdbSleep_MilliSleep(10); if((tmp = in.gets(buf, 1024))) - ndbout << tmp; + { + const char ping_token[]= ""; + if (memcmp(ping_token,tmp,sizeof(ping_token)-1)) + ndbout << tmp; + } } while(do_event_thread); + NDB_CLOSE_SOCKET(fd); } else { do_event_thread= -1; } - return NULL; + DBUG_RETURN(NULL); } bool CommandInterpreter::connect() { + DBUG_ENTER("CommandInterpreter::connect"); if(!m_connected) { if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) @@ -512,8 +520,19 @@ CommandInterpreter::connect() do_event_thread == 0 || do_event_thread == -1) { - printf("Warning, event thread startup failed, degraded printouts as result\n"); + DBUG_PRINT("info",("Warning, event thread startup failed, " + "degraded printouts as result, errno=%d", + errno)); + printf("Warning, event thread startup failed, " + "degraded printouts as result, errno=%d\n", errno); do_event_thread= 0; + if (m_event_thread) + { + void *res; + NdbThread_WaitFor(m_event_thread, &res); + NdbThread_Destroy(&m_event_thread); + } + ndb_mgm_disconnect(m_mgmsrv2); } } else @@ -521,6 +540,8 @@ CommandInterpreter::connect() printf("Warning, event connect failed, degraded printouts as result\n"); } m_connected= true; + DBUG_PRINT("info",("Connected to Management Server at: %s:%d", + host,port)); if (m_verbose) { printf("Connected to Management Server at: %s:%d\n", @@ -528,12 +549,13 @@ CommandInterpreter::connect() } } } - return m_connected; + DBUG_RETURN(m_connected); } bool CommandInterpreter::disconnect() { + DBUG_ENTER("CommandInterpreter::disconnect"); if (m_event_thread) { void *res; do_event_thread= 0; @@ -550,7 +572,7 @@ CommandInterpreter::disconnect() } m_connected= false; } - return true; + DBUG_RETURN(true); } //***************************************************************************** diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index 9ed5c2eb1d4..2b87bb9416a 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -60,6 +60,7 @@ public: } void add_listener(const Event_listener&); + void check_listeners(); void update_max_log_level(const LogLevel&); void update_log_level(const LogLevel&); diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 8ba8c2fe87e..00cf6390c73 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -253,15 +253,19 @@ ParserRow commands[] = { }; MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock) - : SocketServer::Session(sock), m_mgmsrv(mgm) { + : SocketServer::Session(sock), m_mgmsrv(mgm) +{ + DBUG_ENTER("MgmApiSession::MgmApiSession"); m_input = new SocketInputStream(sock); m_output = new SocketOutputStream(sock); m_parser = new Parser_t(commands, *m_input, true, true, true); m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); + DBUG_VOID_RETURN; } MgmApiSession::~MgmApiSession() { + DBUG_ENTER("MgmApiSession::~MgmApiSession"); if (m_input) delete m_input; if (m_output) @@ -270,10 +274,19 @@ MgmApiSession::~MgmApiSession() delete m_parser; if (m_allocated_resources) delete m_allocated_resources; + if(m_socket != NDB_INVALID_SOCKET) + { + NDB_CLOSE_SOCKET(m_socket); + m_socket= NDB_INVALID_SOCKET; + } + DBUG_VOID_RETURN; } void -MgmApiSession::runSession() { +MgmApiSession::runSession() +{ + DBUG_ENTER("MgmApiSession::runSession"); + Parser_t::Context ctx; while(!m_stop) { m_parser->run(ctx, *this); @@ -301,8 +314,13 @@ MgmApiSession::runSession() { break; } } - if(m_socket >= 0) + if(m_socket != NDB_INVALID_SOCKET) + { NDB_CLOSE_SOCKET(m_socket); + m_socket= NDB_INVALID_SOCKET; + } + + DBUG_VOID_RETURN; } #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT @@ -1236,7 +1254,7 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) Uint32 threshold; LogLevel::EventCategory cat; Logger::LoggerLevel severity; - int i; + int i, n; DBUG_ENTER("Ndb_mgmd_event_service::log"); DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId)); @@ -1248,28 +1266,30 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) Vector copy; m_clients.lock(); - for(i = m_clients.size() - 1; i >= 0; i--){ - if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)){ - if(m_clients[i].m_socket != NDB_INVALID_SOCKET && - println_socket(m_clients[i].m_socket, - MAX_WRITE_TIMEOUT, m_text) == -1){ - copy.push_back(m_clients[i].m_socket); + for(i = m_clients.size() - 1; i >= 0; i--) + { + if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)) + { + int fd= m_clients[i].m_socket; + if(fd != NDB_INVALID_SOCKET && + println_socket(fd, MAX_WRITE_TIMEOUT, m_text) == -1) + { + copy.push_back(fd); m_clients.erase(i, false); } } } m_clients.unlock(); - for(i = 0; (unsigned)i < copy.size(); i++){ - NDB_CLOSE_SOCKET(copy[i]); - } + if ((n= (int)copy.size())) + { + for(i= 0; i < n; i++) + NDB_CLOSE_SOCKET(copy[i]); - if(copy.size()){ LogLevel tmp; tmp.clear(); m_clients.lock(); - for(i = 0; (unsigned)i < m_clients.size(); i++){ + for(i= m_clients.size() - 1; i >= 0; i--) tmp.set_max(m_clients[i].m_logLevel); - } m_clients.unlock(); update_log_level(tmp); } @@ -1297,9 +1317,48 @@ Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp) } void -Ndb_mgmd_event_service::add_listener(const Event_listener& client){ +Ndb_mgmd_event_service::check_listeners() +{ + int i, n= 0; + DBUG_ENTER("Ndb_mgmd_event_service::check_listeners"); + m_clients.lock(); + for(i= m_clients.size() - 1; i >= 0; i--) + { + int fd= m_clients[i].m_socket; + DBUG_PRINT("info",("%d %d",i,fd)); + char buf[1]; + buf[0]=0; + if (fd != NDB_INVALID_SOCKET && + println_socket(fd,MAX_WRITE_TIMEOUT,"") == -1) + { + NDB_CLOSE_SOCKET(fd); + m_clients.erase(i, false); + n=1; + } + } + if (n) + { + LogLevel tmp; tmp.clear(); + for(i= m_clients.size() - 1; i >= 0; i--) + tmp.set_max(m_clients[i].m_logLevel); + update_log_level(tmp); + } + m_clients.unlock(); + DBUG_VOID_RETURN; +} + +void +Ndb_mgmd_event_service::add_listener(const Event_listener& client) +{ + DBUG_ENTER("Ndb_mgmd_event_service::add_listener"); + DBUG_PRINT("enter",("client.m_socket: %d", client.m_socket)); + + check_listeners(); + m_clients.push_back(client); update_max_log_level(client.m_logLevel); + + DBUG_VOID_RETURN; } void From f97c11fe03c2c591d324bfb8f7dca86f222eaef6 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 15 Jul 2005 13:57:21 +0200 Subject: [PATCH 39/39] minor type fixes to prev patch --- ndb/src/mgmapi/ndb_logevent.cpp | 5 ++--- ndb/src/mgmsrv/Services.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp index 4188929c952..27e7c1f36f5 100644 --- a/ndb/src/mgmapi/ndb_logevent.cpp +++ b/ndb/src/mgmapi/ndb_logevent.cpp @@ -392,9 +392,8 @@ int ndb_logevent_get_next(const NdbLogEventHandle h, struct timeval now; gettimeofday(&now, 0); - unsigned elapsed_ms= - (now.tv_sec-start_time.tv_sec)*1000 + - (now.tv_usec-start_time.tv_usec)/1000; + unsigned elapsed_ms= (now.tv_sec-start_time.tv_sec)*1000 + + ((signed int)now.tv_usec-(signed int)start_time.tv_usec)/1000; if (elapsed_ms >= timeout_in_milliseconds) { diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index a541be0f24a..270d7f716dd 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -1308,7 +1308,7 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) { if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)) { - int fd= m_clients[i].m_socket; + NDB_SOCKET_TYPE fd= m_clients[i].m_socket; if(fd != NDB_INVALID_SOCKET) { int r;