From ba82a6a759643d287810f814ad2f7b7f54c71e5f Mon Sep 17 00:00:00 2001 From: "hf@deer.(none)" <> Date: Sat, 15 Oct 2005 19:47:23 +0500 Subject: [PATCH 01/28] Fix for bug #9855 (Inconsistend column type in create select) --- mysql-test/r/func_gconcat.result | 6 +++--- mysql-test/r/subselect.result | 6 +++--- mysql-test/r/type_float.result | 22 ++++++++++++++++++++++ mysql-test/t/type_float.test | 17 +++++++++++++++++ sql/item_func.cc | 9 +++++++++ 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d7a741827d5..200b4a4d53b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -131,9 +131,9 @@ grp group_concat(a separator "")+0 3 456789 select grp, group_concat(a separator "")+0.0 from t1 group by grp; grp group_concat(a separator "")+0.0 -1 1.0 -2 23.0 -3 456789.0 +1 1 +2 23 +3 456789 select grp, ROUND(group_concat(a separator "")) from t1 group by grp; grp ROUND(group_concat(a separator "")) 1 1 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 4c795abe986..500aa4b1728 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -213,9 +213,9 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from a select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) -8 7.5000 -8 4.5000 -9 7.5000 +8 7.5 +8 4.5 +9 7.5 explain extended select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t4 ALL NULL NULL NULL NULL 3 diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 6e381192270..e8daeb08526 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -250,3 +250,25 @@ t3 CREATE TABLE `t3` ( `d` double(22,9) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2, t3; +create table t1 select 105213674794682365.00 + 0.0 x; +show warnings; +Level Code Message +desc t1; +Field Type Null Key Default Extra +x double 0 +drop table t1; +create table t1 select 0.0 x; +desc t1; +Field Type Null Key Default Extra +x double(3,1) 0.0 +create table t2 select 105213674794682365.00 y; +desc t2; +Field Type Null Key Default Extra +y double(21,2) 0.00 +create table t3 select x+y a from t1,t2; +show warnings; +Level Code Message +desc t3; +Field Type Null Key Default Extra +a double 0 +drop table t1,t2,t3; diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index abaf72ea2ed..75723d2a0ff 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -162,4 +162,21 @@ show create table t3; drop table t1, t2, t3; +# +# Bug #9855 (inconsistent column type for create select +# +create table t1 select 105213674794682365.00 + 0.0 x; +show warnings; +desc t1; +drop table t1; + +create table t1 select 0.0 x; +desc t1; +create table t2 select 105213674794682365.00 y; +desc t2; +create table t3 select x+y a from t1,t2; +show warnings; +desc t3; +drop table t1,t2,t3; + # End of 4.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 288859443ff..019147e151f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -359,10 +359,19 @@ String *Item_num_func::val_str(String *str) void Item_func::fix_num_length_and_dec() { + uint fl_length= 0; decimals=0; for (uint i=0 ; i < arg_count ; i++) + { set_if_bigger(decimals,args[i]->decimals); + set_if_bigger(fl_length, args[i]->max_length); + } max_length=float_length(decimals); + if (fl_length > max_length) + { + decimals= NOT_FIXED_DEC; + max_length= float_length(NOT_FIXED_DEC); + } } Item *Item_func::get_tmp_table_item(THD *thd) From 1fcecea7a372f451c51c22cc355cbf8cd09ace6b Mon Sep 17 00:00:00 2001 From: "holyfoot@deer.(none)" <> Date: Sat, 10 Dec 2005 18:20:00 +0400 Subject: [PATCH 02/28] Fix for bug #14320 (MBROverlaps does wrong test) --- sql/spatial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/spatial.h b/sql/spatial.h index ec5e80e00fd..206958b3eaf 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -142,7 +142,7 @@ struct MBR bool inner_point(double x, double y) const { /* The following should be safe, even if we compare doubles */ - return (xminx) && (yminx); + return (xminx) && (yminy); } int overlaps(const MBR *mbr) From cdfe77e2ec41078f58c4dff22f7c686b61fa23a6 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Thu, 15 Dec 2005 15:23:16 +0100 Subject: [PATCH 03/28] Fixed BUG#14834: Server denies to execute Stored Procedure The problem was that databases with '_' in the name did not match a correct ACL with a literal '_' (i.e. '\_') in the db name, only identical strings matched. The fix makes this work, and also ACLs with wildcards in the db name work. --- mysql-test/r/sp-security.result | 21 ++++++++++++++++ mysql-test/t/sp-security.test | 44 +++++++++++++++++++++++++++++++++ sql/sql_acl.cc | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 614e670f25d..fbc6d64f9c9 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -263,3 +263,24 @@ CREATE VIEW v1 AS SELECT test.bug12812()| ERROR 42000: execute command denied to user 'user_bug12812'@'localhost' for routine 'test.bug12812' DROP USER user_bug12812@localhost| drop function bug12812| +create database db_bug14834; +create user user1_bug14834@localhost identified by ''; +grant all on `db\_bug14834`.* to user1_bug14834@localhost; +create user user2_bug14834@localhost identified by ''; +grant all on `db\_bug14834`.* to user2_bug14834@localhost; +create user user3_bug14834@localhost identified by ''; +grant all on `db__ug14834`.* to user3_bug14834@localhost; +create procedure p_bug14834() select user(), current_user(); +call p_bug14834(); +user() current_user() +user1_bug14834@localhost user1_bug14834@localhost +call p_bug14834(); +user() current_user() +user2_bug14834@localhost user1_bug14834@localhost +call p_bug14834(); +user() current_user() +user3_bug14834@localhost user1_bug14834@localhost +drop user user1_bug14834@localhost; +drop user user2_bug14834@localhost; +drop user user3_bug14834@localhost; +drop database db_bug14834; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 8d4f99abd71..0b24881a056 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -437,4 +437,48 @@ disconnect test_user_12812| DROP USER user_bug12812@localhost| drop function bug12812| delimiter ;| + + +# +# BUG#14834: Server denies to execute Stored Procedure +# +# The problem here was with '_' in the database name. +# +create database db_bug14834; + +create user user1_bug14834@localhost identified by ''; +# The exact name of the database (no wildcard) +grant all on `db\_bug14834`.* to user1_bug14834@localhost; + +create user user2_bug14834@localhost identified by ''; +# The exact name of the database (no wildcard) +grant all on `db\_bug14834`.* to user2_bug14834@localhost; + +create user user3_bug14834@localhost identified by ''; +# Wildcards in the database name +grant all on `db__ug14834`.* to user3_bug14834@localhost; + +connect (user1_bug14834,localhost,user1_bug14834,,db_bug14834); +# Create the procedure and check that we can call it +create procedure p_bug14834() select user(), current_user(); +call p_bug14834(); + +connect (user2_bug14834,localhost,user2_bug14834,,db_bug14834); +# This didn't work before +call p_bug14834(); + +connect (user3_bug14834,localhost,user3_bug14834,,db_bug14834); +# Should also work +call p_bug14834(); + +# Cleanup +connection default; +disconnect user1_bug14834; +disconnect user2_bug14834; +disconnect user3_bug14834; +drop user user1_bug14834@localhost; +drop user user2_bug14834@localhost; +drop user user3_bug14834@localhost; +drop database db_bug14834; + # End of 5.0 bugs. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index cd83efcac2c..dadb4b75d7c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -987,7 +987,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, { if (compare_hostname(&acl_db->host, host, ip)) { - if (!acl_db->db || (db && !strcmp(acl_db->db, db))) + if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0))) { sctx->db_access= acl_db->access; break; From 6a8f762ecd257370668d156a58417ef750e5ac7b Mon Sep 17 00:00:00 2001 From: "holyfoot@deer.(none)" <> Date: Mon, 19 Dec 2005 14:21:42 +0400 Subject: [PATCH 04/28] bug #15429 (Test 'func_math' not prepared for 'classic' build) --- mysql-test/t/func_math.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index a8f62e38e86..c22c09ab62b 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -91,7 +91,9 @@ drop table t1; # # InnoDB is required to reproduce the fault, but it is okay if we default to # MyISAM when testing. +--disable_warnings create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8; +--enable_warnings insert into t1 values ('http://www.foo.com/', now()); select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0)); drop table t1; From 0cc1acd51c35ec44a874ffa53f1df77d01e669b9 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Wed, 11 Jan 2006 15:11:05 +0100 Subject: [PATCH 05/28] Fixing BUG#15658: Server crashes after creating function as empty string Empty strings (and names with trailing spaces) should not be allowed. --- mysql-test/r/sp-error.result | 19 +++++++++++++++++++ mysql-test/t/sp-error.test | 27 +++++++++++++++++++++++++++ sql/share/errmsg.txt | 2 ++ sql/sp_head.cc | 17 +++++++++++++++++ sql/sp_head.h | 2 ++ sql/sql_yacc.yy | 15 +++++++++++++++ 6 files changed, 82 insertions(+) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index d7bed7e88a7..a784b59a6e5 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1128,3 +1128,22 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function drop function bug11555_1; drop table t1; drop view v1; +drop procedure if exists ` bug15658`; +create procedure ``() select 1; +ERROR 42000: Incorrect routine name '' +create procedure ` `() select 1; +ERROR 42000: Incorrect routine name ' ' +create procedure `bug15658 `() select 1; +ERROR 42000: Incorrect routine name 'bug15658 ' +create procedure ``.bug15658() select 1; +ERROR 42000: Incorrect database name '' +create procedure `x `.bug15658() select 1; +ERROR 42000: Incorrect database name 'x ' +create procedure ` bug15658`() select 1; +call ` bug15658`(); +1 +1 +show procedure status; +Db Name Type Definer Modified Created Security_type Comment +test bug15658 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +drop procedure ` bug15658`; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index cf8f8dfc79c..25944144d21 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1556,6 +1556,7 @@ drop procedure bug13012_1| drop function bug13012_2| delimiter ;| +# # BUG#11555 "Stored procedures: current SP tables locking make # impossible view security". We should not expose names of tables # which are implicitly used by view (via stored routines/triggers). @@ -1616,7 +1617,33 @@ drop function bug11555_1; drop table t1; drop view v1; +# +# BUG#15658: Server crashes after creating function as empty string +# +--disable_warnings +drop procedure if exists ` bug15658`; +--enable_warnings +--error ER_SP_WRONG_NAME +create procedure ``() select 1; +--error ER_SP_WRONG_NAME +create procedure ` `() select 1; +--error ER_SP_WRONG_NAME +create procedure `bug15658 `() select 1; +--error ER_WRONG_DB_NAME +create procedure ``.bug15658() select 1; +--error ER_WRONG_DB_NAME +create procedure `x `.bug15658() select 1; + +# This should work +create procedure ` bug15658`() select 1; +call ` bug15658`(); +--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' +show procedure status; +drop procedure ` bug15658`; + + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 185b4326c5c..63c75cdaddc 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5605,3 +5605,5 @@ ER_SP_RECURSION_LIMIT ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.64s überschritten" ER_SP_PROC_TABLE_CORRUPT eng "Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)" +ER_SP_WRONG_NAME 42000 + eng "Incorrect routine name '%-.64s'" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 12f9260e7b1..bf1de53acd6 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -384,6 +384,23 @@ sp_name_current_db_new(THD *thd, LEX_STRING name) return qname; } +/* + * Check that the name 'ident' is ok. It's assumed to be an 'ident' + * from the parser, so we only have to check length and trailing spaces. + * The former is a standard requirement (and 'show status' assumes a + * non-empty name), the latter is a mysql:ism as trailing spaces are + * removed by get_field(). + * + * RETURN + * TRUE - bad name + * FALSE - name is ok + */ + +bool +sp_name_check(LEX_STRING ident) +{ + return (!ident.str || !ident.str[0] || ident.str[ident.length-1] == ' '); +} /* ------------------------------------------------------------------ */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 2eebd35f6dc..30859ee8f8a 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -102,6 +102,8 @@ public: sp_name * sp_name_current_db_new(THD *thd, LEX_STRING name); +bool +sp_name_check(LEX_STRING name); class sp_head :private Query_arena { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 25e10362ece..281e3e2eb5b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1288,11 +1288,26 @@ clear_privileges: sp_name: ident '.' ident { + if (!$1.str || check_db_name($1.str)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); + YYABORT; + } + if (sp_name_check($3)) + { + my_error(ER_SP_WRONG_NAME, MYF(0), $3.str); + YYABORT; + } $$= new sp_name($1, $3); $$->init_qname(YYTHD); } | ident { + if (sp_name_check($1)) + { + my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); + YYABORT; + } $$= sp_name_current_db_new(YYTHD, $1); } ; From df7097f203fc2147c3aca979fa9e7d453441f5af Mon Sep 17 00:00:00 2001 From: "SergeyV@selena." <> Date: Thu, 12 Jan 2006 17:32:39 +0300 Subject: [PATCH 06/28] Fixes bug #15787. Fix makes available _FILE_OFFSET_BITS definition for zlib library in order to enable support of files larger than 2Gb. Providing an effective test is hardly possible, since the problem starts only when archive table becomes larger than 2Gb. --- zlib/gzio.c | 4 ++-- zlib/zconf.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/zlib/gzio.c b/zlib/gzio.c index 7e90f4928fc..afac5352323 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -7,10 +7,10 @@ /* @(#) $Id$ */ -#include - #include "zutil.h" +#include + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif diff --git a/zlib/zconf.h b/zlib/zconf.h index 03a9431c8be..f786a20a6f9 100644 --- a/zlib/zconf.h +++ b/zlib/zconf.h @@ -8,6 +8,10 @@ #ifndef ZCONF_H #define ZCONF_H +#ifdef HAVE_CONFIG_H +#include +#endif + /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. From e5e61eb15b96d1edb72016b9f45cf200ffd831c3 Mon Sep 17 00:00:00 2001 From: "stewart@mysql.com" <> Date: Fri, 13 Jan 2006 11:43:50 +1100 Subject: [PATCH 07/28] BUG#11331 "Warning: could not add log destination" message does not provide enough info Implement error reporting to Logger and associated classes. --- ndb/include/logger/LogHandler.hpp | 13 +++++++++++ ndb/include/logger/Logger.hpp | 5 +++- ndb/src/common/logger/FileLogHandler.cpp | 17 ++++++++++---- ndb/src/common/logger/LogHandler.cpp | 29 +++++++++++++++++++++--- ndb/src/common/logger/Logger.cpp | 11 ++++++++- ndb/src/common/logger/SysLogHandler.cpp | 1 + ndb/src/mgmsrv/MgmtSrvr.cpp | 14 ++++++++++-- 7 files changed, 79 insertions(+), 11 deletions(-) diff --git a/ndb/include/logger/LogHandler.hpp b/ndb/include/logger/LogHandler.hpp index 7df6ad864e5..8b9aa43d7a9 100644 --- a/ndb/include/logger/LogHandler.hpp +++ b/ndb/include/logger/LogHandler.hpp @@ -125,6 +125,18 @@ public: */ void setErrorCode(int code); + /** + * Returns the error string. + */ + char* getErrorStr(); + + /** + * Sets the error string. + * + * @param str the error string. + */ + void setErrorStr(char* str); + /** * Parse logstring parameters * @@ -195,6 +207,7 @@ private: const char* m_pDateTimeFormat; int m_errorCode; + char* m_errorStr; // for handling repeated messages unsigned m_count_repeated_messages; diff --git a/ndb/include/logger/Logger.hpp b/ndb/include/logger/Logger.hpp index ee762098fb6..3414468d42d 100644 --- a/ndb/include/logger/Logger.hpp +++ b/ndb/include/logger/Logger.hpp @@ -178,8 +178,11 @@ public: * Add a new handler * * @param logstring string describing the handler to add + * @param err OS errno in event of error + * @param len max length of errStr buffer + * @param errStr logger error string in event of error */ - bool addHandler(const BaseString &logstring); + bool addHandler(const BaseString &logstring, int *err, int len, char* errStr); /** * Remove a log handler. diff --git a/ndb/src/common/logger/FileLogHandler.cpp b/ndb/src/common/logger/FileLogHandler.cpp index 8678b999b6f..3d29e63ac1f 100644 --- a/ndb/src/common/logger/FileLogHandler.cpp +++ b/ndb/src/common/logger/FileLogHandler.cpp @@ -187,6 +187,7 @@ FileLogHandler::setParam(const BaseString ¶m, const BaseString &value){ return setMaxSize(value); if(param == "maxfiles") return setMaxFiles(value); + setErrorStr("Invalid parameter"); return false; } @@ -196,16 +197,18 @@ FileLogHandler::setFilename(const BaseString &filename) { if(m_pLogFile) delete m_pLogFile; m_pLogFile = new File_class(filename.c_str(), "a+"); - open(); - return true; + return open(); } bool FileLogHandler::setMaxSize(const BaseString &size) { char *end; long val = strtol(size.c_str(), &end, 0); /* XXX */ - if(size.c_str() == end) + if(size.c_str() == end || val < 0) + { + setErrorStr("Invalid file size"); return false; + } if(end[0] == 'M') val *= 1024*1024; if(end[0] == 'k') @@ -220,8 +223,11 @@ bool FileLogHandler::setMaxFiles(const BaseString &files) { char *end; long val = strtol(files.c_str(), &end, 0); - if(files.c_str() == end) + if(files.c_str() == end || val < 1) + { + setErrorStr("Invalid maximum number of files"); return false; + } m_maxNoFiles = val; return true; @@ -230,6 +236,9 @@ FileLogHandler::setMaxFiles(const BaseString &files) { bool FileLogHandler::checkParams() { if(m_pLogFile == NULL) + { + setErrorStr("Log file cannot be null."); return false; + } return true; } diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp index 521bd346fd3..c11f962d4fb 100644 --- a/ndb/src/common/logger/LogHandler.cpp +++ b/ndb/src/common/logger/LogHandler.cpp @@ -23,7 +23,8 @@ // LogHandler::LogHandler() : m_pDateTimeFormat("%d-%.2d-%.2d %.2d:%.2d:%.2d"), - m_errorCode(0) + m_errorCode(0), + m_errorStr(NULL) { m_max_repeat_frequency= 3; // repeat messages maximum every 3 seconds m_count_repeated_messages= 0; @@ -155,6 +156,19 @@ LogHandler::setErrorCode(int code) m_errorCode = code; } + +char* +LogHandler::getErrorStr() +{ + return m_errorStr; +} + +void +LogHandler::setErrorStr(char* str) +{ + m_errorStr= str; +} + bool LogHandler::parseParams(const BaseString &_params) { Vector v_args; @@ -165,9 +179,18 @@ LogHandler::parseParams(const BaseString &_params) { for(size_t i=0; i < v_args.size(); i++) { Vector v_param_value; if(v_args[i].split(v_param_value, "=", 2) != 2) + { ret = false; - else if (!setParam(v_param_value[0], v_param_value[1])) - ret = false; + setErrorStr("Can't find key=value pair."); + } + else + { + v_param_value[0].trim(" \t"); + if (!setParam(v_param_value[0], v_param_value[1])) + { + ret = false; + } + } } if(!checkParams()) diff --git a/ndb/src/common/logger/Logger.cpp b/ndb/src/common/logger/Logger.cpp index 4a48236053d..48e084a782b 100644 --- a/ndb/src/common/logger/Logger.cpp +++ b/ndb/src/common/logger/Logger.cpp @@ -167,7 +167,7 @@ Logger::addHandler(LogHandler* pHandler) } bool -Logger::addHandler(const BaseString &logstring) { +Logger::addHandler(const BaseString &logstring, int *err, int len, char* errStr) { size_t i; Vector logdest; Vectorloghandlers; @@ -200,9 +200,18 @@ Logger::addHandler(const BaseString &logstring) { handler = new ConsoleLogHandler(); if(handler == NULL) + { + snprintf(errStr,len,"Could not create log destination: %s", + logdest[i].c_str()); DBUG_RETURN(false); + } if(!handler->parseParams(params)) + { + *err= handler->getErrorCode(); + if(handler->getErrorStr()) + strncpy(errStr, handler->getErrorStr(), len); DBUG_RETURN(false); + } loghandlers.push_back(handler); } diff --git a/ndb/src/common/logger/SysLogHandler.cpp b/ndb/src/common/logger/SysLogHandler.cpp index 5b1b8d85ca7..c7fcb102dd4 100644 --- a/ndb/src/common/logger/SysLogHandler.cpp +++ b/ndb/src/common/logger/SysLogHandler.cpp @@ -154,5 +154,6 @@ SysLogHandler::setFacility(const BaseString &facility) { return true; } } + setErrorStr("Invalid syslog facility name"); return false; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 3ee0dc6e750..47d156c1f9e 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -179,6 +179,8 @@ MgmtSrvr::startEventLog() } const char * tmp; + char errStr[100]; + int err= 0; BaseString logdest; char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId); NdbAutoPtr tmp_aptr(clusterLog); @@ -192,9 +194,17 @@ MgmtSrvr::startEventLog() logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", clusterLog); } - if(!g_eventLogger.addHandler(logdest)) { + errStr[0]='\0'; + if(!g_eventLogger.addHandler(logdest, &err, sizeof(errStr), errStr)) { ndbout << "Warning: could not add log destination \"" - << logdest.c_str() << "\"" << endl; + << logdest.c_str() << "\". Reason: "; + if(err) + ndbout << strerror(err); + if(err && errStr[0]!='\0') + ndbout << ", "; + if(errStr[0]!='\0') + ndbout << errStr; + ndbout << endl; } } From 5cf0ede080ce8b42ff22a0ffe7d6c71efcdec915 Mon Sep 17 00:00:00 2001 From: "stewart@mysql.com" <> Date: Tue, 17 Jan 2006 00:13:18 +1100 Subject: [PATCH 08/28] BUG#12124 ndb_mgm -e "# stop" does not allow stopping ndb_mgmd processes on other systems WL#2703 restart for ndb_mgmd Solving two problems with one stone. Allows the stopping and restarting of mgm nodes other than the one the mgmclient is connected to. --- ndb/include/mgmapi/mgmapi.h | 16 +++ ndb/include/mgmcommon/ConfigRetriever.hpp | 3 + ndb/src/common/mgmcommon/ConfigRetriever.cpp | 3 + ndb/src/common/util/SocketServer.cpp | 2 + ndb/src/kernel/main.cpp | 5 +- ndb/src/kernel/vm/Configuration.cpp | 3 +- ndb/src/kernel/vm/Configuration.hpp | 2 +- ndb/src/mgmapi/mgmapi.cpp | 19 +++ ndb/src/mgmclient/CommandInterpreter.cpp | 23 ++- ndb/src/mgmsrv/MgmtSrvr.cpp | 141 +++++++++++++++++-- ndb/src/mgmsrv/MgmtSrvr.hpp | 11 +- ndb/src/mgmsrv/Services.cpp | 15 +- ndb/src/mgmsrv/Services.hpp | 1 + ndb/src/mgmsrv/main.cpp | 55 +++----- 14 files changed, 239 insertions(+), 60 deletions(-) diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h index 36dee7193c7..6e2d53abcf3 100644 --- a/ndb/include/mgmapi/mgmapi.h +++ b/ndb/include/mgmapi/mgmapi.h @@ -993,6 +993,22 @@ extern "C" { int ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned version, int nodetype); + /** + * End Session + * + * This function tells the mgm server to free all resources associated with + * this connection. It will also close it. + * + * This differs from just disconnecting as we now synchronously clean up, + * so that a quickly restarting server that needs the same node id can + * get it when it restarts. + * + * @param handle NDB management handle + * @return 0 on success + * + * @note you still have to destroy the NdbMgmHandle. + */ + int ndb_mgm_end_session(NdbMgmHandle handle); /** * Get the node id of the mgm server we're connected to diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp index c0b877af07d..1b4ecd56f80 100644 --- a/ndb/include/mgmcommon/ConfigRetriever.hpp +++ b/ndb/include/mgmcommon/ConfigRetriever.hpp @@ -78,6 +78,7 @@ public: const char *get_connectstring(char *buf, int buf_sz) const; NdbMgmHandle get_mgmHandle() { return m_handle; }; NdbMgmHandle* get_mgmHandlePtr() { return &m_handle; }; + void end_session(bool end) { m_end_session= end; }; Uint32 get_configuration_nodeid() const; private: @@ -92,6 +93,8 @@ private: void setError(ErrorType, const char * errorMsg); Uint32 _ownNodeId; + bool m_end_session; + /* Uint32 m_mgmd_port; const char *m_mgmd_host; diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index a44550da48b..fb3531d81f6 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -52,6 +52,7 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string, m_version = version; m_node_type = node_type; _ownNodeId= 0; + m_end_session= true; m_handle= ndb_mgm_create_handle(); @@ -73,6 +74,8 @@ ConfigRetriever::~ConfigRetriever() { DBUG_ENTER("ConfigRetriever::~ConfigRetriever"); if (m_handle) { + if(m_end_session) + ndb_mgm_end_session(m_handle); ndb_mgm_disconnect(m_handle); ndb_mgm_destroy_handle(&m_handle); } diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp index 15dca2d96b1..481c656b78b 100644 --- a/ndb/src/common/util/SocketServer.cpp +++ b/ndb/src/common/util/SocketServer.cpp @@ -42,6 +42,8 @@ SocketServer::~SocketServer() { delete m_sessions[i].m_session; } for(i = 0; icloseConfiguration(); + theConfig->closeConfiguration(false); int status = 0, error_exit = 0, signum = 0; while(waitpid(child, &status, 0) != child); diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp index 46e237d1fe6..0fca1841a15 100644 --- a/ndb/src/kernel/vm/Configuration.cpp +++ b/ndb/src/kernel/vm/Configuration.cpp @@ -172,7 +172,8 @@ Configuration::~Configuration(){ } void -Configuration::closeConfiguration(){ +Configuration::closeConfiguration(bool end_session){ + m_config_retriever->end_session(end_session); if (m_config_retriever) { delete m_config_retriever; } diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp index 5043d1f0bee..243ecbee4e7 100644 --- a/ndb/src/kernel/vm/Configuration.hpp +++ b/ndb/src/kernel/vm/Configuration.hpp @@ -35,7 +35,7 @@ public: void fetch_configuration(); void setupConfiguration(); - void closeConfiguration(); + void closeConfiguration(bool end_session= true); bool lockPagesInMainMemory() const; diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index a69a61dcda7..c1fb4c3e87f 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -2321,4 +2321,23 @@ int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length) DBUG_RETURN(0); } +extern "C" +int ndb_mgm_end_session(NdbMgmHandle handle) +{ + DBUG_ENTER("ndb_mgm_end_session"); + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + SocketOutputStream s_output(handle->socket); + s_output.println("end session"); + s_output.println(""); + + SocketInputStream in(handle->socket, handle->read_timeout); + char buf[32]; + + in.gets(buf, sizeof(buf)); + + DBUG_RETURN(0); +} + template class Vector*>; diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 0b1b2e3a087..74d7f879f9c 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -1000,26 +1000,21 @@ CommandInterpreter::executeShutdown(char* parameters) int result = 0; result = ndb_mgm_stop(m_mgmsrv, 0, 0); if (result < 0) { - ndbout << "Shutdown off NDB Cluster storage node(s) failed." << endl; + ndbout << "Shutdown of NDB Cluster node(s) failed." << endl; printError(); return result; } - ndbout << result << " NDB Cluster storage node(s) have shutdown." << endl; + ndbout << result << " NDB Cluster node(s) have shutdown." << endl; int mgm_id= 0; - for(int i=0; i < state->no_of_nodes; i++) { - if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM && - state->node_states[i].version != 0){ - if (mgm_id == 0) - mgm_id= state->node_states[i].node_id; - else { - ndbout << "Unable to locate management server, " - << "shutdown manually with STOP" - << endl; - return 1; - } - } + mgm_id= ndb_mgm_get_mgmd_nodeid(m_mgmsrv); + if (mgm_id == 0) + { + ndbout << "Unable to locate management server, " + << "shutdown manually with STOP" + << endl; + return 1; } result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id); diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 34a0adf46b9..bfa9f67b793 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -60,6 +60,9 @@ #include +extern bool g_StopServer; +extern bool g_RestartServer; + //#define MGM_SRV_DEBUG #ifdef MGM_SRV_DEBUG #define DEBUG(x) do ndbout << x << endl; while(0) @@ -373,7 +376,8 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server, _ownReference(0), theSignalIdleList(NULL), theWaitState(WAIT_SUBSCRIBE_CONF), - m_event_listner(this) + m_event_listner(this), + m_local_mgm_handle(0) { DBUG_ENTER("MgmtSrvr::MgmtSrvr"); @@ -541,6 +545,8 @@ MgmtSrvr::check_start() bool MgmtSrvr::start(BaseString &error_string) { + int mgm_connect_result; + DBUG_ENTER("MgmtSrvr::start"); if (_props == NULL) { if (!check_start()) { @@ -578,6 +584,13 @@ MgmtSrvr::start(BaseString &error_string) DBUG_RETURN(false); } + if((mgm_connect_result= connect_to_self()) < 0) + { + ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)", + mgm_connect_result); + ndbout_c("This is probably a bug."); + } + TransporterRegistry *reg = theFacade->get_registry(); for(unsigned int i=0;im_transporter_interface.size();i++) { BaseString msg; @@ -835,9 +848,81 @@ MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address) return 0; } +int MgmtSrvr::sendStopMgmd(NodeId nodeId, + bool abort, + bool stop, + bool restart, + bool nostart, + bool initialStart) +{ + const char* hostname; + Uint32 port; + BaseString connect_string; + + { + Guard g(m_configMutex); + { + ndb_mgm_configuration_iterator + iter(* _config->m_configValues, CFG_SECTION_NODE); + + if(iter.first()) return SEND_OR_RECEIVE_FAILED; + if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED; + if(iter.get(CFG_NODE_HOST, &hostname)) return SEND_OR_RECEIVE_FAILED; + } + { + ndb_mgm_configuration_iterator + iter(* _config->m_configValues, CFG_SECTION_NODE); + + if(iter.first()) return SEND_OR_RECEIVE_FAILED; + if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED; + if(iter.get(CFG_MGM_PORT, &port)) return SEND_OR_RECEIVE_FAILED; + } + if( strlen(hostname) == 0 ) + return SEND_OR_RECEIVE_FAILED; + } + connect_string.assfmt("%s:%u",hostname,port); + + DBUG_PRINT("info",("connect string: %s",connect_string.c_str())); + + NdbMgmHandle h= ndb_mgm_create_handle(); + if ( h && connect_string.length() > 0 ) + { + ndb_mgm_set_connectstring(h,connect_string.c_str()); + if(ndb_mgm_connect(h,1,0,0)) + { + DBUG_PRINT("info",("failed ndb_mgm_connect")); + return SEND_OR_RECEIVE_FAILED; + } + if(!restart) + { + if(ndb_mgm_stop(h, 1, (const int*)&nodeId) < 0) + { + return SEND_OR_RECEIVE_FAILED; + } + } + else + { + int nodes[1]; + nodes[0]= (int)nodeId; + if(ndb_mgm_restart2(h, 1, nodes, initialStart, nostart, abort) < 0) + { + return SEND_OR_RECEIVE_FAILED; + } + } + } + ndb_mgm_destroy_handle(&h); + + return 0; +} + /* * Common method for handeling all STOP_REQ signalling that * is used by Stopping, Restarting and Single user commands + * + * In the event that we need to stop a mgmd, we create a mgm + * client connection to that mgmd and stop it that way. + * This allows us to stop mgm servers when there isn't any real + * distributed communication up. */ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, @@ -849,6 +934,8 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, bool nostart, bool initialStart) { + int error = 0; + stoppedNodes.clear(); SignalSender ss(theFacade); @@ -887,18 +974,34 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, NodeBitmask nodes; if (nodeId) { + if(nodeId==getOwnNodeId()) + { + if(restart) + g_RestartServer= true; + g_StopServer= true; + return 0; + } + if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB) { int r; - if((r = okToSendTo(nodeId, true)) != 0) - return r; - } - { + if((r= okToSendTo(nodeId, true)) != 0) + return r; if (ss.sendSignal(nodeId, &ssig) != SEND_OK) return SEND_OR_RECEIVE_FAILED; } + else if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM) + { + error= sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart); + if(error==0) + stoppedNodes.set(nodeId); + return error; + } + else + return WRONG_PROCESS_TYPE; nodes.set(nodeId); } else + { while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) { if(okToSendTo(nodeId, true) == 0) @@ -908,9 +1011,17 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, nodes.set(nodeId); } } + nodeId= 0; + while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)) + { + if(nodeId==getOwnNodeId()) + continue; + if(sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart)==0) + stoppedNodes.set(nodeId); + } + } // now wait for the replies - int error = 0; while (!nodes.isclear()) { SimpleSignal *signal = ss.waitFor(); @@ -2446,9 +2557,23 @@ void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd) } } -int MgmtSrvr::set_connect_string(const char *str) +int MgmtSrvr::connect_to_self(void) { - return ndb_mgm_set_connectstring(m_config_retriever->get_mgmHandle(),str); + int r= 0; + m_local_mgm_handle= ndb_mgm_create_handle(); + snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string), + "localhost:%u",getPort()); + ndb_mgm_set_connectstring(m_local_mgm_handle, m_local_mgm_connect_string); + + if((r= ndb_mgm_connect(m_local_mgm_handle, 0, 0, 0)) < 0) + { + ndb_mgm_destroy_handle(&m_local_mgm_handle); + return r; + } + // TransporterRegistry now owns this NdbMgmHandle and will destroy it. + theFacade->get_registry()->set_mgm_handle(m_local_mgm_handle); + + return 0; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index 600d168ee08..46bdb112cb9 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -471,7 +471,7 @@ public: int getConnectionDbParameter(int node1, int node2, int param, int *value, BaseString& msg); - int set_connect_string(const char *str); + int connect_to_self(void); void transporter_connect(NDB_SOCKET_TYPE sockfd); @@ -487,6 +487,13 @@ private: int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type); + int sendStopMgmd(NodeId nodeId, + bool abort, + bool stop, + bool restart, + bool nostart, + bool initialStart); + int sendSTOP_REQ(NodeId nodeId, NodeBitmask &stoppedNodes, Uint32 singleUserNodeId, @@ -629,6 +636,8 @@ private: // signal arrives. // We wait in receiveOptimisedResponse and signal in handleReceivedSignal. + NdbMgmHandle m_local_mgm_handle; + char m_local_mgm_connect_string[20]; class TransporterFacade * theFacade; int sendVersionReq( int processId, Uint32 &version, const char **address); diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index ee24cf18941..80f0aa2eda8 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -203,6 +203,8 @@ ParserRow commands[] = { MGM_CMD("bye", &MgmApiSession::bye, ""), + MGM_CMD("end session", &MgmApiSession::endSession, ""), + MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""), MGM_ARG("node", Int, Mandatory, "Node"), MGM_ARG("category", Int, Mandatory, "Event category"), @@ -719,10 +721,21 @@ MgmApiSession::dumpState(Parser::Context &, void MgmApiSession::bye(Parser::Context &, - Properties const &) { + Properties const &) { m_stop = true; } +void +MgmApiSession::endSession(Parser::Context &, + Properties const &) { + if(m_allocated_resources) + delete m_allocated_resources; + + m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); + + m_output->println("end session reply"); +} + void MgmApiSession::setClusterLogLevel(Parser::Context &, Properties const &args) { diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp index 30f220cd060..f97223750a1 100644 --- a/ndb/src/mgmsrv/Services.hpp +++ b/ndb/src/mgmsrv/Services.hpp @@ -79,6 +79,7 @@ public: void start(Parser_t::Context &ctx, const class Properties &args); void startAll(Parser_t::Context &ctx, const class Properties &args); void bye(Parser_t::Context &ctx, const class Properties &args); + void endSession(Parser_t::Context &ctx, const class Properties &args); void setLogLevel(Parser_t::Context &ctx, const class Properties &args); void setClusterLogLevel(Parser_t::Context &ctx, const class Properties &args); diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index f0c2ac298a5..e8a2a366dc9 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -132,6 +132,7 @@ static MgmGlobals *glob= 0; * Global variables */ bool g_StopServer; +bool g_RestartServer; extern EventLogger g_eventLogger; extern int global_mgmt_server_check; @@ -191,7 +192,19 @@ static void usage() */ int main(int argc, char** argv) { + int mgm_connect_result; + NDB_INIT(argv[0]); + + int ho_error; +#ifndef DBUG_OFF + opt_debug= "d:t:O,/tmp/ndb_mgmd.trace"; +#endif + if ((ho_error=handle_options(&argc, &argv, my_long_options, + ndb_std_get_one_option))) + exit(ho_error); + +start: glob= new MgmGlobals; /** @@ -208,14 +221,6 @@ int main(int argc, char** argv) const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; load_defaults("my",load_default_groups,&argc,&argv); - int ho_error; -#ifndef DBUG_OFF - opt_debug= "d:t:O,/tmp/ndb_mgmd.trace"; -#endif - if ((ho_error=handle_options(&argc, &argv, my_long_options, - ndb_std_get_one_option))) - exit(ho_error); - if (opt_interactive || opt_non_interactive || g_print_full_config) { @@ -293,34 +298,12 @@ int main(int argc, char** argv) goto error_end; } - /* Construct a fake connectstring to connect back to ourselves */ - char connect_str[20]; - if(!opt_connect_str) { - snprintf(connect_str,20,"localhost:%u",glob->mgmObject->getPort()); - opt_connect_str= connect_str; - } - glob->mgmObject->set_connect_string(opt_connect_str); - 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; } - /* - * Connect back to ourselves so we can use mgmapi to fetch - * config info - */ - int mgm_connect_result; - mgm_connect_result = glob->mgmObject->get_config_retriever()-> - do_connect(0,0,0); - - if(mgm_connect_result<0) { - ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)", - mgm_connect_result); - ndbout_c("This is probably a bug."); - } - if (opt_daemon) { // Become a daemon char *lockfile= NdbConfig_PidFileName(glob->localNodeId); @@ -361,6 +344,7 @@ int main(int argc, char** argv) g_eventLogger.info(msg); g_StopServer = false; + g_RestartServer= false; glob->socketServer->startServer(); #if ! defined NDB_OSE && ! defined NDB_SOFTOSE @@ -378,14 +362,19 @@ int main(int argc, char** argv) while(g_StopServer != true) NdbSleep_MilliSleep(500); } - - g_eventLogger.info("Shutting down server..."); + + if(g_RestartServer) + g_eventLogger.info("Restarting server..."); + else + g_eventLogger.info("Shutting down server..."); glob->socketServer->stopServer(); - glob->mgmObject->get_config_retriever()->disconnect(); + // We disconnect from the ConfigRetreiver mgmd when we delete glob below glob->socketServer->stopSessions(true); g_eventLogger.info("Shutdown complete"); the_end: delete glob; + if(g_RestartServer) + goto start; ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); return 0; error_end: From e2b3b1f398994861f4d719a87fa3c7f40bc24786 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Tue, 17 Jan 2006 12:55:30 +0100 Subject: [PATCH 09/28] Increase the version number to 4.1.18 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 9afd2034796..b3daaa5731d 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.17) +AM_INIT_AUTOMAKE(mysql, 4.1.18) 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=17 +NDB_VERSION_BUILD=18 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From f84b301bd19c39b73ef1e89e8485134f8b1fe124 Mon Sep 17 00:00:00 2001 From: "svoj@april.(none)" <> Date: Tue, 17 Jan 2006 18:51:08 +0400 Subject: [PATCH 10/28] BUG#3074: Unversioned symbols in shared library libmysqlclient versioning when linked with GNU ld. --- .bzrignore | 1 + configure.in | 11 ++++++++++- libmysql/Makefile.shared | 2 +- libmysql/libmysql.ver.in | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 libmysql/libmysql.ver.in diff --git a/.bzrignore b/.bzrignore index d8be10eacdb..414a40ef1eb 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1057,3 +1057,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +libmysql/libmysql.ver diff --git a/configure.in b/configure.in index 9afd2034796..6ac6f77b318 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,8 @@ AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 DOT_FRM_VERSION=6 # See the libtool docs for information on how to do shared lib versions. -SHARED_LIB_VERSION=14:0:0 +SHARED_LIB_MAJOR_VERSION=14 +SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=4 @@ -68,6 +69,7 @@ AC_DEFINE_UNQUOTED([PROTOCOL_VERSION], [$PROTOCOL_VERSION], AC_SUBST(DOT_FRM_VERSION) AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION], [Version of .frm files]) +AC_SUBST(SHARED_LIB_MAJOR_VERSION) AC_SUBST(SHARED_LIB_VERSION) AC_SUBST(AVAILABLE_LANGUAGES) AC_SUBST(AVAILABLE_LANGUAGES_ERRORS) @@ -431,6 +433,13 @@ then fi fi +# libmysqlclient versioning when linked with GNU ld. +if $LD --version 2>/dev/null|grep -q GNU; then + LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmysql/libmysql.ver" + AC_CONFIG_FILES(libmysql/libmysql.ver) +fi +AC_SUBST(LD_VERSION_SCRIPT) + # Avoid bug in fcntl on some versions of linux AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") # Any wariation of Linux diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index bb4d252f385..3f72049bf43 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -75,7 +75,7 @@ mysysobjects2 = my_lib.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ $(sql_cmn_objects) $(vio_objects) $(sqlobjects) -target_ldflags = -version-info @SHARED_LIB_VERSION@ +target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@ vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo CLEANFILES = $(target_libadd) $(SHLIBOBJS) \ $(target) diff --git a/libmysql/libmysql.ver.in b/libmysql/libmysql.ver.in new file mode 100644 index 00000000000..20eb0fd41bb --- /dev/null +++ b/libmysql/libmysql.ver.in @@ -0,0 +1 @@ +libmysqlclient_@SHARED_LIB_MAJOR_VERSION@ { global: *; }; From 19fd36e2540be2e807b71fd4350d6893889308e2 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Tue, 17 Jan 2006 23:19:43 +0300 Subject: [PATCH 11/28] A fix and a test case for Bug#16144 "mysql_stmt_attr_get type error": use the right type in mysql_stmt_attr_get --- libmysql/libmysql.c | 2 +- tests/mysql_client_test.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 7c6d140d2ef..921f042922a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2733,7 +2733,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, { switch (attr_type) { case STMT_ATTR_UPDATE_MAX_LENGTH: - *(unsigned long *) value= stmt->update_max_length; + *(my_bool*) value= stmt->update_max_length; break; default: return TRUE; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index f0566995262..797a0b1b8d7 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11753,6 +11753,25 @@ static void test_bug12925() } +/* Bug #16144: mysql_stmt_attr_get type error */ + +static void test_bug16144() +{ + const my_bool flag_orig= (my_bool) 0xde; + my_bool flag= flag_orig; + MYSQL_STMT *stmt; + myheader("test_bug16144"); + + /* Check that attr_get returns correct data on little and big endian CPUs */ + stmt= mysql_stmt_init(mysql); + mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag); + mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag); + DIE_UNLESS(flag == flag_orig); + + mysql_stmt_close(stmt); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11974,6 +11993,7 @@ static struct my_tests_st my_tests[]= { { "test_bug12001", test_bug12001 }, { "test_bug11718", test_bug11718 }, { "test_bug12925", test_bug12925 }, + { "test_bug16144", test_bug16144 }, { 0, 0 } }; From 4ca48591f154b625bdeb2c29bd2c52bfc4d04d04 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Wed, 18 Jan 2006 22:50:31 +0300 Subject: [PATCH 12/28] A fix and a test case for Bug#15613 "libmysqlclient API function mysql_stmt_prepare returns wrong field length" --- sql/protocol.cc | 18 +++++++++-- tests/mysql_client_test.c | 65 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 6a17ae2f95b..a2287740f1e 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -565,9 +565,23 @@ bool Protocol::send_fields(List *list, uint flag) else { /* With conversion */ + uint max_char_len; int2store(pos, thd_charset->number); - uint char_len= field.length / item->collation.collation->mbmaxlen; - int4store(pos+2, char_len * thd_charset->mbmaxlen); + /* + For TEXT/BLOB columns, field_length describes the maximum data + length in bytes. There is no limit to the number of characters + that a TEXT column can store, as long as the data fits into + the designated space. + For the rest of textual columns, field_length is evaluated as + char_count * mbmaxlen, where character count is taken from the + definition of the column. In other words, the maximum number + of characters here is limited by the column definition. + */ + max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB && + field.type <= (int) MYSQL_TYPE_BLOB) ? + field.length / item->collation.collation->mbminlen : + field.length / item->collation.collation->mbmaxlen; + int4store(pos+2, max_char_len * thd_charset->mbmaxlen); } pos[6]= field.type; int2store(pos+7,field.flags); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 797a0b1b8d7..91c2ab9205d 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11772,6 +11772,70 @@ static void test_bug16144() } +/* + Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong + field length" +*/ + +static void test_bug15613() +{ + MYSQL_STMT *stmt; + const char *stmt_text; + MYSQL_RES *metadata; + MYSQL_FIELD *field; + int rc; + myheader("test_bug15613"); + + /* I. Prepare the table */ + rc= mysql_query(mysql, "set names latin1"); + myquery(rc); + mysql_query(mysql, "drop table if exists t1"); + rc= mysql_query(mysql, + "create table t1 (t text character set utf8, " + "tt tinytext character set utf8, " + "mt mediumtext character set utf8, " + "lt longtext character set utf8, " + "vl varchar(255) character set latin1," + "vb varchar(255) character set binary," + "vu varchar(255) character set utf8)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + /* II. Check SELECT metadata */ + stmt_text= ("select t, tt, mt, lt, vl, vb, vu from t1"); + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_fields(metadata); + if (!opt_silent) + { + printf("Field lengths (client character set is latin1):\n" + "text character set utf8:\t\t%lu\n" + "tinytext character set utf8:\t\t%lu\n" + "mediumtext character set utf8:\t\t%lu\n" + "longtext character set utf8:\t\t%lu\n" + "varchar(255) character set latin1:\t%lu\n" + "varchar(255) character set binary:\t%lu\n" + "varchar(255) character set utf8:\t%lu\n", + field[0].length, field[1].length, field[2].length, field[3].length, + field[4].length, field[5].length, field[6].length); + } + DIE_UNLESS(field[0].length == 65535); + DIE_UNLESS(field[1].length == 255); + DIE_UNLESS(field[2].length == 16777215); + DIE_UNLESS(field[3].length == 4294967295UL); + DIE_UNLESS(field[4].length == 255); + DIE_UNLESS(field[5].length == 255); + DIE_UNLESS(field[6].length == 255); + + /* III. Cleanup */ + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); + rc= mysql_query(mysql, "set names default"); + myquery(rc); + mysql_stmt_close(stmt); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -11994,6 +12058,7 @@ static struct my_tests_st my_tests[]= { { "test_bug11718", test_bug11718 }, { "test_bug12925", test_bug12925 }, { "test_bug16144", test_bug16144 }, + { "test_bug15613", test_bug15613 }, { 0, 0 } }; From 166c9f8405ad0e24b82de5bc543882e047b4098f Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Thu, 19 Jan 2006 10:44:44 +0100 Subject: [PATCH 13/28] Update the spec file for the shared compat RPM with version info. --- support-files/MySQL-shared-compat.spec.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/support-files/MySQL-shared-compat.spec.sh b/support-files/MySQL-shared-compat.spec.sh index ffc96fd6fff..72ebf4d4d2b 100644 --- a/support-files/MySQL-shared-compat.spec.sh +++ b/support-files/MySQL-shared-compat.spec.sh @@ -23,16 +23,19 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # Temple Place, Suite 330, Boston, MA 02111-1307 USA +# For 5.0 and up, this is needed because of "libndbclient". +%define _unpackaged_files_terminate_build 0 + # # Change this to match the version of the shared libs you want to include # %define version50 @MYSQL_NO_DASH_VERSION@ -%define version41 4.1.9 -%define version40 4.0.23 +%define version41 4.1.16 +%define version40 4.0.26 %define version3 3.23.58 Name: MySQL-shared-compat -Packager: Lenz Grimmer +Packager: MySQL Product Engineering team Vendor: MySQL AB License: GPL Group: Applications/Databases @@ -47,7 +50,7 @@ Summary: MySQL shared client libraries for MySQL %{version}, %{version41}, # We simply use the "MySQL-shared" subpackages as input sources instead of # rebuilding all from source Source0: MySQL-shared-%{version50}-0.%{_arch}.rpm -Source1: MySQL-shared-%{version41}-0.%{_arch}.rpm +Source1: MySQL-shared-%{version41}-1.%{_arch}.rpm Source2: MySQL-shared-%{version40}-0.%{_arch}.rpm Source3: MySQL-shared-%{version3}-1.%{_arch}.rpm # No need to include the RPMs once more - they can be downloaded seperately From 95e29a975a54ddc3dd99b7197f1dfe3f9df02dfc Mon Sep 17 00:00:00 2001 From: "stewart@mysql.com" <> Date: Thu, 19 Jan 2006 22:50:54 +1100 Subject: [PATCH 14/28] small typo fixes --- mysql-test/ndb/ndbcluster.sh | 2 +- ndb/tools/ndb_size.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index 16bb3a9b122..d3471b6cfde 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -135,7 +135,7 @@ if [ ! -x "$exec_waiter" ]; then fi exec_mgmtclient="$exec_mgmtclient --no-defaults $NDB_MGM_EXTRA_OPTS" -exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $NDB_MGMD_EXTRA_OPTS" +exec_mgmtsrvr="$exec_mgmtsrvr $NDB_MGMD_EXTRA_OPTS" exec_ndb="$exec_ndb --no-defaults $NDBD_EXTRA_OPTS" exec_waiter="$exec_waiter --no-defaults" diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl index e0085c619f0..c285a7590fd 100644 --- a/ndb/tools/ndb_size.pl +++ b/ndb/tools/ndb_size.pl @@ -147,7 +147,7 @@ foreach(@{$tables}) { my $fixed= 1+$size; my @dynamic=$dbh->selectrow_array("select avg(length(`" - .$name. + .$name ."`)) from `".$table.'`'); $dynamic[0]=0 if !$dynamic[0]; @realsize= ($fixed,$fixed,ceil($dynamic[0])); From de7cb5fc995875dd023f2eeba31f90adf8dcbf58 Mon Sep 17 00:00:00 2001 From: "stewart@mysql.com" <> Date: Fri, 20 Jan 2006 00:06:17 +1100 Subject: [PATCH 15/28] fix ndb_mgmd --no-defaults option processing --- ndb/src/mgmsrv/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index e8a2a366dc9..5960a3517b5 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -196,6 +196,9 @@ int main(int argc, char** argv) NDB_INIT(argv[0]); + const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; #ifndef DBUG_OFF opt_debug= "d:t:O,/tmp/ndb_mgmd.trace"; @@ -217,9 +220,6 @@ start: #endif global_mgmt_server_check = 1; - - const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 }; - load_defaults("my",load_default_groups,&argc,&argv); if (opt_interactive || opt_non_interactive || From c079e801228dd5a1d77e262c0a030a810eeda6a4 Mon Sep 17 00:00:00 2001 From: "stewart@mysql.com" <> Date: Fri, 20 Jan 2006 00:08:26 +1100 Subject: [PATCH 16/28] reintroduce --no-defaults to ndb_mgmd --- mysql-test/ndb/ndbcluster.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index d3471b6cfde..16bb3a9b122 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -135,7 +135,7 @@ if [ ! -x "$exec_waiter" ]; then fi exec_mgmtclient="$exec_mgmtclient --no-defaults $NDB_MGM_EXTRA_OPTS" -exec_mgmtsrvr="$exec_mgmtsrvr $NDB_MGMD_EXTRA_OPTS" +exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults $NDB_MGMD_EXTRA_OPTS" exec_ndb="$exec_ndb --no-defaults $NDBD_EXTRA_OPTS" exec_waiter="$exec_waiter --no-defaults" From 509b5b5a272f7b975c305da0e72afae15709c312 Mon Sep 17 00:00:00 2001 From: "knielsen@mysql.com" <> Date: Thu, 19 Jan 2006 15:36:41 +0100 Subject: [PATCH 17/28] Fix option type error, crashes on 64-bit big endian. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f738bb7cee1..7f835c0e8e0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4825,7 +4825,7 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).", (gptr*) &srv_flush_log_at_trx_commit, (gptr*) &srv_flush_log_at_trx_commit, - 0, GET_UINT, OPT_ARG, 1, 0, 2, 0, 0, 0}, + 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method, (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, From a07bbd78da6d686e821a3e1daf7f34aeaf1b380f Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Thu, 19 Jan 2006 16:13:04 +0100 Subject: [PATCH 18/28] Post-review fixes (BUG#15658). --- sql/sp_head.cc | 22 +++++++++++----------- sql/sp_head.h | 2 +- sql/sql_yacc.yy | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9c86ebfddf4..f42fbef82e3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -387,19 +387,19 @@ sp_name_current_db_new(THD *thd, LEX_STRING name) } /* - * Check that the name 'ident' is ok. It's assumed to be an 'ident' - * from the parser, so we only have to check length and trailing spaces. - * The former is a standard requirement (and 'show status' assumes a - * non-empty name), the latter is a mysql:ism as trailing spaces are - * removed by get_field(). - * - * RETURN - * TRUE - bad name - * FALSE - name is ok - */ + Check that the name 'ident' is ok. It's assumed to be an 'ident' + from the parser, so we only have to check length and trailing spaces. + The former is a standard requirement (and 'show status' assumes a + non-empty name), the latter is a mysql:ism as trailing spaces are + removed by get_field(). + + RETURN + TRUE - bad name + FALSE - name is ok +*/ bool -sp_name_check(LEX_STRING ident) +check_routine_name(LEX_STRING ident) { return (!ident.str || !ident.str[0] || ident.str[ident.length-1] == ' '); } diff --git a/sql/sp_head.h b/sql/sp_head.h index d912cfeaac3..858bf523a07 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -104,7 +104,7 @@ sp_name * sp_name_current_db_new(THD *thd, LEX_STRING name); bool -sp_name_check(LEX_STRING name); +check_routine_name(LEX_STRING name); class sp_head :private Query_arena { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2face8238b8..41552100264 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1293,7 +1293,7 @@ sp_name: my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); YYABORT; } - if (sp_name_check($3)) + if (check_routine_name($3)) { my_error(ER_SP_WRONG_NAME, MYF(0), $3.str); YYABORT; @@ -1303,7 +1303,7 @@ sp_name: } | ident { - if (sp_name_check($1)) + if (check_routine_name($1)) { my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); YYABORT; From 28f3989c8acce47967f976bb54fe0d852ccf0731 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Thu, 19 Jan 2006 17:55:54 +0100 Subject: [PATCH 19/28] Fixed BUG#15866: Thread stack limit insufficient for recursive call "fib(20)" Lowered the parameter to 10, and also renamed non-standard table names to t3. --- mysql-test/r/sp.result | 46 +++++++++++++++++------------------ mysql-test/r/sp_trans.result | 2 +- mysql-test/t/sp.test | 47 ++++++++++++++++++------------------ mysql-test/t/sp_trans.test | 2 +- 4 files changed, 49 insertions(+), 48 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 19f3d033f53..63ab2098d5f 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1178,8 +1178,8 @@ drop view v2| delete from t1 | delete from t2 | drop table t4| -drop table if exists fac| -create table fac (n int unsigned not null primary key, f bigint unsigned)| +drop table if exists t3| +create table t3 (n int unsigned not null primary key, f bigint unsigned)| drop procedure if exists ifac| create procedure ifac(n int unsigned) begin @@ -1189,13 +1189,13 @@ set n = 20; # bigint overflow otherwise end if; while i <= n do begin -insert into test.fac values (i, fac(i)); +insert into test.t3 values (i, fac(i)); set i = i + 1; end; end while; end| call ifac(20)| -select * from fac| +select * from t3| n f 1 1 2 2 @@ -1217,7 +1217,7 @@ n f 18 6402373705728000 19 121645100408832000 20 2432902008176640000 -drop table fac| +drop table t3| show function status like '%f%'| Db Name Type Definer Modified Created Security_type Comment test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER @@ -1225,12 +1225,12 @@ drop procedure ifac| drop function fac| show function status like '%f%'| Db Name Type Definer Modified Created Security_type Comment -drop table if exists primes| -create table primes ( +drop table if exists t3| +create table t3 ( i int unsigned not null primary key, p bigint unsigned not null )| -insert into primes values +insert into t3 values ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53), @@ -1253,7 +1253,7 @@ set b = b+200, s = 0; else begin declare p bigint unsigned; -select t.p into p from test.primes t where t.i = s; +select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; @@ -1278,7 +1278,7 @@ begin declare pp bool default 0; call opp(p, pp); if pp then -insert into test.primes values (i, p); +insert into test.t3 values (i, p); set i = i+1; end if; set p = p+2; @@ -1299,7 +1299,7 @@ set b = b+200, s = 0; else begin declare p bigint unsigned; -select t.p into p from test.primes t where t.i = s; +select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; @@ -1318,47 +1318,47 @@ Db Name Type Definer Modified Created Security_type Comment test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER call ip(200)| -select * from primes where i=45 or i=100 or i=199| +select * from t3 where i=45 or i=100 or i=199| i p 45 211 100 557 199 1229 -drop table primes| +drop table t3| drop procedure opp| drop procedure ip| show procedure status like '%p%'| Db Name Type Definer Modified Created Security_type Comment -drop table if exists fib| -create table fib ( f bigint unsigned not null )| +drop table if exists t3| +create table t3 ( f bigint unsigned not null )| drop procedure if exists fib| create procedure fib(n int unsigned) begin if n > 1 then begin declare x, y bigint unsigned; -declare c cursor for select f from fib order by f desc limit 2; +declare c cursor for select f from t3 order by f desc limit 2; open c; fetch c into y; fetch c into x; close c; -insert into fib values (x+y); +insert into t3 values (x+y); call fib(n-1); end; end if; end| set @@max_sp_recursion_depth= 20| -insert into fib values (0), (1)| +insert into t3 values (0), (1)| call fib(3)| -select * from fib order by f asc| +select * from t3 order by f asc| f 0 1 1 2 -delete from fib| -insert into fib values (0), (1)| +delete from t3| +insert into t3 values (0), (1)| call fib(20)| -select * from fib order by f asc| +select * from t3 order by f asc| f 0 1 @@ -1381,7 +1381,7 @@ f 2584 4181 6765 -drop table fib| +drop table t3| drop procedure fib| set @@max_sp_recursion_depth= 0| drop procedure if exists bar| diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index 8f2bd9985fc..e9289cf01c7 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -1,4 +1,4 @@ -drop table if exists t1, t2; +drop table if exists t1, t2, t3; drop procedure if exists bug8850| create table t1 (a int) engine=innodb| create procedure bug8850() diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 68ce9cdb118..f9b218967dd 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1419,9 +1419,9 @@ drop table t4| # fac --disable_warnings -drop table if exists fac| +drop table if exists t3| --enable_warnings -create table fac (n int unsigned not null primary key, f bigint unsigned)| +create table t3 (n int unsigned not null primary key, f bigint unsigned)| --disable_warnings drop procedure if exists ifac| @@ -1435,15 +1435,15 @@ begin end if; while i <= n do begin - insert into test.fac values (i, fac(i)); + insert into test.t3 values (i, fac(i)); set i = i + 1; end; end while; end| call ifac(20)| -select * from fac| -drop table fac| +select * from t3| +drop table t3| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' show function status like '%f%'| drop procedure ifac| @@ -1455,15 +1455,15 @@ show function status like '%f%'| # primes --disable_warnings -drop table if exists primes| +drop table if exists t3| --enable_warnings -create table primes ( +create table t3 ( i int unsigned not null primary key, p bigint unsigned not null )| -insert into primes values +insert into t3 values ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53), @@ -1492,7 +1492,7 @@ begin begin declare p bigint unsigned; - select t.p into p from test.primes t where t.i = s; + select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; @@ -1523,7 +1523,7 @@ begin call opp(p, pp); if pp then - insert into test.primes values (i, p); + insert into test.t3 values (i, p); set i = i+1; end if; set p = p+2; @@ -1545,8 +1545,8 @@ call ip(200)| # 45 211 # 100 557 # 199 1229 -select * from primes where i=45 or i=100 or i=199| -drop table primes| +select * from t3 where i=45 or i=100 or i=199| +drop table t3| drop procedure opp| drop procedure ip| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' @@ -1556,9 +1556,9 @@ show procedure status like '%p%'| # Fibonacci, for recursion test. (Yet Another Numerical series :) # --disable_warnings -drop table if exists fib| +drop table if exists t3| --enable_warnings -create table fib ( f bigint unsigned not null )| +create table t3 ( f bigint unsigned not null )| # We deliberately do it the awkward way, fetching the last two # values from the table, in order to exercise various statements @@ -1571,13 +1571,13 @@ begin if n > 1 then begin declare x, y bigint unsigned; - declare c cursor for select f from fib order by f desc limit 2; + declare c cursor for select f from t3 order by f desc limit 2; open c; fetch c into y; fetch c into x; close c; - insert into fib values (x+y); + insert into t3 values (x+y); call fib(n-1); end; end if; @@ -1588,22 +1588,23 @@ set @@max_sp_recursion_depth= 20| # Minimum test: recursion of 3 levels -insert into fib values (0), (1)| +insert into t3 values (0), (1)| call fib(3)| -select * from fib order by f asc| +select * from t3 order by f asc| -delete from fib| +delete from t3| -# Original test: 20 levels (may run into memory limits!) +# The original test, 20 levels, ran into memory limits on some machines +# and builds. Try 10 instead... -insert into fib values (0), (1)| +insert into t3 values (0), (1)| call fib(20)| -select * from fib order by f asc| -drop table fib| +select * from t3 order by f asc| +drop table t3| drop procedure fib| set @@max_sp_recursion_depth= 0| diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test index 308d4ad5c33..b9bd4c938b3 100644 --- a/mysql-test/t/sp_trans.test +++ b/mysql-test/t/sp_trans.test @@ -5,7 +5,7 @@ -- source include/have_innodb.inc --disable_warnings -drop table if exists t1, t2; +drop table if exists t1, t2, t3; --enable_warnings delimiter |; From 2c6ea2d2dfa19d2585fd86a58d5ae330e56122e1 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Fri, 20 Jan 2006 08:32:22 +0100 Subject: [PATCH 20/28] Fix of fix for BUG#15866. (Actually change the fib() call in sp.test) --- mysql-test/r/sp.result | 12 +----------- mysql-test/t/sp.test | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 63ab2098d5f..904cd7d8642 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1357,7 +1357,7 @@ f 2 delete from t3| insert into t3 values (0), (1)| -call fib(20)| +call fib(10)| select * from t3 order by f asc| f 0 @@ -1371,16 +1371,6 @@ f 21 34 55 -89 -144 -233 -377 -610 -987 -1597 -2584 -4181 -6765 drop table t3| drop procedure fib| set @@max_sp_recursion_depth= 0| diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f9b218967dd..8235686a74a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1601,7 +1601,7 @@ delete from t3| insert into t3 values (0), (1)| -call fib(20)| +call fib(10)| select * from t3 order by f asc| drop table t3| From 145fd62bc12285db199af8b9c49e0428f44ff69c Mon Sep 17 00:00:00 2001 From: "anozdrin@mysql.com" <> Date: Fri, 20 Jan 2006 15:59:22 +0300 Subject: [PATCH 21/28] Fix for BUG#15588: String overrun during sp-vars.test The bug appears after implementation of WL#2984 (Make stored routine variables work according to the standard). --- mysql-test/r/type_varchar.result | 7 +++++++ mysql-test/t/type_varchar.test | 16 +++++++++++++++ sql/field.cc | 4 ++-- sql/sp_head.cc | 35 ++++++++++++++++++++++---------- sql/sql_select.cc | 2 +- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index e3b12cc36e3..e74850bba33 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -415,3 +415,10 @@ t1 CREATE TABLE `t1` ( KEY `index1` (`f1`(10)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index 1a3a93018a4..2d2314f0a29 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -130,3 +130,19 @@ show create table t1; alter table t1 modify f1 tinytext; show create table t1; drop table t1; + +# +# BUG#15588: String overrun +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); +INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); +DROP TABLE IF EXISTS t1; diff --git a/sql/field.cc b/sql/field.cc index df76eb729f8..0d48d4ae004 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5873,7 +5873,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) field_length/ field_charset->mbmaxlen, &well_formed_error); - memcpy(ptr,from,copy_length); + memmove(ptr, from, copy_length); /* Append spaces if the string was shorter than the field. */ if (copy_length < field_length) @@ -6266,7 +6266,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) field_length/ field_charset->mbmaxlen, &well_formed_error); - memcpy(ptr + length_bytes, from, copy_length); + memmove(ptr + length_bytes, from, copy_length); if (length_bytes == 1) *ptr= (uchar) copy_length; else diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f42fbef82e3..ae27b910304 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -105,21 +105,27 @@ sp_get_item_value(Item *item, String *str) case STRING_RESULT: { - char buf_holder[STRING_BUFFER_USUAL_SIZE]; - String buf(buf_holder, sizeof(buf_holder), &my_charset_latin1); String *result= item->val_str(str); if (!result) return NULL; - buf.append('_'); - buf.append(result->charset()->csname); - buf.append('\''); - buf.append(*result); - buf.append('\''); - str->copy(buf); + { + char buf_holder[STRING_BUFFER_USUAL_SIZE]; + String buf(buf_holder, sizeof(buf_holder), result->charset()); - return str; + /* We must reset length of the buffer, because of String specificity. */ + buf.length(0); + + buf.append('_'); + buf.append(result->charset()->csname); + buf.append('\''); + buf.append(*result); + buf.append('\''); + str->copy(buf); + + return str; + } } case ROW_RESULT: @@ -3085,9 +3091,16 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) void sp_instr_set_case_expr::print(String *str) { - str->append(STRING_WITH_LEN("set_case_expr ")); + const char CASE_EXPR_TAG[]= "set_case_expr "; + const int CASE_EXPR_TAG_LEN= sizeof(CASE_EXPR_TAG) - 1; + const int INT_STRING_MAX_LEN= 10; + + /* We must call reserve(), because qs_append() doesn't care about memory. */ + str->reserve(CASE_EXPR_TAG_LEN + INT_STRING_MAX_LEN + 2); + + str->qs_append(CASE_EXPR_TAG, CASE_EXPR_TAG_LEN); str->qs_append(m_case_expr_id); - str->append(' '); + str->qs_append(' '); m_case_expr->print(str); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index be255d1f790..1037f490397 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9046,7 +9046,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List &field_list) ++field; } - *field= NULL; /* mark the end of the list */ + *field= NULL; /* mark the end of the list */ s->blob_field[blob_count]= 0; /* mark the end of the list */ s->blob_fields= blob_count; From f2c3ed8e7b2ab119b6d8896c5187ec375a5e70d4 Mon Sep 17 00:00:00 2001 From: "anozdrin@mysql.com" <> Date: Fri, 20 Jan 2006 17:21:39 +0300 Subject: [PATCH 22/28] Test case for BUG#16621: INSERTs in Stored Procedures causes data corruption in the Binary Log. --- mysql-test/r/rpl_sp.result | 13 +++++++++++++ mysql-test/t/rpl_sp.test | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index c9a9e162fa6..7180b677b8e 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -401,5 +401,18 @@ drop function f1; select * from t1; a 1 +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(col VARCHAR(10)); +CREATE PROCEDURE p1(arg VARCHAR(10)) +INSERT INTO t1 VALUES(arg); +CALL p1('test'); +SELECT * FROM t1; +col +test +SELECT * FROM t1; +col +test +DROP PROCEDURE p1; drop table t1; reset master; diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index 8fa330584e2..c0eaf6f817f 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -401,6 +401,42 @@ sync_slave_with_master; connection slave; select * from t1; +# +# Bug#16621 "INSERTs in Stored Procedures causes data corruption in the Binary +# Log for 5.0.18" +# + +# Prepare environment. + +connection master; + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# Test case. + +CREATE TABLE t1(col VARCHAR(10)); + +CREATE PROCEDURE p1(arg VARCHAR(10)) + INSERT INTO t1 VALUES(arg); + +CALL p1('test'); + +SELECT * FROM t1; + +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; + +# Cleanup. + +connection master; + +DROP PROCEDURE p1; + # cleanup connection master; drop table t1; From 2f657ee9d4aa0a1702149ee11546018a4e5a23b7 Mon Sep 17 00:00:00 2001 From: "brian@zim.tangent.org" <> Date: Sat, 21 Jan 2006 04:49:26 -0800 Subject: [PATCH 23/28] Turns out that the bulk interface was not well documented. I fixed the issue in archive and I will go and update the comments in handler next. I should probably also look through the other engines and see if this an issue elsewhere as well. --- sql/ha_archive.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index c60d40c2685..68219151186 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -135,6 +135,13 @@ static HASH archive_open_tables; #define DATA_BUFFER_SIZE 2 // Size of the data used in the data file #define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption +/* + Number of rows that will force a bulk insert. +*/ +#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2 + + + /* dummy handlerton - only to have something to return from archive_db_init */ handlerton archive_hton = { "ARCHIVE", @@ -1026,7 +1033,8 @@ void ha_archive::info(uint flag) void ha_archive::start_bulk_insert(ha_rows rows) { DBUG_ENTER("ha_archive::start_bulk_insert"); - bulk_insert= TRUE; + if (!rows || rows >= ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT) + bulk_insert= TRUE; DBUG_VOID_RETURN; } From 12fcabbbf2088baa10921253e740cd5fa860b2df Mon Sep 17 00:00:00 2001 From: "holyfoot@eagle.intranet.mysql.r18.ru" <> Date: Sat, 21 Jan 2006 21:50:54 +0400 Subject: [PATCH 24/28] Merging --- mysql-test/r/func_gconcat.result | 6 +++--- mysql-test/r/type_float.result | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 057c4990309..2a36e6fe17b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -131,9 +131,9 @@ grp group_concat(a separator "")+0 3 456789 select grp, group_concat(a separator "")+0.0 from t1 group by grp; grp group_concat(a separator "")+0.0 -1 1 -2 23 -3 456789 +1 1.0 +2 23.0 +3 456789.0 select grp, ROUND(group_concat(a separator "")) from t1 group by grp; grp ROUND(group_concat(a separator "")) 1 1 diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 86c89231cc4..fb8d0515c18 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -245,22 +245,22 @@ show warnings; Level Code Message desc t1; Field Type Null Key Default Extra -x double 0 +x decimal(21,2) unsigned NO 0.00 drop table t1; create table t1 select 0.0 x; desc t1; Field Type Null Key Default Extra -x double(3,1) 0.0 +x decimal(2,1) unsigned NO 0.0 create table t2 select 105213674794682365.00 y; desc t2; Field Type Null Key Default Extra -y double(21,2) 0.00 +y decimal(20,2) unsigned NO 0.00 create table t3 select x+y a from t1,t2; show warnings; Level Code Message desc t3; Field Type Null Key Default Extra -a double 0 +a decimal(21,2) unsigned NO 0.00 drop table t1,t2,t3; create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). From 4dc4502ab3528718c6a7ffb0fd11da224bb700bd Mon Sep 17 00:00:00 2001 From: "svoj@april.(none)" <> Date: Mon, 23 Jan 2006 17:15:33 +0400 Subject: [PATCH 25/28] BUG#16489 - utf8 + fulltext leads to corrupt index file. Fixed that UPDATE statement crashes multi-byte charset fulltext index. --- myisam/ft_update.c | 4 ++++ mysql-test/r/fulltext2.result | 5 +++++ mysql-test/t/fulltext2.test | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/myisam/ft_update.c b/myisam/ft_update.c index beccc062270..8f2b2bce101 100644 --- a/myisam/ft_update.c +++ b/myisam/ft_update.c @@ -170,6 +170,10 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2) FT_SEG_ITERATOR ftsi1, ftsi2; CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset; DBUG_ENTER("_mi_ft_cmp"); +#ifndef MYSQL_HAS_TRUE_CTYPE_IMPLEMENTATION + if (cs->mbmaxlen > 1) + DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT); +#endif _mi_ft_segiterator_init(info, keynr, rec1, &ftsi1); _mi_ft_segiterator_init(info, keynr, rec2, &ftsi2); diff --git a/mysql-test/r/fulltext2.result b/mysql-test/r/fulltext2.result index 72c6b2d22ed..f6a4b20bc22 100644 --- a/mysql-test/r/fulltext2.result +++ b/mysql-test/r/fulltext2.result @@ -234,5 +234,10 @@ insert into t1 values('test test '),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); delete from t1 limit 1; +truncate table t1; +insert into t1 values('ab c d'); +update t1 set a='ab c d'; +select * from t1 where match a against('ab c' in boolean mode); +a drop table t1; set names latin1; diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test index 7a7b572d58f..fd97f795534 100644 --- a/mysql-test/t/fulltext2.test +++ b/mysql-test/t/fulltext2.test @@ -209,6 +209,14 @@ insert into t1 values('test test '),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); delete from t1 limit 1; + +# +# BUG#16489: utf8 + fulltext leads to corrupt index file. +# +truncate table t1; +insert into t1 values('ab c d'); +update t1 set a='ab c d'; +select * from t1 where match a against('ab c' in boolean mode); drop table t1; set names latin1; From 86cb9bf94dc49db0824f389e7e81233b54e5b52c Mon Sep 17 00:00:00 2001 From: "SergeyV@selena." <> Date: Mon, 23 Jan 2006 21:35:11 +0300 Subject: [PATCH 26/28] Changes after initial patch to #15787 --- zlib/Makefile.am | 2 ++ zlib/README.MySQL | 9 +++++++++ zlib/zconf.h | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/zlib/Makefile.am b/zlib/Makefile.am index 11b1991fa62..71619ce40c1 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -16,6 +16,8 @@ # Process this file with automake to create Makefile.in +INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include + pkglib_LTLIBRARIES=libz.la libz_la_LDFLAGS= -version-info 3:3:2 diff --git a/zlib/README.MySQL b/zlib/README.MySQL index 355dfb62d71..c17d3eeb6f9 100644 --- a/zlib/README.MySQL +++ b/zlib/README.MySQL @@ -5,3 +5,12 @@ original zlib distribution. You can find the original distribution at http://www.gzip.org/zlib/ or http://www.zlib.net/ + +Revision history: + +20.01.2006. The following files were changed as part of #15787 fix: + makefile.am + gzio.c + zconf.h + README.mysql + diff --git a/zlib/zconf.h b/zlib/zconf.h index f786a20a6f9..d983fa3eed4 100644 --- a/zlib/zconf.h +++ b/zlib/zconf.h @@ -288,7 +288,7 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +#ifdef HAVE_UNISTD_H # include /* for off_t */ # include /* for SEEK_* and off_t */ # ifdef VMS From fa776a6f6752b0b23fc89e0fd9887c747de0766b Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Tue, 24 Jan 2006 15:59:08 +0400 Subject: [PATCH 27/28] Fix for bug#15851 Unlistable directories yield no info from information_schema to skip directories which are not allowed for read --- mysql-test/r/information_schema.result | 5 +++++ mysql-test/t/information_schema.test | 10 ++++++++++ mysys/my_lib.c | 2 ++ 3 files changed, 17 insertions(+) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index e7d82f48691..074b68881af 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1084,3 +1084,8 @@ DROP TABLE t1; DROP VIEW v1; DROP FUNCTION func1; DROP FUNCTION func2; +create database mysqltest; +create table mysqltest.t1(a int); +select table_schema from information_schema.tables where table_schema='mysqltest'; +table_schema +drop database mysqltest; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index f835a7148a2..323c6b37059 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -790,3 +790,13 @@ DROP TABLE t1; DROP VIEW v1; DROP FUNCTION func1; DROP FUNCTION func2; + +# +# Bug #15851 Unlistable directories yield no info from information_schema +# +create database mysqltest; +create table mysqltest.t1(a int); +--exec chmod -r $MYSQL_TEST_DIR/var/master-data/mysqltest +select table_schema from information_schema.tables where table_schema='mysqltest'; +--exec chmod +r $MYSQL_TEST_DIR/var/master-data/mysqltest +drop database mysqltest; diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 1908c70f407..4ca343064d3 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -170,6 +170,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags) bzero(finfo.mystat, sizeof(MY_STAT)); VOID(strmov(tmp_file,dp->d_name)); VOID(my_stat(tmp_path, finfo.mystat, MyFlags)); + if (!(finfo.mystat->st_mode & MY_S_IREAD)) + continue; } else finfo.mystat= NULL; From b4f7c9bbd53c4934f98cd5a7c3b492d82a997e64 Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Tue, 24 Jan 2006 16:48:19 +0400 Subject: [PATCH 28/28] Fix for bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema(2nd ver) Fill schema tables with data before filesort if it's necessary --- mysql-test/r/information_schema.result | 8 ++++++++ mysql-test/t/information_schema.test | 9 +++++++++ sql/sql_prepare.cc | 2 ++ sql/sql_select.cc | 6 ++++++ sql/sql_show.cc | 12 +++++++++++- sql/table.h | 1 + 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 074b68881af..08d698092e2 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1089,3 +1089,11 @@ create table mysqltest.t1(a int); select table_schema from information_schema.tables where table_schema='mysqltest'; table_schema drop database mysqltest; +select column_type, group_concat(table_schema, '.', table_name), count(*) as num +from information_schema.columns where +table_schema='information_schema' and +(column_type = 'varchar(7)' or column_type = 'varchar(20)') +group by column_type order by num; +column_type group_concat(table_schema, '.', table_name) num +varchar(20) information_schema.COLUMNS 1 +varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2 diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 323c6b37059..85d56bfc78b 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -800,3 +800,12 @@ create table mysqltest.t1(a int); select table_schema from information_schema.tables where table_schema='mysqltest'; --exec chmod +r $MYSQL_TEST_DIR/var/master-data/mysqltest drop database mysqltest; + +# +# Bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema +# +select column_type, group_concat(table_schema, '.', table_name), count(*) as num +from information_schema.columns where +table_schema='information_schema' and +(column_type = 'varchar(7)' or column_type = 'varchar(20)') +group by column_type order by num; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index ffbbf0c6476..68f033f78fe 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2111,6 +2111,8 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) were closed in the end of previous prepare or execute call. */ tables->table= 0; + /* Reset is_schema_table_processed value(needed for I_S tables */ + tables->is_schema_table_processed= FALSE; if (tables->prep_on_expr) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1037f490397..95da0e6263a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11582,6 +11582,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, goto err; } } + + /* Fill schema tables with data before filesort if it's necessary */ + if ((join->select_lex->options & OPTION_SCHEMA_TABLE) && + get_schema_tables_result(join)) + goto err; + if (table->s->tmp_table) table->file->info(HA_STATUS_VARIABLE); // Get record count table->sort.found_records=filesort(thd, table,sortorder, length, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 17a8c846944..1f776d815df 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3845,7 +3845,16 @@ bool get_schema_tables_result(JOIN *join) TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_derived_tables()) { - if (&lex->unit != lex->current_select->master_unit()) // is subselect + bool is_subselect= (&lex->unit != lex->current_select->master_unit()); + /* + The schema table is already processed and + the statement is not a subselect. + So we don't need to handle this table again. + */ + if (table_list->is_schema_table_processed && !is_subselect) + continue; + + if (is_subselect) // is subselect { table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->delete_all_rows(); @@ -3858,6 +3867,7 @@ bool get_schema_tables_result(JOIN *join) if (table_list->schema_table->fill_table(thd, table_list, tab->select_cond)) result= 1; + table_list->is_schema_table_processed= TRUE; } } thd->no_warnings_for_error= 0; diff --git a/sql/table.h b/sql/table.h index ce0616a6833..947316e253f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -515,6 +515,7 @@ typedef struct st_table_list st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; + bool is_schema_table_processed; /* True when the view field translation table is used to convert schema table fields for backwards compatibility with SHOW command.