From ca9c47936cfdf19e9169a482523efca320e5f28e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Apr 2006 12:33:45 +0500 Subject: [PATCH 01/52] Bug#17939: Wrong table format when using UTF8 strings Lines with column names consisting of national letters were wrongly formatted in "mysql --table" results: mysql> SELECT 'xxx xxx xxx' as 'xxx xxx xxx'; +-------------------+ | xxx xxx xxx | +-------------------+ | xxx xxx xxx | +-------------------+ 1 row in set (0.00 sec) It happened because in UTF-8 (and other multibyte charsets) the number of display cells is not always equal to the number of bytes of the string. Data lines (unlike column name lines) were formatted correctly, because data lines were displayed taking in account number of display cells. This patch takes in account number of cells when displaying column names, the same way like displaying data lines does. Note: The patch is going to be applied to 4.1. Test case will be added after merge to 5.0, into "mysql.test", which appeared in 5.0. mysql.cc: Adding column name allignment using numcells(), the same to data alignment, which was implemented earlier. client/mysql.cc: Adding column name allignment, the same to data alignment, which was implemented earlier. --- client/mysql.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 2f9031b84b8..22fe6e81b25 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2145,9 +2145,14 @@ print_table_data(MYSQL_RES *result) (void) tee_fputs("|", PAGER); for (uint off=0; (field = mysql_fetch_field(result)) ; off++) { - tee_fprintf(PAGER, " %-*s|",(int) min(field->max_length, + uint name_length= (uint) strlen(field->name); + uint numcells= charset_info->cset->numcells(charset_info, + field->name, + field->name + name_length); + uint display_length= field->max_length + name_length - numcells; + tee_fprintf(PAGER, " %-*s|",(int) min(display_length, MAX_COLUMN_LENGTH), - field->name); + field->name); num_flag[off]= IS_NUM(field->type); } (void) tee_fputs("\n", PAGER); From 9328e8874ac3eb2351ad2a283482efd097c8515e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Apr 2006 15:09:01 +0500 Subject: [PATCH 02/52] Bug#9509: Optimizer: wrong result after AND with latin1_german2_ci comparisons Fixing part2 of this problem: AND didn't work well with utf8_czech_ci and utf8_lithianian_ci in some cases. The problem was because when during condition optimization field was replaced with a constant, the constant's collation and collation derivation was used later for comparison instead of the field collation and derivation, which led to non-equal new condition in some cases. This patch copies collation and derivation from the field being removed to the new constant, which makes comparison work using the same collation with the one which would be used if no condition optimization were done. In other words: where s1 < 'K' and s1 = 'Y'; was rewritten to: where 'Y' < 'K' and s1 = 'Y'; Now it's rewritten to: where 'Y' collate collation_of_s1 < 'K' and s1 = 'Y' (using derivation of s1) Note, the first problem of this bug (with latin1_german2_ci) was fixed earlier in 5.0 tree, in a separate changeset. mysql-test/r/ctype_utf8.result: Adding test case mysql-test/t/ctype_utf8.test: Adding test case sql/sql_select.cc: Set proper collation of the new item --- mysql-test/r/ctype_utf8.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 18 ++++++++++++++++++ sql/sql_select.cc | 4 ++++ 3 files changed, 53 insertions(+) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 69d7577ee77..615b0ae2d52 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -924,6 +924,37 @@ NULL select ifnull(NULL, _utf8'string'); ifnull(NULL, _utf8'string') string +set names utf8; +create table t1 (s1 char(5) character set utf8 collate utf8_lithuanian_ci); +insert into t1 values ('I'),('K'),('Y'); +select * from t1 where s1 < 'K' and s1 = 'Y'; +s1 +I +Y +select * from t1 where 'K' > s1 and s1 = 'Y'; +s1 +I +Y +drop table t1; +create table t1 (s1 char(5) character set utf8 collate utf8_czech_ci); +insert into t1 values ('c'),('d'),('h'),('ch'),('CH'),('cH'),('Ch'),('i'); +select * from t1 where s1 > 'd' and s1 = 'CH'; +s1 +ch +CH +Ch +select * from t1 where 'd' < s1 and s1 = 'CH'; +s1 +ch +CH +Ch +select * from t1 where s1 = 'cH' and s1 <> 'ch'; +s1 +cH +select * from t1 where 'cH' = s1 and s1 <> 'ch'; +s1 +cH +drop table t1; create table t1 (a varchar(255)) default character set utf8; insert into t1 values (1.0); drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 5044f7979f1..159e8490f12 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -727,6 +727,24 @@ drop table t1; select repeat(_utf8'+',3) as h union select NULL; select ifnull(NULL, _utf8'string'); +# +# Bug#9509 Optimizer: wrong result after AND with comparisons +# +set names utf8; +create table t1 (s1 char(5) character set utf8 collate utf8_lithuanian_ci); +insert into t1 values ('I'),('K'),('Y'); +select * from t1 where s1 < 'K' and s1 = 'Y'; +select * from t1 where 'K' > s1 and s1 = 'Y'; +drop table t1; + +create table t1 (s1 char(5) character set utf8 collate utf8_czech_ci); +insert into t1 values ('c'),('d'),('h'),('ch'),('CH'),('cH'),('Ch'),('i'); +select * from t1 where s1 > 'd' and s1 = 'CH'; +select * from t1 where 'd' < s1 and s1 = 'CH'; +select * from t1 where s1 = 'cH' and s1 <> 'ch'; +select * from t1 where 'cH' = s1 and s1 <> 'ch'; +drop table t1; + # # Bug#10714: Inserting double value into utf8 column crashes server # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 91fc808058f..caaace13c6f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4456,6 +4456,8 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, left_item->collation.collation == value->collation.collation)) { Item *tmp=value->new_item(); + tmp->collation.set(right_item->collation); + if (tmp) { thd->change_item_tree(args + 1, tmp); @@ -4477,6 +4479,8 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, right_item->collation.collation == value->collation.collation)) { Item *tmp=value->new_item(); + tmp->collation.set(left_item->collation); + if (tmp) { thd->change_item_tree(args, tmp); From 0feec183b27838bf2fb0b8fc3abcc6bd0097dcc6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 09:20:55 +0200 Subject: [PATCH 03/52] ndb autotest - add BUILD/compile-ndb-autotest to simplify building autotest on different mysql versions BUILD/compile-ndb-autotest: New BitKeeper file ``BUILD/compile-ndb-autotest'' --- BUILD/compile-ndb-autotest | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 BUILD/compile-ndb-autotest diff --git a/BUILD/compile-ndb-autotest b/BUILD/compile-ndb-autotest new file mode 100755 index 00000000000..3ef0091c155 --- /dev/null +++ b/BUILD/compile-ndb-autotest @@ -0,0 +1,9 @@ +#! /bin/sh + +path=`dirname $0` +. "$path/SETUP.sh" + +extra_flags="$fast_cflags $max_cflags -g" +extra_configs="$max_configs --with-ndb-test --with-ndb-ccflags="-DERROR_INSERT"" + +. "$path/FINISH.sh" From 31e3e753042bf6e51fc26d38fa5eb6794e7ebccd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Jul 2006 16:01:35 +0200 Subject: [PATCH 04/52] ndb - bug#20904 Reset logpartstate if file_change_problem after writeing of zero page is done --- ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 42e38b41b4b..e4289715c38 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -12508,6 +12508,20 @@ void Dblqh::lastWriteInFileLab(Signal* signal) void Dblqh::writePageZeroLab(Signal* signal) { + if (logPartPtr.p->logPartState == LogPartRecord::FILE_CHANGE_PROBLEM) + { + if (logPartPtr.p->firstLogQueue == RNIL) + { + jam(); + logPartPtr.p->logPartState = LogPartRecord::IDLE; + } + else + { + jam(); + logPartPtr.p->logPartState = LogPartRecord::ACTIVE; + } + } + logFilePtr.p->fileChangeState = LogFileRecord::NOT_ONGOING; /*---------------------------------------------------------------------------*/ /* IT COULD HAVE ARRIVED PAGE WRITES TO THE CURRENT FILE WHILE WE WERE */ From 43181777c19badfbe8a5c5f3cf3fde560fa0a297 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Jul 2006 18:02:42 +0500 Subject: [PATCH 05/52] Bug #15440 (handler.test hangs in embedded mode) the old problem - mysqltest can't handle multiple connections in the embedded server properly. So i disabled the test for the embedded mode until mysqltest is fixed mysql-test/t/handler.test: test temporarily disabled in embedded server --- mysql-test/t/handler.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index a78800d3d5a..55936e44b32 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -1,3 +1,4 @@ +-- source include/not_embedded.inc # # test of HANDLER ... # From 3845856cc65eacd397d1ccf84ad283d223a52e9d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 16:33:26 -0600 Subject: [PATCH 06/52] Bug #20402: DROP USER failure logged as ERROR rather than WARNING slave.cc, sql_acl.cc: - remove sql_print_error() for events that are not server errors sql/slave.cc: Bug #20402: DROP USER failure logged as ERROR rather than WARNING remove sql_print_error() for events that are not server errors sql/sql_acl.cc: Bug #20402: DROP USER failure logged as ERROR rather than WARNING remove sql_print_error() for events that are not server errors --- sql/slave.cc | 2 +- sql/sql_acl.cc | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index b2862a437bb..bceeca1055c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2946,7 +2946,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) rli->is_until_satisfied()) { char buf[22]; - sql_print_error("Slave SQL thread stopped because it reached its" + sql_print_information("Slave SQL thread stopped because it reached its" " UNTIL position %s", llstr(rli->until_pos(), buf)); /* Setting abort_slave flag because we do not want additional message about diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 734bccb6b46..0ad5432f3eb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3671,17 +3671,11 @@ int mysql_drop_user(THD *thd, List &list) { if (!(acl_user= check_acl_user(user_name, &counter))) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; No such user", - user_name->user.str, - user_name->host.str); result= -1; continue; } if ((acl_user->access & ~0)) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Global privileges exists", - user_name->user.str, - user_name->host.str); result= -1; continue; } @@ -3702,9 +3696,6 @@ int mysql_drop_user(THD *thd, List &list) } if (counter != acl_dbs.elements) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Database privileges exists", - user_name->user.str, - user_name->host.str); result= -1; continue; } @@ -3725,9 +3716,6 @@ int mysql_drop_user(THD *thd, List &list) } if (counter != column_priv_hash.records) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Table privileges exists", - user_name->user.str, - user_name->host.str); result= -1; continue; } @@ -3793,9 +3781,6 @@ int mysql_revoke_all(THD *thd, List &list) { if (!check_acl_user(lex_user, &counter)) { - sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists", - lex_user->user.str, - lex_user->host.str); result= -1; continue; } From 2b86ee9f0aa874065acf25094782e1e1f0f0f7b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Aug 2006 15:18:21 +0500 Subject: [PATCH 07/52] bug #13717 embedded library dumps warnings on STDERR directly Here i just disabled STDERR warnings in embedded server Later we should get more defined about logs in the embedded server sql/log.cc: Log messages muted in embedded server --- sql/log.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index c530f15a84f..78605de3141 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2321,6 +2321,12 @@ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, void */ +#ifdef EMBEDDED_LIBRARY +void vprint_msg_to_log(enum loglevel level __attribute__((unused)), + const char *format __attribute__((unused)), + va_list argsi __attribute__((unused))) +{} +#else /*!EMBEDDED_LIBRARY*/ void vprint_msg_to_log(enum loglevel level, const char *format, va_list args) { char buff[1024]; @@ -2336,6 +2342,7 @@ void vprint_msg_to_log(enum loglevel level, const char *format, va_list args) DBUG_VOID_RETURN; } +#endif /*EMBEDDED_LIBRARY*/ void sql_print_error(const char *format, ...) From e80d95a7d68ccd0602778fe1502aa39639fbadbb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Aug 2006 16:55:41 +0200 Subject: [PATCH 08/52] ndb - bug#21384 handle error in TCKEYREQ during TCINDXREQ better ndb/src/kernel/blocks/ERROR_codes.txt: new error code ndb/src/kernel/blocks/dbtc/Dbtc.hpp: Add 3 values to isIndexOp ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: handle error in TCKEYREQ during TCINDXREQ ndb/test/ndbapi/testIndex.cpp: Add testcase ndb/test/run-test/daily-basic-tests.txt: Add testcase --- ndb/src/kernel/blocks/ERROR_codes.txt | 3 +- ndb/src/kernel/blocks/dbtc/Dbtc.hpp | 4 +- ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 161 +++++++++++++++++++----- ndb/test/ndbapi/testIndex.cpp | 52 ++++++++ ndb/test/run-test/daily-basic-tests.txt | 4 + 5 files changed, 192 insertions(+), 32 deletions(-) diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 20f03e7ea69..e4d115a600a 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -6,7 +6,7 @@ Next DBTUP 4013 Next DBLQH 5043 Next DBDICT 6006 Next DBDIH 7174 -Next DBTC 8037 +Next DBTC 8038 Next CMVMI 9000 Next BACKUP 10022 Next DBUTIL 11002 @@ -281,6 +281,7 @@ ABORT OF TCKEYREQ 8032: No free TC records any more +8037 : Invalid schema version in TCINDXREQ CMVMI ----- diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index 25c746b0a89..4488e7500f5 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -718,7 +718,7 @@ public: // Index data - bool isIndexOp; // Used to mark on-going TcKeyReq as indx table access + Uint8 isIndexOp; // Used to mark on-going TcKeyReq as indx table access bool indexOpReturn; UintR noIndexOp; // No outstanding index ops @@ -806,7 +806,7 @@ public: UintR savedState[LqhKeyConf::SignalLength]; // Index data - bool isIndexOp; // Used to mark on-going TcKeyReq as index table access + Uint8 isIndexOp; // Used to mark on-going TcKeyReq as index table access UintR indexOp; UintR currentIndexId; UintR attrInfoLen; diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index a71942f5cc8..ab0981a98ef 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -1757,8 +1757,7 @@ void Dbtc::execKEYINFO(Signal* signal) apiConnectptr.i = signal->theData[0]; tmaxData = 20; if (apiConnectptr.i >= capiConnectFilesize) { - jam(); - warningHandlerLab(signal); + TCKEY_abort(signal, 18); return; }//if ptrAss(apiConnectptr, apiConnectRecord); @@ -1767,9 +1766,7 @@ void Dbtc::execKEYINFO(Signal* signal) compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2]; compare_transid1 = compare_transid1 | compare_transid2; if (compare_transid1 != 0) { - jam(); - printState(signal, 10); - sendSignalErrorRefuseLab(signal); + TCKEY_abort(signal, 19); return; }//if switch (apiConnectptr.p->apiConnectstate) { @@ -2467,7 +2464,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) Uint32 TstartFlag = tcKeyReq->getStartFlag(Treqinfo); Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo); - bool isIndexOp = regApiPtr->isIndexOp; + Uint8 isIndexOp = regApiPtr->isIndexOp; bool isIndexOpReturn = regApiPtr->indexOpReturn; regApiPtr->isIndexOp = false; // Reset marker regApiPtr->m_exec_flag |= TexecFlag; @@ -3210,7 +3207,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal, sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16); sig2 = regApiPtr->transid[0]; sig3 = regApiPtr->transid[1]; - sig4 = regApiPtr->ndbapiBlockref; + sig4 = (regTcPtr->isIndexOp == 2) ? reference() : regApiPtr->ndbapiBlockref; sig5 = regTcPtr->clientData; sig6 = regCachePtr->scanInfo; @@ -8551,6 +8548,7 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) // left over from simple/dirty read } else { jam(); + jamLine(transP->apiConnectstate); errCode = ZSTATE_ERROR; goto SCAN_TAB_error_no_state_change; } @@ -11915,14 +11913,18 @@ void Dbtc::readIndexTable(Signal* signal, opType == ZREAD ? ZREAD : ZREAD_EX); TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0); - BlockReference originalReceiver = regApiPtr->ndbapiBlockref; - regApiPtr->ndbapiBlockref = reference(); // Send result to me tcKeyReq->senderData = indexOp->indexOpId; indexOp->indexOpState = IOS_INDEX_ACCESS; regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp; regApiPtr->accumulatingIndexOp = RNIL; - regApiPtr->isIndexOp = true; + regApiPtr->isIndexOp = 2; + if (ERROR_INSERTED(8037)) + { + ndbout_c("shifting index version"); + tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.indexSchemaVersion; + } + Uint32 remainingKey = indexOp->keyInfo.getSize(); bool moreKeyData = indexOp->keyInfo.first(keyIter); // *********** KEYINFO in TCKEYREQ *********** @@ -11941,21 +11943,13 @@ void Dbtc::readIndexTable(Signal* signal, ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0); ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0); EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); - - /** - * "Fool" TC not to start commiting transaction since it always will - * have one outstanding lqhkeyreq - * This is later decreased when the index read is complete - */ - regApiPtr->lqhkeyreqrec++; - - /** - * Remember ptr to index read operation - * (used to set correct save point id on index operation later) - */ - indexOp->indexReadTcConnect = regApiPtr->lastTcConnect; - jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + goto err; + } + // *********** KEYINFO *********** if (moreKeyData) { jam(); @@ -11975,6 +11969,10 @@ void Dbtc::readIndexTable(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + goto err; + } dataPos = 0; dataPtr = (Uint32 *) &keyInfo->keyData; } @@ -11985,10 +11983,32 @@ void Dbtc::readIndexTable(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + dataPos); jamEntry(); + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + goto err; + } } } - regApiPtr->ndbapiBlockref = originalReceiver; // reset original receiver + /** + * "Fool" TC not to start commiting transaction since it always will + * have one outstanding lqhkeyreq + * This is later decreased when the index read is complete + */ + regApiPtr->lqhkeyreqrec++; + + /** + * Remember ptr to index read operation + * (used to set correct save point id on index operation later) + */ + indexOp->indexReadTcConnect = regApiPtr->lastTcConnect; + +done: + return; + +err: + jam(); + goto done; } /** @@ -12039,7 +12059,7 @@ void Dbtc::executeIndexOperation(Signal* signal, tcKeyReq->transId2 = regApiPtr->transid[1]; tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API indexOp->indexOpState = IOS_INDEX_OPERATION; - regApiPtr->isIndexOp = true; + regApiPtr->isIndexOp = 1; regApiPtr->executingIndexOp = indexOp->indexOpId;; regApiPtr->noIndexOp++; // Increase count @@ -12112,9 +12132,16 @@ void Dbtc::executeIndexOperation(Signal* signal, const Uint32 currSavePointId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = tmp.p->savePointId; EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); + jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + regApiPtr->currSavePointId = currSavePointId; - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { jam(); @@ -12135,6 +12162,13 @@ void Dbtc::executeIndexOperation(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPos = 0; dataPtr = (Uint32 *) &keyInfo->keyData; } @@ -12145,6 +12179,12 @@ void Dbtc::executeIndexOperation(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal, KeyInfo::HeaderLength + dataPos); jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } } } @@ -12174,6 +12214,13 @@ void Dbtc::executeIndexOperation(Signal* signal, EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal, AttrInfo::HeaderLength + AttrInfo::DataLength); jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + attrInfoPos = 0; dataPtr = (Uint32 *) &attrInfo->attrData; } @@ -12573,9 +12620,16 @@ void Dbtc::insertIntoIndexTable(Signal* signal, const Uint32 currSavePointId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = opRecord->savePointId; EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); + jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + regApiPtr->currSavePointId = currSavePointId; tcConnectptr.p->currentIndexId = indexData->indexId; - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { @@ -12605,6 +12659,12 @@ void Dbtc::insertIntoIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } @@ -12640,6 +12700,13 @@ void Dbtc::insertIntoIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } @@ -12657,6 +12724,11 @@ void Dbtc::insertIntoIndexTable(Signal* signal, KeyInfo::HeaderLength + dataPos); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } } } @@ -12692,6 +12764,12 @@ void Dbtc::insertIntoIndexTable(Signal* signal, AttrInfo::HeaderLength + AttrInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &attrInfo->attrData; attrInfoPos = 0; } @@ -12728,6 +12806,12 @@ void Dbtc::insertIntoIndexTable(Signal* signal, AttrInfo::HeaderLength + AttrInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &attrInfo->attrData; attrInfoPos = 0; } @@ -12873,9 +12957,16 @@ void Dbtc::deleteFromIndexTable(Signal* signal, const Uint32 currSavePointId = regApiPtr->currSavePointId; regApiPtr->currSavePointId = opRecord->savePointId; EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength); + jamEntry(); + + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + regApiPtr->currSavePointId = currSavePointId; tcConnectptr.p->currentIndexId = indexData->indexId; - jamEntry(); // *********** KEYINFO *********** if (moreKeyData) { @@ -12906,6 +12997,12 @@ void Dbtc::deleteFromIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } @@ -12942,6 +13039,12 @@ void Dbtc::deleteFromIndexTable(Signal* signal, KeyInfo::HeaderLength + KeyInfo::DataLength); jamEntry(); #endif + if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING)) + { + jam(); + return; + } + dataPtr = (Uint32 *) &keyInfo->keyData; dataPos = 0; } diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index d359f83257f..174f6f170f4 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -1201,6 +1201,48 @@ int runLQHKEYREF(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runBug21384(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* pNdb = GETNDB(step); + HugoTransactions hugoTrans(*ctx->getTab()); + NdbRestarter restarter; + + int loops = ctx->getNumLoops(); + const int rows = ctx->getNumRecords(); + const int batchsize = ctx->getProperty("BatchSize", 50); + + while (loops--) + { + if(restarter.insertErrorInAllNodes(8037) != 0) + { + g_err << "Failed to error insert(8037)" << endl; + return NDBT_FAILED; + } + + if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchsize) == 0) + { + g_err << "Index succeded (it should have failed" << endl; + return NDBT_FAILED; + } + + if(restarter.insertErrorInAllNodes(0) != 0) + { + g_err << "Failed to error insert(0)" << endl; + return NDBT_FAILED; + } + + if (hugoTrans.indexReadRecords(pNdb, pkIdxName, rows, batchsize) != 0){ + g_err << "Index read failed" << endl; + return NDBT_FAILED; + } + } + + return NDBT_OK; +} + + + NDBT_TESTSUITE(testIndex); TESTCASE("CreateAll", "Test that we can create all various indexes on each table\n" @@ -1507,6 +1549,16 @@ TESTCASE("UniqueNull", FINALIZER(createPkIndex_Drop); FINALIZER(runClearTable); } +TESTCASE("Bug21384", + "Test that unique indexes and nulls"){ + TC_PROPERTY("LoggedIndexes", (unsigned)0); + INITIALIZER(runClearTable); + INITIALIZER(createPkIndex); + INITIALIZER(runLoadTable); + STEP(runBug21384); + FINALIZER(createPkIndex_Drop); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testIndex); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index e70dcafb249..004d49f651f 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -474,6 +474,10 @@ max-time: 1000 cmd: testNodeRestart args: -n Bug20185 T1 +max-time: 1000 +cmd: testIndex +args: -n Bug21384 + # OLD FLEX max-time: 500 cmd: flexBench From 753651c1db798da646b606b02b292919f1ffe04a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Aug 2006 09:08:21 +0200 Subject: [PATCH 09/52] ndb - Make possible to build both debug/release from compile-ndb-autotest BUILD/compile-ndb-autotest: Make possible to build both debug/release from compile-ndb-autotest --- BUILD/compile-ndb-autotest | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/BUILD/compile-ndb-autotest b/BUILD/compile-ndb-autotest index 3ef0091c155..be28cc28346 100755 --- a/BUILD/compile-ndb-autotest +++ b/BUILD/compile-ndb-autotest @@ -3,7 +3,17 @@ path=`dirname $0` . "$path/SETUP.sh" -extra_flags="$fast_cflags $max_cflags -g" -extra_configs="$max_configs --with-ndb-test --with-ndb-ccflags="-DERROR_INSERT"" +extra_configs="$max_configs --with-ndb-test --with-ndb-ccflags='-DERROR_INSERT'" +if [ "$full_debug" ] +then + extra_flags="$debug_cflags" + c_warnings="$c_warnings $debug_extra_warnings" + cxx_warnings="$cxx_warnings $debug_extra_warnings" + extra_configs="$debug_configs $extra_configs" +else + extra_flags="$fast_cflags" +fi + +extra_flags="$extra_flags $max_cflags -g" . "$path/FINISH.sh" From 42fd7e8f7d0ecae92bf154cf277dfe8dd5ba9f5f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Aug 2006 14:01:37 +0200 Subject: [PATCH 10/52] ndb - bug#20892 Fix bug in tup buddy allocator, which made it make invalid access to cfreepagelist[16] (which is not defined) ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp: loop from firstListToCheck -1 (as firstListToCheck has already been checked), when looking for less than requested pages add if-statement for firtListToCheck == 0 --- ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp | 30 ++++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp index 9722aa437c0..8a18fddae19 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp @@ -184,24 +184,28 @@ void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate, /* PROPER AMOUNT OF PAGES WERE NOT FOUND. FIND AS MUCH AS */ /* POSSIBLE. */ /* ---------------------------------------------------------------- */ - for (Uint32 j = firstListToCheck; (Uint32)~j; j--) { + if (firstListToCheck) + { ljam(); - if (cfreepageList[j] != RNIL) { + for (Uint32 j = firstListToCheck - 1; (Uint32)~j; j--) { ljam(); + if (cfreepageList[j] != RNIL) { + ljam(); /* ---------------------------------------------------------------- */ /* SOME AREA WAS FOUND, ALLOCATE ALL OF IT. */ /* ---------------------------------------------------------------- */ - allocPageRef = cfreepageList[j]; - removeCommonArea(allocPageRef, j); - noOfPagesAllocated = 1 << j; - findFreeLeftNeighbours(allocPageRef, noOfPagesAllocated, - noOfPagesToAllocate); - findFreeRightNeighbours(allocPageRef, noOfPagesAllocated, - noOfPagesToAllocate); - - return; - }//if - }//for + allocPageRef = cfreepageList[j]; + removeCommonArea(allocPageRef, j); + noOfPagesAllocated = 1 << j; + findFreeLeftNeighbours(allocPageRef, noOfPagesAllocated, + noOfPagesToAllocate); + findFreeRightNeighbours(allocPageRef, noOfPagesAllocated, + noOfPagesToAllocate); + + return; + }//if + }//for + } /* ---------------------------------------------------------------- */ /* NO FREE AREA AT ALL EXISTED. RETURN ZERO PAGES */ /* ---------------------------------------------------------------- */ From f287b4a8c8eb5890a38f18461b94fa11fc85e600 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Aug 2006 08:41:32 +0200 Subject: [PATCH 11/52] ndb - bug#20296 (recommit in 4.1) Make sure that tupkeyErrorLab is run if interpretedUpdate(fail), so that entry is not inserted into index. Yeilding crash on following dml on tupel ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp: Make sure that tupkeyErrorLab is run if interpretedUpdate(fail), so that entry is not inserted into index. Yeilding crash on following dml on tupe --- ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 8171fa65771..a1f8b827752 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1111,14 +1111,16 @@ Dbtup::updateStartLab(Signal* signal, regOperPtr->pageOffset, &cinBuffer[0], regOperPtr->attrinbufLen); - if (retValue == -1) { - tupkeyErrorLab(signal); - return -1; - }//if } else { jam(); retValue = interpreterStartLab(signal, pagePtr, regOperPtr->pageOffset); }//if + + if (retValue == -1) { + tupkeyErrorLab(signal); + return -1; + }//if + ndbrequire(regOperPtr->tupVersion != ZNIL); pagePtr->pageWord[regOperPtr->pageOffset + 1] = regOperPtr->tupVersion; if (regTabPtr->checksumIndicator) { From bb285b44c3b61f550122847325478e3ac3f7661d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Aug 2006 09:43:23 +0200 Subject: [PATCH 12/52] ndb - bug#21400 Fix docs for NdbOpertation::sub_reg ndb/include/ndbapi/NdbOperation.hpp: Fix docs for sub_reg --- ndb/include/ndbapi/NdbOperation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp index 46e44226e18..5498b21a962 100644 --- a/ndb/include/ndbapi/NdbOperation.hpp +++ b/ndb/include/ndbapi/NdbOperation.hpp @@ -445,7 +445,7 @@ public: /** * Interpreted program instruction: - * Substract RegSource1 from RegSource2 and put the result in RegDest. + * Substract RegSource2 from RegSource1 and put the result in RegDest. * * @param RegSource1 First register. * @param RegSource2 Second register. From f4e01cf6a13f0a06566355c451f8bfb313b824f6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Aug 2006 09:41:39 +0200 Subject: [PATCH 13/52] ndb - bug#18475 Fix error message on copyfragref ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp: Fix error message --- ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 5a841d6f836..db0acd27da0 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -177,13 +177,12 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal) "the state of a fragment scan was out of sync.", killingNode); break; - + case SystemError::CopyFragRefError: BaseString::snprintf(buf, sizeof(buf), - "Node %d killed this node because " - "it could not copy a fragment during node restart. " - "Copy fragment error code: %u.", - killingNode, data1); + "Killed by node %d as " + "copyfrag failed, error: %u", + killingNode, data1); break; default: From 6e5ad6914e14809ffc0816df7de214ff5d2337b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Aug 2006 07:59:52 +0200 Subject: [PATCH 14/52] ndb - bug#21213 Make sure totSendlenAi is set in case of ACC_ABORTCONF and activeCreate == true (only needed when >2 replica) ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: Make sure totSendlenAi is set in case of ACC_ABORTCONF and activeCreate == true --- ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index e4289715c38..bc6671f805d 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -6435,6 +6435,7 @@ void Dblqh::execACC_ABORTCONF(Signal* signal) * A NORMAL EVENT DURING CREATION OF A FRAGMENT. WE NOW NEED TO CONTINUE * WITH NORMAL COMMIT PROCESSING. * ---------------------------------------------------------------------- */ + regTcPtr->totSendlenAi = regTcPtr->totReclenAi; if (regTcPtr->currTupAiLen == regTcPtr->totReclenAi) { jam(); regTcPtr->abortState = TcConnectionrec::ABORT_IDLE; From 3d7cb87b00e9ee3930efc101d429817ec63da93b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Aug 2006 16:24:14 +0200 Subject: [PATCH 15/52] ndb - bug#21536 Make sure updateNodeInfo is run on master also for temporary tables ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: Run update nodeinfo also here to handle temprorary tables in some situations ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp: new error insert ndb/test/ndbapi/testSystemRestart.cpp: test case --- ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 1 + ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp | 7 ++- ndb/test/ndbapi/testSystemRestart.cpp | 47 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 65c864bd853..02ec5782c3e 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -8338,6 +8338,7 @@ Dbdih::resetReplicaSr(TabRecordPtr tabPtr){ } replicaPtr.i = nextReplicaPtrI; }//while + updateNodeInfo(fragPtr); } } diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index db0acd27da0..f6970ecce2d 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -2036,6 +2036,11 @@ void Ndbcntr::execSET_VAR_REQ(Signal* signal) { void Ndbcntr::updateNodeState(Signal* signal, const NodeState& newState) const{ NodeStateRep * const stateRep = (NodeStateRep *)&signal->theData[0]; + if (newState.startLevel == NodeState::SL_STARTED) + { + CRASH_INSERTION(1000); + } + stateRep->nodeState = newState; stateRep->nodeState.masterNodeId = cmasterNodeId; stateRep->nodeState.setNodeGroup(c_nodeGroup); @@ -2826,7 +2831,7 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){ cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB); } } - + signal->theData[0] = EventReport::NDBStartCompleted; signal->theData[1] = NDB_VERSION; cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); diff --git a/ndb/test/ndbapi/testSystemRestart.cpp b/ndb/test/ndbapi/testSystemRestart.cpp index 30f7aca9b06..8a0100ff3e4 100644 --- a/ndb/test/ndbapi/testSystemRestart.cpp +++ b/ndb/test/ndbapi/testSystemRestart.cpp @@ -1121,6 +1121,46 @@ int runClearTable(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int +runBug21536(NDBT_Context* ctx, NDBT_Step* step) +{ + NdbRestarter restarter; + const Uint32 nodeCount = restarter.getNumDbNodes(); + if(nodeCount != 2){ + g_info << "Bug21536 - 2 nodes to test" << endl; + return NDBT_OK; + } + + int node1 = restarter.getDbNodeId(rand() % nodeCount); + int node2 = restarter.getRandomNodeSameNodeGroup(node1, rand()); + + if (node1 == -1 || node2 == -1) + return NDBT_OK; + + int result = NDBT_OK; + do { + CHECK(restarter.restartOneDbNode(node1, false, true, true) == 0); + CHECK(restarter.waitNodesNoStart(&node1, 1) == 0); + CHECK(restarter.insertErrorInNode(node1, 1000) == 0); + int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + CHECK(restarter.dumpStateOneNode(node1, val2, 2) == 0); + CHECK(restarter.startNodes(&node1, 1) == 0); + restarter.waitNodesStartPhase(&node1, 1, 3, 120); + CHECK(restarter.waitNodesNoStart(&node1, 1) == 0); + + CHECK(restarter.restartOneDbNode(node2, true, true, true) == 0); + CHECK(restarter.waitNodesNoStart(&node2, 1) == 0); + CHECK(restarter.startNodes(&node1, 1) == 0); + CHECK(restarter.waitNodesStarted(&node1, 1) == 0); + CHECK(restarter.startNodes(&node2, 1) == 0); + CHECK(restarter.waitClusterStarted() == 0); + + } while(0); + + g_info << "Bug21536 finished" << endl; + + return result; +} NDBT_TESTSUITE(testSystemRestart); TESTCASE("SR1", @@ -1287,6 +1327,13 @@ TESTCASE("Bug18385", STEP(runBug18385); FINALIZER(runClearTable); } +TESTCASE("Bug21536", + "Perform partition system restart with other nodes with higher GCI"){ + INITIALIZER(runWaitStarted); + INITIALIZER(runClearTable); + STEP(runBug21536); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testSystemRestart); int main(int argc, const char** argv){ From fa1641e1f3c68e240d79099ae9a3a1346997e4d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 15:37:24 +0200 Subject: [PATCH 16/52] Bug#19844: time_format in Union truncates values time_format() claimed %H and %k would return at most two digits (hours 0-23), but this coincided neither with actual behaviour nor with docs. this is not visible in simple queries; forcing a temp-table is probably the easiest way to see this. adjusted the return-length appropriately; the alternative would be to adjust the docs to say that behaviour for > 99 hours is undefined. --- Bug#19844: time_format in Union truncates values time_format() claimed %H and %k would return at most two digits (hours 0-23), but this coincided neither with actual behaviour nor with docs. this is not visible in simple queries; forcing a temp-table is probably the easiest way to see this. adjusted the return-length appropriately; the alternative would be to adjust the docs to say that behaviour for > 99 hours is undefined. mysql-test/r/func_time.result: Bug#19844: time_format in Union truncates values show time_format() handles %H and %k correctly four > 99 hours mysql-test/t/func_time.test: Bug#19844: time_format in Union truncates values show time_format() handles %H and %k correctly four > 99 hours sql/item_timefunc.cc: Bug#19844: time_format in Union truncates values unbreak promises we make about field-length of %H and %k in time_format() so they coincide with the actual range rather than just 0..23. the docs say we must operate outside that range, so we'd better do it right. --- Bug#19844: time_format in Union truncates values unbreak promises we make about field-length of %H and %k in time_format() so they coincide with the actual range rather than just 0..23. the docs say we must operate outside that range, so we'd better do it right. One digit values are padded to two digits with %H, "longer" values are handled correctly up to seven digits including any sign. (clarified comments as per jimw's suggestion.) --- mysql-test/r/func_time.result | 21 +++++++++++++++++++++ mysql-test/t/func_time.test | 20 +++++++++++++++++++- sql/item_timefunc.cc | 6 ++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index d8ba606a558..47a0f83802c 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -695,3 +695,24 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H); +H +120 +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H); +H +120 +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H); +H +05 +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H); +H +5 +End of 4.1 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b8647a281d4..472f3d81d2b 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -368,4 +368,22 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; -# End of 4.1 tests +# +# Bug #19844 time_format in Union truncates values +# + +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H); +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H); +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H); + +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H); + +--echo End of 4.1 tests diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 44d9b422263..febc92e34f6 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1600,14 +1600,12 @@ uint Item_func_date_format::format_length(const String *format) case 'u': /* week (00..52), where week starts with Monday */ case 'V': /* week 1..53 used with 'x' */ case 'v': /* week 1..53 used with 'x', where week starts with Monday */ - case 'H': /* hour (00..23) */ case 'y': /* year, numeric, 2 digits */ case 'm': /* month, numeric */ case 'd': /* day (of the month), numeric */ case 'h': /* hour (01..12) */ case 'I': /* --||-- */ case 'i': /* minutes, numeric */ - case 'k': /* hour ( 0..23) */ case 'l': /* hour ( 1..12) */ case 'p': /* locale's AM or PM */ case 'S': /* second (00..61) */ @@ -1616,6 +1614,10 @@ uint Item_func_date_format::format_length(const String *format) case 'e': /* day (0..31) */ size += 2; break; + case 'k': /* hour ( 0..23) */ + case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */ + size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */ + break; case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */ size += 11; break; From 256ac388eb65ed9fb381d9e743b8cea389a5eb54 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Aug 2006 13:14:26 +0500 Subject: [PATCH 17/52] Bug#7192 Specify --with-collation doesn't work for connections? --with-collation worked only on the server side. Client side ignored this argument, so collation_connection was not properly set (remained latin1_swedish_ci). sql-common/client.c: - Take into account MYSQL_DEFAULT_COLLATION_NAME if character set is not set using mysql_option(), to honor --with-collation argument to configure. - Use default collation for the character set when it's not set using mysql_option(). --- sql-common/client.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index e5bab51ca8a..ff5f1ef150a 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1544,11 +1544,18 @@ C_MODE_START int mysql_init_character_set(MYSQL *mysql) { NET *net= &mysql->net; + const char *default_collation_name; + /* Set character set */ - if (!mysql->options.charset_name && - !(mysql->options.charset_name= + if (!mysql->options.charset_name) + { + default_collation_name= MYSQL_DEFAULT_COLLATION_NAME; + if (!(mysql->options.charset_name= my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME)))) return 1; + } + else + default_collation_name= NULL; { const char *save= charsets_dir; @@ -1556,6 +1563,28 @@ int mysql_init_character_set(MYSQL *mysql) charsets_dir=mysql->options.charset_dir; mysql->charset=get_charset_by_csname(mysql->options.charset_name, MY_CS_PRIMARY, MYF(MY_WME)); + if (mysql->charset && default_collation_name) + { + CHARSET_INFO *collation; + if ((collation= + get_charset_by_name(default_collation_name, MYF(MY_WME)))) + { + if (!my_charset_same(mysql->charset, collation)) + { + my_printf_error(ER_UNKNOWN_ERROR, + "COLLATION %s is not valid for CHARACTER SET %s", + MYF(0), + default_collation_name, mysql->options.charset_name); + mysql->charset= NULL; + } + else + { + mysql->charset= collation; + } + } + else + mysql->charset= NULL; + } charsets_dir= save; } From edc8900bb0d9ea128e38b85d0a936d24fa560ca7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Aug 2006 13:19:44 +0500 Subject: [PATCH 18/52] mysqld --collation-server=xxx --character-set-server=yyy didn't work as expected: collation_server was set not to xxx, but to the default collation of character set "yyy". With different argument order it worked as expected: mysqld --character-set-server=yyy --collation-server=yyy Fix: initializate default_collation_name to 0 when processing --character-set-server only if --collation-server has not been specified in command line. mysql-test/r/ctype_ucs2_def.result: Adding test cast mysql-test/t/ctype_ucs2_def-master.opt: Adding test case mysql-test/t/ctype_ucs2_def.test: Adding test case sql/mysqld.cc: Don't clear default_collation_name when processing --character-set-server if collation has already been specified using --collation-server --- mysql-test/r/ctype_ucs2_def.result | 3 +++ mysql-test/t/ctype_ucs2_def-master.opt | 2 +- mysql-test/t/ctype_ucs2_def.test | 5 +++++ sql/mysqld.cc | 6 ++++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ctype_ucs2_def.result b/mysql-test/r/ctype_ucs2_def.result index 897dbac251c..2f9dc4ae616 100644 --- a/mysql-test/r/ctype_ucs2_def.result +++ b/mysql-test/r/ctype_ucs2_def.result @@ -1,3 +1,6 @@ +show variables like 'collation_server'; +Variable_name Value +collation_server ucs2_unicode_ci show variables like "%character_set_ser%"; Variable_name Value character_set_server ucs2 diff --git a/mysql-test/t/ctype_ucs2_def-master.opt b/mysql-test/t/ctype_ucs2_def-master.opt index 1f884ff1d67..a0b5b061860 100644 --- a/mysql-test/t/ctype_ucs2_def-master.opt +++ b/mysql-test/t/ctype_ucs2_def-master.opt @@ -1 +1 @@ ---default-character-set=ucs2 --default-collation=ucs2_unicode_ci +--default-collation=ucs2_unicode_ci --default-character-set=ucs2 diff --git a/mysql-test/t/ctype_ucs2_def.test b/mysql-test/t/ctype_ucs2_def.test index fb174d551cf..00f636d79dc 100644 --- a/mysql-test/t/ctype_ucs2_def.test +++ b/mysql-test/t/ctype_ucs2_def.test @@ -1,3 +1,8 @@ +# +# MySQL Bug#15276: MySQL ignores collation-server +# +show variables like 'collation_server'; + # # Bug#18004 Connecting crashes server when default charset is UCS2 # diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 74c7b1a4e4c..bf83772a8d8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -378,6 +378,7 @@ key_map key_map_full(0); // Will be initialized later const char *opt_date_time_formats[3]; +char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME; char *language_ptr, *default_collation_name, *default_character_set_name; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; struct passwd *user_info; @@ -5936,7 +5937,7 @@ static void mysql_init_variables(void) /* Variables in libraries */ charsets_dir= 0; default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME; - default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME; + default_collation_name= compiled_default_collation_name; sys_charset_system.value= (char*) system_charset_info->csname; @@ -6091,7 +6092,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), strmake(mysql_home,argument,sizeof(mysql_home)-1); break; case 'C': - default_collation_name= 0; + if (default_collation_name == compiled_default_collation_name) + default_collation_name= 0; break; case 'l': opt_log=1; From 3212b399a85b3c985655b950443fe09133c0922c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Aug 2006 17:09:19 -0600 Subject: [PATCH 19/52] Bug #20536: md5() with GROUP BY and UCS2 return different results on myisam/innodb Make the encryption functions MD5(), SHA1() and ENCRYPT() return binary results. Make MAKE_SET() and EXPORT_SET() use the correct character set for their default separator strings. mysql-test/r/ctype_ucs.result: Add tests for bug #20536. mysql-test/t/ctype_ucs.test: Add tests for bug #20536. Tests showing correct behavior for MD5(), SHA1(), MAKE_SET() and EXPORT_SET(). Also, tests showing incorrect behavior, which will remain "Won't fix", for PASSWORD(), OLD_PASSWORD(), ENCRYPT() and QUOTE(). sql/item_strfunc.cc: Make the encryption functions MD5(), SHA1() and ENCRYPT() return binary results. Make MAKE_SET() and EXPORT_SET() use the correct character set for their default separator strings. sql/item_strfunc.h: Make the encryption functions MD5(), SHA1() and ENCRYPT() return binary results. --- mysql-test/r/ctype_ucs.result | 43 +++++++++++++++++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 41 ++++++++++++++++++++++++++++++++- sql/item_strfunc.cc | 14 ++++++++---- sql/item_strfunc.h | 26 +++++++++++++++++---- 4 files changed, 115 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index bcf9cc77519..3a65287ffc5 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -722,3 +722,46 @@ id MIN(s) 1 ZZZ 2 ZZZ DROP TABLE t1; +drop table if exists bug20536; +set names latin1; +create table bug20536 (id bigint not null auto_increment primary key, name +varchar(255) character set ucs2 not null); +insert into `bug20536` (`id`,`name`) values (1, _latin1 x'74657374311a'), (2, "'test\\_2'"); +select md5(name) from bug20536; +md5(name) +3417d830fe24ffb2f81a28e54df2d1b3 +48d95db0d8305c2fe11548a3635c9385 +select sha1(name) from bug20536; +sha1(name) +72228a6d56efb7a89a09543068d5d8fa4c330881 +677d4d505355eb5b0549b865fcae4b7f0c28aef5 +select make_set(3, name, upper(name)) from bug20536; +make_set(3, name, upper(name)) +test1,TEST1 +'test\_2','TEST\_2' +select export_set(5, name, upper(name)) from bug20536; +export_set(5, name, upper(name)) +test1,TEST1,test1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1 +'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2' +select export_set(5, name, upper(name), ",", 5) from bug20536; +export_set(5, name, upper(name), ",", 5) +test1,TEST1,test1,TEST1,TEST1 +'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2' +select password(name) from bug20536; +password(name) +???????????????????? +???????????????????? +select old_password(name) from bug20536; +old_password(name) +???????? +???????? +select encrypt(name, 'SALT') from bug20536; +encrypt(name, 'SALT') +SA5pDi1UPZdys +SA5pDi1UPZdys +select quote(name) from bug20536; +quote(name) +?????????? +???????????????? +drop table bug20536; +End of 4.1 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index a4d4d1846a7..0ad38d98403 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -463,4 +463,43 @@ INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ'); SELECT id, MIN(s) FROM t1 GROUP BY id; DROP TABLE t1; -# End of 4.1 tests + +# +# Bug #20536: md5() with GROUP BY and UCS2 return different results on myisam/innodb +# + +--disable_warnings +drop table if exists bug20536; +--enable_warnings + +set names latin1; +create table bug20536 (id bigint not null auto_increment primary key, name +varchar(255) character set ucs2 not null); +insert into `bug20536` (`id`,`name`) values (1, _latin1 x'74657374311a'), (2, "'test\\_2'"); +select md5(name) from bug20536; +select sha1(name) from bug20536; +select make_set(3, name, upper(name)) from bug20536; +select export_set(5, name, upper(name)) from bug20536; +select export_set(5, name, upper(name), ",", 5) from bug20536; + +# Some broken functions: add these tests just to document current behavior. + +# PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would +# not be backwards compatible in all cases, so it's best to leave it alone +select password(name) from bug20536; +select old_password(name) from bug20536; + +# ENCRYPT relies on OS function crypt() which takes a NUL-terminated string; it +# doesn't return good results for strings with embedded 0 bytes. It won't be +# fixed unless we choose to re-implement the crypt() function ourselves to take +# an extra size_t string_length argument. +select encrypt(name, 'SALT') from bug20536; + +# QUOTE doesn't work with UCS2 data. It would require a total rewrite +# of Item_func_quote::val_str(), which isn't worthwhile until UCS2 is +# supported fully as a client character set. +select quote(name) from bug20536; + +drop table bug20536; + +--echo End of 4.1 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7bc7956283b..56a31d074ac 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -88,6 +88,7 @@ String *Item_func_md5::val_str(String *str) { DBUG_ASSERT(fixed == 1); String * sptr= args[0]->val_str(str); + str->set_charset(&my_charset_bin); if (sptr) { my_MD5_CTX context; @@ -134,6 +135,7 @@ String *Item_func_sha::val_str(String *str) { DBUG_ASSERT(fixed == 1); String * sptr= args[0]->val_str(str); + str->set_charset(&my_charset_bin); if (sptr) /* If we got value different from NULL */ { SHA1_CONTEXT context; /* Context used to generate SHA1 hash */ @@ -1529,7 +1531,7 @@ String *Item_func_encrypt::val_str(String *str) null_value= 1; return 0; } - str->set(tmp,(uint) strlen(tmp),res->charset()); + str->set(tmp, (uint) strlen(tmp), &my_charset_bin); str->copy(); pthread_mutex_unlock(&LOCK_crypt); return str; @@ -1926,7 +1928,7 @@ String *Item_func_make_set::val_str(String *str) return &my_empty_string; result= &tmp_str; } - if (tmp_str.append(',') || tmp_str.append(*res)) + if (tmp_str.append(",", 1, &my_charset_bin) || tmp_str.append(*res)) return &my_empty_string; } } @@ -2592,8 +2594,12 @@ String* Item_func_export_set::val_str(String* str) } break; case 3: - sep_buf.set(",", 1, default_charset()); - sep = &sep_buf; + { + /* errors is not checked - assume "," can always be converted */ + uint errors; + sep_buf.copy(",", 1, &my_charset_bin, collation.collation, &errors); + sep = &sep_buf; + } break; default: DBUG_ASSERT(0); // cannot happen diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index f800c17182b..d3e2d24099b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -41,7 +41,10 @@ class Item_func_md5 :public Item_str_func { String tmp_value; public: - Item_func_md5(Item *a) :Item_str_func(a) {} + Item_func_md5(Item *a) :Item_str_func(a) + { + collation.set(&my_charset_bin); + } String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } @@ -51,7 +54,10 @@ public: class Item_func_sha :public Item_str_func { public: - Item_func_sha(Item *a) :Item_str_func(a) {} + Item_func_sha(Item *a) :Item_str_func(a) + { + collation.set(&my_charset_bin); + } String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } @@ -306,9 +312,21 @@ public: class Item_func_encrypt :public Item_str_func { String tmp_value; + + /* Encapsulate common constructor actions */ + void constructor_helper() + { + collation.set(&my_charset_bin); + } public: - Item_func_encrypt(Item *a) :Item_str_func(a) {} - Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {} + Item_func_encrypt(Item *a) :Item_str_func(a) + { + constructor_helper(); + } + Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) + { + constructor_helper(); + } String *val_str(String *); void fix_length_and_dec() { maybe_null=1; max_length = 13; } const char *func_name() const { return "ecrypt"; } From bb3efba00c5cac5a8b26eee129a512ab24622adb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Aug 2006 10:54:24 +0500 Subject: [PATCH 20/52] Restore alphabetical order of the system variables. sql/set_var.cc: Restore alphabetical order of the system variables. - moved the have_merge_engine variable. --- sql/set_var.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index 1d994f1c98f..4acedc7bcbd 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -738,8 +738,8 @@ struct show_var_st init_vars[]= { {"have_geometry", (char*) &have_geometry, SHOW_HAVE}, {"have_innodb", (char*) &have_innodb, SHOW_HAVE}, {"have_isam", (char*) &have_isam, SHOW_HAVE}, - {"have_ndbcluster", (char*) &have_ndbcluster, SHOW_HAVE}, {"have_merge_engine", (char*) &have_merge_db, SHOW_HAVE}, + {"have_ndbcluster", (char*) &have_ndbcluster, SHOW_HAVE}, {"have_openssl", (char*) &have_openssl, SHOW_HAVE}, {"have_query_cache", (char*) &have_query_cache, SHOW_HAVE}, {"have_raid", (char*) &have_raid, SHOW_HAVE}, From a756f762e868c73ac9e90ebadfd51f1c3d905499 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Aug 2006 12:59:54 +0500 Subject: [PATCH 21/52] Make the heap_btree test repeatable. mysql-test/r/heap_btree.result: Make the heap_btree test repeatable. - 'order by' added where we don't use the 'a' index. mysql-test/t/heap_btree.test: Make the heap_btree test repeatable. - 'order by' added where we don't use the 'a' index. --- mysql-test/r/heap_btree.result | 14 +++++++------- mysql-test/t/heap_btree.test | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index 91c3ec65a13..e6492e90b80 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -255,27 +255,27 @@ a 3 3 delete from t1 where a < 4; -select a from t1; +select a from t1 order by a; a insert into t1 values (2), (2), (2), (1), (1), (3), (3), (3), (3); select a from t1 where a > 4; a delete from t1 where a > 4; -select a from t1; +select a from t1 order by a; a -3 -3 1 -3 -3 1 2 2 2 +3 +3 +3 +3 select a from t1 where a > 3; a delete from t1 where a >= 2; -select a from t1; +select a from t1 order by a; a 1 1 diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test index f510f97fe9b..9aa820becd9 100644 --- a/mysql-test/t/heap_btree.test +++ b/mysql-test/t/heap_btree.test @@ -172,14 +172,14 @@ create table t1(a int not null, key using btree(a)) engine=heap; insert into t1 values (2), (2), (2), (1), (1), (3), (3), (3), (3); select a from t1 where a > 2; delete from t1 where a < 4; -select a from t1; +select a from t1 order by a; insert into t1 values (2), (2), (2), (1), (1), (3), (3), (3), (3); select a from t1 where a > 4; delete from t1 where a > 4; -select a from t1; +select a from t1 order by a; select a from t1 where a > 3; delete from t1 where a >= 2; -select a from t1; +select a from t1 order by a; drop table t1; --echo End of 4.1 tests From f6d7985a5b4a5c7d94cb04ba003dfa411cf0d3f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Aug 2006 17:05:02 +0500 Subject: [PATCH 22/52] BUG#18874 - Setting myisam_repair_threads > 1, index cardinality always 1 Fixed by moving update_key_parts() down to be after write_index(). myisam/sort.c: write_index() collects index statistic which is further used in update_key_parts(). Thus update_key_parts() must be called after write_index(). mysql-test/r/repair.result: Test case for bug#18874. mysql-test/t/repair.test: Test case for bug#18874. --- myisam/sort.c | 12 +++++------- mysql-test/r/repair.result | 11 +++++++++++ mysql-test/t/repair.test | 11 +++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/myisam/sort.c b/myisam/sort.c index 96b55d599c8..1a3dc147cd9 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -480,13 +480,6 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) if (!got_error) { share->state.key_map|=(ulonglong) 1 << sinfo->key; - if (param->testflag & T_STATISTICS) - update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique, - param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? - sinfo->notnull: NULL, - (ulonglong) info->state->records); - - if (!sinfo->buffpek.elements) { if (param->testflag & T_VERBOSE) @@ -498,6 +491,11 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) flush_ft_buf(sinfo) || flush_pending_blocks(sinfo)) got_error=1; } + if (!got_error && param->testflag & T_STATISTICS) + update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique, + param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? + sinfo->notnull: NULL, + (ulonglong) info->state->records); } my_free((gptr) sinfo->sort_keys,MYF(0)); my_free(mi_get_rec_buff_ptr(info, sinfo->rec_buff), diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index dbca5c39a6c..e0849452399 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -37,3 +37,14 @@ Table Op Msg_type Msg_text test.t1 repair warning Number of rows changed from 0 to 1 test.t1 repair status OK drop table t1; +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES(1),(2),(3),(4),(5); +SET myisam_repair_threads=2; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SHOW INDEX FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A 5 NULL NULL YES BTREE +SET myisam_repair_threads=@@global.myisam_repair_threads; +DROP TABLE t1; diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index 5e39e0b6a50..f086d5b0c2a 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -34,4 +34,15 @@ repair table t1; repair table t1 use_frm; drop table t1; +# +# BUG#18874 - Setting myisam_repair_threads > 1, index cardinality always 1 +# +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES(1),(2),(3),(4),(5); +SET myisam_repair_threads=2; +REPAIR TABLE t1; +SHOW INDEX FROM t1; +SET myisam_repair_threads=@@global.myisam_repair_threads; +DROP TABLE t1; + # End of 4.1 tests From 32741794a3d50038f66871b49dfc3c26f4285e19 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Aug 2006 20:01:19 +0400 Subject: [PATCH 23/52] BUG#9678: Client library hangs after network communication failure Socket timeouts in client library were used only on Windows. The solution is to use socket timeouts in client library on all systems were they are supported. No test case is provided because it is impossible to simulate network failure in current test suit. sql/net_serv.cc: Retry indefinitely only if got EINTR. vio/viosocket.c: Set socket timeouts on POSIX systems as well as on Windows. --- sql/net_serv.cc | 2 +- vio/viosocket.c | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 93fa7ac938c..08184537896 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -747,7 +747,7 @@ my_real_read(NET *net, ulong *complen) #endif /* EXTRA_DEBUG */ } #if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) - if (vio_should_retry(net->vio)) + if (vio_errno(net->vio) == SOCKET_EINTR) { DBUG_PRINT("warning",("Interrupted read. Retrying...")); continue; diff --git a/vio/viosocket.c b/vio/viosocket.c index 8d4c2387632..847e036d3b2 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -333,16 +333,30 @@ my_bool vio_poll_read(Vio *vio,uint timeout) } -void vio_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) +void vio_timeout(Vio *vio, uint which, uint timeout) { +/* TODO: some action should be taken if socket timeouts are not supported. */ +#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) + #ifdef __WIN__ - ulong wait_timeout= (ulong) timeout * 1000; - (void) setsockopt(vio->sd, SOL_SOCKET, - which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout, - sizeof(wait_timeout)); -#endif /* __WIN__ */ + + /* Windows expects time in milliseconds as int. */ + int wait_timeout= (int) timeout * 1000; + +#else /* ! __WIN__ */ + + /* POSIX specifies time as struct timeval. */ + struct timeval wait_timeout; + wait_timeout.tv_sec= timeout; + wait_timeout.tv_usec= 0; + +#endif /* ! __WIN__ */ + + /* TODO: return value should be checked. */ + (void) setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO, + (char*) &wait_timeout, sizeof(wait_timeout)); + +#endif /* defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) */ } From fe3dee0621a23136c33c6b7085a6846353b1f797 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Aug 2006 15:24:07 +0500 Subject: [PATCH 24/52] Fix for bug #20695: Charset introducer overrides charset definition for column. - if there are two character set definitions in the column declaration, we replace the first one with the second one as we store both in the LEX->charset slot. Add a separate slot to the LEX structure to store underscore charset. - convert default values to the column charset of STRING, VARSTRING fields if necessary as well. mysql-test/r/ctype_recoding.result: Fix for bug #20695: Charset introducer overrides charset definition for column. - test result. mysql-test/t/ctype_recoding.test: Fix for bug #20695: Charset introducer overrides charset definition for column. - test case. sql/sql_lex.cc: Fix for bug #20695: Charset introducer overrides charset definition for column. - LEX->underscore_charset introduced to store UNDERSCORE_CHARSET sql/sql_lex.h: Fix for bug #20695: Charset introducer overrides charset definition for column. - LEX->underscore_charset introduced to store UNDERSCORE_CHARSET sql/sql_table.cc: Fix for bug #20695: Charset introducer overrides charset definition for column. - convert default values to the column charset of VARSTRING, STRING, ENUM, SET fields if necessary. sql/sql_yacc.yy: Fix for bug #20695: Charset introducer overrides charset definition for column. - LEX->underscore_charset introduced to store UNDERSCORE_CHARSET --- mysql-test/r/ctype_recoding.result | 11 ++++++ mysql-test/t/ctype_recoding.test | 12 ++++++ sql/sql_lex.cc | 5 ++- sql/sql_lex.h | 2 +- sql/sql_table.cc | 63 ++++++++++++++++-------------- sql/sql_yacc.yy | 4 +- 6 files changed, 63 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 0b5c6f8974c..2daa2d5ba0b 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -247,3 +247,14 @@ lpad(c1,3,' select rpad(c1,3,''), rpad('',3,c1) from t1; rpad(c1,3,'') rpad('',3,c1) +drop table t1; +set names koi8r; +create table t1(a char character set cp1251 default _koi8r 0xFF); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(1) character set cp1251 default '' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1(a char character set latin1 default _cp1251 0xFF); +ERROR 42000: Invalid default value for 'a' diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 5648cea7fd3..ddaaa7b9e4f 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -186,5 +186,17 @@ select rpad(c1,3,' # TODO #select case c1 when '' then '' when '' then '' else 'c' end from t1; #select export_set(5,c1,''), export_set(5,'',c1) from t1; +drop table t1; + +# +# Bug 20695: problem with field default value's character set +# + +set names koi8r; +create table t1(a char character set cp1251 default _koi8r 0xFF); +show create table t1; +drop table t1; +--error 1067 +create table t1(a char character set latin1 default _cp1251 0xFF); # End of 4.1 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index fb9a765f12c..dfe406c351e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -643,8 +643,9 @@ int yylex(void *arg, void *yythd) */ if ((yylval->lex_str.str[0]=='_') && - (lex->charset=get_charset_by_csname(yylval->lex_str.str+1, - MY_CS_PRIMARY,MYF(0)))) + (lex->underscore_charset= + get_charset_by_csname(yylval->lex_str.str + 1, + MY_CS_PRIMARY,MYF(0)))) return(UNDERSCORE_CHARSET); return(result_state); // IDENT or IDENT_QUOTED diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 35f02db6cf9..12f89202e2d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -613,7 +613,7 @@ typedef struct st_lex LEX_USER *grant_user; gptr yacc_yyss,yacc_yyvs; THD *thd; - CHARSET_INFO *charset; + CHARSET_INFO *charset, *underscore_charset; List col_list; List ref_list; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 631d2d89bbb..a5cb0d45664 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -516,6 +516,40 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(-1); } + /* + Convert the default value character + set into the column character set if necessary. + */ + if (sql_field->def && + savecs != sql_field->def->collation.collation && + (sql_field->sql_type == FIELD_TYPE_VAR_STRING || + sql_field->sql_type == FIELD_TYPE_STRING || + sql_field->sql_type == FIELD_TYPE_SET || + sql_field->sql_type == FIELD_TYPE_ENUM)) + { + Item_arena backup_arena; + bool need_to_change_arena= + !thd->current_arena->is_conventional_execution(); + if (need_to_change_arena) + { + /* Assert that we don't do that at every PS execute */ + DBUG_ASSERT(thd->current_arena->is_first_stmt_execute()); + thd->set_n_backup_item_arena(thd->current_arena, &backup_arena); + } + + sql_field->def= sql_field->def->safe_charset_converter(savecs); + + if (need_to_change_arena) + thd->restore_backup_item_arena(thd->current_arena, &backup_arena); + + if (sql_field->def == NULL) + { + /* 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 || sql_field->sql_type == FIELD_TYPE_ENUM) { @@ -580,35 +614,6 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->interval_list.empty(); // Don't need interval_list anymore } - /* - Convert the default value from client character - set into the column character set if necessary. - */ - if (sql_field->def && cs != sql_field->def->collation.collation) - { - Item_arena backup_arena; - bool need_to_change_arena= - !thd->current_arena->is_conventional_execution(); - if (need_to_change_arena) - { - /* Asser that we don't do that at every PS execute */ - DBUG_ASSERT(thd->current_arena->is_first_stmt_execute()); - thd->set_n_backup_item_arena(thd->current_arena, &backup_arena); - } - - sql_field->def= sql_field->def->safe_charset_converter(cs); - - if (need_to_change_arena) - thd->restore_backup_item_arena(thd->current_arena, &backup_arena); - - if (sql_field->def == NULL) - { - /* 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) { if (sql_field->def != NULL) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..efd83549312 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4896,7 +4896,7 @@ text_literal: | NCHAR_STRING { $$= new Item_string($1.str,$1.length,national_charset_info); } | UNDERSCORE_CHARSET TEXT_STRING - { $$ = new Item_string($2.str,$2.length,Lex->charset); } + { $$ = new Item_string($2.str,$2.length,Lex->underscore_charset); } | text_literal TEXT_STRING_literal { ((Item_string*) $1)->append($2.str,$2.length); } ; @@ -4963,7 +4963,7 @@ literal: (String*) 0; $$= new Item_string(str ? str->ptr() : "", str ? str->length() : 0, - Lex->charset); + Lex->underscore_charset); } | DATE_SYM text_literal { $$ = $2; } | TIME_SYM text_literal { $$ = $2; } From 87b7363c5ca7dc0f1165a9460cbfd28b0ff23a61 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Aug 2006 13:12:27 +0200 Subject: [PATCH 25/52] ndb_lock.test, ndb_lock.result: bug #18184 SELECT ... FOR UPDATE does not work..: New test case ha_ndbcluster.h, ha_ndbcluster.cc, NdbConnection.hpp: Fix for bug #21059 Server crashes on join query with large dataset with NDB tables: Releasing operation for each intermediate batch, before next call to trans->execute(NoCommit); mysql-test/r/ndb_lock.result: bug #18184 SELECT ... FOR UPDATE does not work..: New test case mysql-test/t/ndb_lock.test: bug #18184 SELECT ... FOR UPDATE does not work..: New test case ndb/include/ndbapi/NdbConnection.hpp: Fix for bug #21059 Server crashes on join query with large dataset with NDB tables: Releasing operation for each intermediate batch, before next call to trans->execute(NoCommit); sql/ha_ndbcluster.cc: Fix for bug #21059 Server crashes on join query with large dataset with NDB tables: Releasing operation for each intermediate batch, before next call to trans->execute(NoCommit); sql/ha_ndbcluster.h: Fix for bug #21059 Server crashes on join query with large dataset with NDB tables: Releasing operation for each intermediate batch, before next call to trans->execute(NoCommit); --- mysql-test/r/ndb_lock.result | 15 +++++++++--- mysql-test/t/ndb_lock.test | 15 ++++++++++-- ndb/include/ndbapi/NdbConnection.hpp | 4 +++- sql/ha_ndbcluster.cc | 34 ++++++++++++++++++++++++++++ sql/ha_ndbcluster.h | 2 ++ 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ndb_lock.result b/mysql-test/r/ndb_lock.result index 875dcd775e6..c7413949f42 100644 --- a/mysql-test/r/ndb_lock.result +++ b/mysql-test/r/ndb_lock.result @@ -64,17 +64,26 @@ pk u o insert into t1 values (1,1,1); drop table t1; create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb; -insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3); +insert into t1 values (1,'one',1); begin; select * from t1 where x = 1 for update; x y z 1 one 1 begin; +select * from t1 where x = 1 for update; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +rollback; +insert into t1 values (2,'two',2),(3,"three",3); +begin; +select * from t1 where x = 1 for update; +x y z +1 one 1 +select * from t1 where x = 1 for update; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction select * from t1 where x = 2 for update; x y z 2 two 2 -select * from t1 where x = 1 for update; -ERROR HY000: Lock wait timeout exceeded; try restarting transaction rollback; commit; begin; diff --git a/mysql-test/t/ndb_lock.test b/mysql-test/t/ndb_lock.test index e8f7c57ac96..3804782b150 100644 --- a/mysql-test/t/ndb_lock.test +++ b/mysql-test/t/ndb_lock.test @@ -73,7 +73,7 @@ drop table t1; create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb; -insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3); +insert into t1 values (1,'one',1); # PK access connection con1; @@ -82,11 +82,22 @@ select * from t1 where x = 1 for update; connection con2; begin; -select * from t1 where x = 2 for update; --error 1205 select * from t1 where x = 1 for update; rollback; +connection con1; +rollback; +insert into t1 values (2,'two',2),(3,"three",3); +begin; +select * from t1 where x = 1 for update; + +connection con2; +--error 1205 +select * from t1 where x = 1 for update; +select * from t1 where x = 2 for update; +rollback; + connection con1; commit; diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 75c3f80121d..c367e156f08 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -163,7 +163,8 @@ class NdbConnection friend class NdbIndexOperation; friend class NdbIndexScanOperation; friend class NdbBlob; - + friend class ha_ndbcluster; + public: /** @@ -675,6 +676,7 @@ private: // optim: any blobs bool theBlobFlag; Uint8 thePendingBlobOps; + inline bool hasBlobOperation() { return theBlobFlag; } static void sendTC_COMMIT_ACK(NdbApiSignal *, Uint32 transId1, Uint32 transId2, diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 10240e597bf..e4c20de2390 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -161,6 +161,7 @@ int execute_no_commit(ha_ndbcluster *h, NdbConnection *trans) if (m_batch_execute) return 0; #endif + h->release_completed_operations(trans); return trans->execute(NoCommit,AbortOnError,h->m_force_send); } @@ -194,6 +195,7 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbConnection *trans) if (m_batch_execute) return 0; #endif + h->release_completed_operations(trans); return trans->execute(NoCommit, AO_IgnoreError,h->m_force_send); } @@ -2747,6 +2749,25 @@ int ha_ndbcluster::close_scan() if (!cursor) DBUG_RETURN(1); + if (m_lock_tuple) + { + /* + Lock level m_lock.type either TL_WRITE_ALLOW_WRITE + (SELECT FOR UPDATE) or TL_READ_WITH_SHARED_LOCKS (SELECT + LOCK WITH SHARE MODE) and row was not explictly unlocked + with unlock_row() call + */ + NdbOperation *op; + // Lock row + DBUG_PRINT("info", ("Keeping lock on scanned row")); + + if (!(op= m_active_cursor->lockTuple())) + { + m_lock_tuple= false; + ERR_RETURN(trans->getNdbError()); + } + m_ops_pending++; + } m_lock_tuple= false; if (m_ops_pending) { @@ -5350,6 +5371,19 @@ int ha_ndbcluster::write_ndb_file() DBUG_RETURN(error); } +void +ha_ndbcluster::release_completed_operations(NdbConnection *trans) +{ + if (trans->hasBlobOperation()) + { + /* We are reading/writing BLOB fields, + releasing operation records is unsafe + */ + return; + } + trans->releaseCompletedOperations(); +} + int ndbcluster_show_status(THD* thd) { diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 313e497f9b5..4a53b4007fe 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -262,6 +262,8 @@ class ha_ndbcluster: public handler void no_uncommitted_rows_init(THD *); void no_uncommitted_rows_reset(THD *); + void release_completed_operations(NdbConnection*); + friend int execute_no_commit(ha_ndbcluster*, NdbConnection*); friend int execute_commit(ha_ndbcluster*, NdbConnection*); friend int execute_no_commit_ie(ha_ndbcluster*, NdbConnection*); From 9907e970aea28ce186e110084c3a4f2d6ac0c602 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Aug 2006 20:33:14 +0400 Subject: [PATCH 26/52] BUG#21077: Possible crash caused by invalid sequence of handler::* calls: The crash was caused by invalid sequence of handler::** calls: ha_smth->index_init(); ha_smth->index_next_same(); (2) (2) is an invalid call as it was not preceeded by any 'scan setup' call like index_first() or index_read(). The cause was that QUICK_SELECT::reset() didn't "fully reset" the quick select- current QUICK_RANGE wasn't forgotten, and quick select might attempt to continue reading the range, which would result in the above mentioned invalid sequence of handler calls. 5.x versions are not affected by the bug - they already have the missing "range=NULL" clause. mysql-test/r/innodb_mysql.result: Testcase for BUG#21077 mysql-test/t/innodb_mysql.test: Testcase for BUG#21077 sql/opt_range.h: BUG#21077: Possible crash caused by invalid sequence of handler::* calls: - Make QUICK_SELECT::reset() really reset the quick select --- mysql-test/r/innodb_mysql.result | 21 +++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 27 +++++++++++++++++++++++++++ sql/opt_range.h | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 920d7aa42ce..ee4c114087d 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -83,3 +83,24 @@ b a 3 3 3 3 DROP TABLE t1, t2, t3; +CREATE TABLE `t1` (`id1` INT) ; +INSERT INTO `t1` (`id1`) VALUES (1),(5),(2); +CREATE TABLE `t2` ( +`id1` INT, +`id2` INT NOT NULL, +`id3` INT, +`id4` INT NOT NULL, +UNIQUE (`id2`,`id4`), +KEY (`id1`) +) ENGINE=InnoDB; +INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES +(1,1,1,0), +(1,1,2,1), +(5,1,2,2), +(6,1,2,3), +(1,2,2,2), +(1,2,1,1); +SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2); +id1 +2 +DROP TABLE t1, t2; diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 0b789e1a6d5..a5fe248604f 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -90,3 +90,30 @@ SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) ORDER BY t1.b LIMIT 5; DROP TABLE t1, t2, t3; + + +# BUG#21077 (The testcase is not deterministic so correct execution doesn't +# prove anything) For proof one should track if sequence of ha_innodb::* func +# calls is correct. +CREATE TABLE `t1` (`id1` INT) ; +INSERT INTO `t1` (`id1`) VALUES (1),(5),(2); + +CREATE TABLE `t2` ( + `id1` INT, + `id2` INT NOT NULL, + `id3` INT, + `id4` INT NOT NULL, + UNIQUE (`id2`,`id4`), + KEY (`id1`) +) ENGINE=InnoDB; + +INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES +(1,1,1,0), +(1,1,2,1), +(5,1,2,2), +(6,1,2,3), +(1,2,2,2), +(1,2,1,1); + +SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2); +DROP TABLE t1, t2; diff --git a/sql/opt_range.h b/sql/opt_range.h index 15f0bf02b34..d2f4452a762 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -86,7 +86,7 @@ public: QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0); virtual ~QUICK_SELECT(); - void reset(void) { next=0; it.rewind(); } + void reset(void) { next=0; it.rewind(); range= NULL;} int init() { key_part_info= head->key_info[index].key_part; From 4934231545c994b90517b2c1b4c9b85b4fbe2018 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Aug 2006 13:55:16 -0400 Subject: [PATCH 27/52] Bug#20328 - Correction to test/result for broken Windows build. mysql-test/r/mysql_client.result: Removed OS dependant output. mysql-test/t/mysql_client.test: Re-directed output to a temporary file because the actual output isn't important and was causing a Windows test failure. --- mysql-test/r/mysql_client.result | 44 -------------------------------- mysql-test/t/mysql_client.test | 6 ++--- 2 files changed, 3 insertions(+), 47 deletions(-) diff --git a/mysql-test/r/mysql_client.result b/mysql-test/r/mysql_client.result index 00d7b6df3cf..87d09428ff6 100644 --- a/mysql-test/r/mysql_client.result +++ b/mysql-test/r/mysql_client.result @@ -2,47 +2,3 @@ 1 ERROR 1064 (42000) at line 3: 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 ERROR at line 1: USE must be followed by a database name -? (\?) Synonym for `help'. -clear (\c) Clear command. -connect (\r) Reconnect to the server. Optional arguments are db and host. -delimiter (\d) Set query delimiter. -edit (\e) Edit command with $EDITOR. -ego (\G) Send command to mysql server, display result vertically. -exit (\q) Exit mysql. Same as quit. -go (\g) Send command to mysql server. -help (\h) Display this help. -nopager (\n) Disable pager, print to stdout. -notee (\t) Don't write into outfile. -pager (\P) Set PAGER [to_pager]. Print the query results via PAGER. -print (\p) Print current command. -prompt (\R) Change your mysql prompt. -quit (\q) Quit mysql. -rehash (\#) Rebuild completion hash. -source (\.) Execute an SQL script file. Takes a file name as an argument. -status (\s) Get status information from the server. -system (\!) Execute a system shell command. -tee (\T) Set outfile [to_outfile]. Append everything into given outfile. -use (\u) Use another database. Takes database name as argument. -charset_name(\C) Switch to another charset. Might be needed for processing binlog. -? (\?) Synonym for `help'. -clear (\c) Clear command. -connect (\r) Reconnect to the server. Optional arguments are db and host. -delimiter (\d) Set query delimiter. -edit (\e) Edit command with $EDITOR. -ego (\G) Send command to mysql server, display result vertically. -exit (\q) Exit mysql. Same as quit. -go (\g) Send command to mysql server. -help (\h) Display this help. -nopager (\n) Disable pager, print to stdout. -notee (\t) Don't write into outfile. -pager (\P) Set PAGER [to_pager]. Print the query results via PAGER. -print (\p) Print current command. -prompt (\R) Change your mysql prompt. -quit (\q) Quit mysql. -rehash (\#) Rebuild completion hash. -source (\.) Execute an SQL script file. Takes a file name as an argument. -status (\s) Get status information from the server. -system (\!) Execute a system shell command. -tee (\T) Set outfile [to_outfile]. Append everything into given outfile. -use (\u) Use another database. Takes database name as argument. -charset_name(\C) Switch to another charset. Might be needed for processing binlog. diff --git a/mysql-test/t/mysql_client.test b/mysql-test/t/mysql_client.test index 9cdf5aea64b..b382357dacf 100644 --- a/mysql-test/t/mysql_client.test +++ b/mysql-test/t/mysql_client.test @@ -29,7 +29,7 @@ --exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 # -# Bug #20328: mysql client interprets commands in comments +# Bug #20328: mysql client: dumb about trailing spaces on 'help' command # ---exec echo 'help' | $MYSQL ---exec echo 'help ' | $MYSQL +--exec echo 'help' | $MYSQL > $MYSQLTEST_VARDIR/tmp/bug20328.tmp +--exec echo 'help ' | $MYSQL > $MYSQLTEST_VARDIR/tmp/bug20328.tmp From 8d8fa0e312bd5e0fcb807fd757414d7d9eb4db32 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Aug 2006 14:09:24 -0700 Subject: [PATCH 28/52] Bug #21288: mysqldump segmentation fault when using --where The problem was that the error handling was using a too-small buffer to print the error message generated. We fix this by not using a buffer at all, but by using fprintf() directly. There were also some problems with the error handling in table dumping that was exposed by this fix that were also corrected. client/mysqldump.c: Use fprintf() instead of my_printf_error() to avoid buffer overflow issues. Since ME_BELL wasn't specified, calling my_printf_error() offered no advantage except for adding my_progname, which we just go ahead and do manually. Also, fix the error handling in dumpTable() when queries to get data fail and --force was specified. mysql-test/r/mysqldump.result: Add new results mysql-test/t/mysqldump.test: Add new regression test --- client/mysqldump.c | 16 +++++++++++----- mysql-test/r/mysqldump.result | 27 +++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 8 ++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 58e51b9b955..7f495ccdafb 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -783,8 +783,8 @@ static int get_options(int *argc, char ***argv) static void DBerror(MYSQL *mysql, const char *when) { DBUG_ENTER("DBerror"); - my_printf_error(0,"Got error: %d: %s %s", MYF(0), - mysql_errno(mysql), mysql_error(mysql), when); + fprintf(stderr, "%s: Got error: %d: %s %s\n", my_progname, + mysql_errno(mysql), mysql_error(mysql), when); safe_exit(EX_MYSQLERR); DBUG_VOID_RETURN; } /* DBerror */ @@ -811,9 +811,9 @@ static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res, if (mysql_query(mysql_con, query) || (res && !((*res)= mysql_store_result(mysql_con)))) { - my_printf_error(0, "%s: Couldn't execute '%s': %s (%d)", - MYF(0), my_progname, query, - mysql_error(mysql_con), mysql_errno(mysql_con)); + fprintf(stderr, "%s: Couldn't execute '%s': %s (%d)\n", + my_progname, query, + mysql_error(mysql_con), mysql_errno(mysql_con)); return 1; } return 0; @@ -1705,13 +1705,19 @@ static void dumpTable(uint numFields, char *table) check_io(md_result_file); } if (mysql_query_with_error_report(sock, 0, query)) + { DBerror(sock, "when retrieving data from server"); + goto err; + } if (quick) res=mysql_use_result(sock); else res=mysql_store_result(sock); if (!res) + { DBerror(sock, "when retrieving data from server"); + goto err; + } if (verbose) fprintf(stderr, "-- Retrieving rows...\n"); if (mysql_num_fields(res) != numFields) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 6c5c757061d..721982e11e3 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1557,4 +1557,31 @@ CREATE TABLE `t2` ( /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1, t2, t3; +create table t1 (a int); +mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': 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 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064) +mysqldump: Got error: 1064: 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 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 when retrieving data from server + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t1; End of 4.1 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index e86635e24d0..b0df2bb9db2 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -694,4 +694,12 @@ create table t3(a int); --exec $MYSQL_DUMP --skip-comments --force --no-data test t3 t1 non_existing t2 drop table t1, t2, t3; +# +# Bug #21288: mysqldump segmentation fault when using --where +# +create table t1 (a int); +--error 2 +--exec $MYSQL_DUMP --skip-comments --force test t1 --where='xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 2>&1 +drop table t1; + --echo End of 4.1 tests From c9327bd970e1c21ec160ec4cba8f3cc843ce8246 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Aug 2006 11:48:58 +0200 Subject: [PATCH 29/52] mysql.spec.sh: Added ndb_size.{pl,tmpl} to the RPM install (bug#20426) support-files/mysql.spec.sh: Added ndb_size.{pl,tmpl} to the RPM install (bug#20426) --- support-files/mysql.spec.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 454ec522f0e..befd9f48fed 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -647,6 +647,8 @@ fi %attr(755, root, root) %{_bindir}/ndb_show_tables %attr(755, root, root) %{_bindir}/ndb_test_platform %attr(755, root, root) %{_bindir}/ndb_config +%attr(755, root, root) %{_bindir}/ndb_size.pl +%attr(-, root, root) %{_datadir}/mysql/ndb_size.tmpl %files ndb-extra %defattr(-,root,root,0755) From 2baf2fdf13ac46f6679de735f05aa6a290e95cc7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Aug 2006 16:46:57 +0300 Subject: [PATCH 30/52] Bug #21456: SELECT DISTINCT(x) produces incorrect results when using order by GROUP BY/DISTINCT pruning optimization must be done before ORDER BY optimization because ORDER BY may be removed when GROUP BY/DISTINCT sorts as a side effect, e.g. in SELECT DISTINCT , FROM t1 ORDER BY DISTINCT must be removed before ORDER BY as if done the other way around it will remove both. mysql-test/r/distinct.result: Test for BUG#21456. mysql-test/t/distinct.test: Test for BUG#21456. sql/sql_select.cc: Bug #21456: SELECT DISTINCT(x) produces incorrect results when using order by GROUP BY/DISTINCT pruning optimization must be done before ORDER BY optimization because ORDER BY may be removed when GROUP BY/DISTINCT sorts as a side effect. --- mysql-test/r/distinct.result | 11 +++++++ mysql-test/t/distinct.test | 11 +++++++ sql/sql_select.cc | 60 ++++++++++++++++++------------------ 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index c6c614a5646..6cdf4063291 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -555,3 +555,14 @@ EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 3 DROP TABLE t1,t2; +CREATE TABLE t1 (a int primary key, b int); +INSERT INTO t1 (a,b) values (1,1), (2,3), (3,2); +explain SELECT DISTINCT a, b FROM t1 ORDER BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT DISTINCT a, b FROM t1 ORDER BY b; +a b +1 1 +3 2 +2 3 +DROP TABLE t1; diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index 8ca6f350b8d..2a87427a2b6 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -378,4 +378,15 @@ EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; DROP TABLE t1,t2; +# +# Bug 21456: SELECT DISTINCT(x) produces incorrect results when using order by +# +CREATE TABLE t1 (a int primary key, b int); + +INSERT INTO t1 (a,b) values (1,1), (2,3), (3,2); + +explain SELECT DISTINCT a, b FROM t1 ORDER BY b; +SELECT DISTINCT a, b FROM t1 ORDER BY b; +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 605ef49bb07..a6bba15d70a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -648,6 +648,36 @@ JOIN::optimize() if (!order && org_order) skip_sort_order= 1; } + /* + Check if we can optimize away GROUP BY/DISTINCT. + We can do that if there are no aggregate functions and the + fields in DISTINCT clause (if present) and/or columns in GROUP BY + (if present) contain direct references to all key parts of + an unique index (in whatever order). + Note that the unique keys for DISTINCT and GROUP BY should not + be the same (as long as they are unique). + + The FROM clause must contain a single non-constant table. + */ + if (tables - const_tables == 1 && (group_list || select_distinct) && + !tmp_table_param.sum_func_count) + { + if (group_list && + list_contains_unique_index(join_tab[const_tables].table, + find_field_in_order_list, + (void *) group_list)) + { + group_list= 0; + group= 0; + } + if (select_distinct && + list_contains_unique_index(join_tab[const_tables].table, + find_field_in_item_list, + (void *) &fields_list)) + { + select_distinct= 0; + } + } if (group_list || tmp_table_param.sum_func_count) { if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE) @@ -717,36 +747,6 @@ JOIN::optimize() if (old_group_list && !group_list) select_distinct= 0; } - /* - Check if we can optimize away GROUP BY/DISTINCT. - We can do that if there are no aggregate functions and the - fields in DISTINCT clause (if present) and/or columns in GROUP BY - (if present) contain direct references to all key parts of - an unique index (in whatever order). - Note that the unique keys for DISTINCT and GROUP BY should not - be the same (as long as they are unique). - - The FROM clause must contain a single non-constant table. - */ - if (tables - const_tables == 1 && (group_list || select_distinct) && - !tmp_table_param.sum_func_count) - { - if (group_list && - list_contains_unique_index(join_tab[const_tables].table, - find_field_in_order_list, - (void *) group_list)) - { - group_list= 0; - group= 0; - } - if (select_distinct && - list_contains_unique_index(join_tab[const_tables].table, - find_field_in_item_list, - (void *) &fields_list)) - { - select_distinct= 0; - } - } if (!group_list && group) { order=0; // The output has only one row From 216f20ad0067a2f3f8349cff3f10355f7ea7677e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Aug 2006 15:37:54 -0600 Subject: [PATCH 31/52] Bug #20402: DROP USER failure logged as ERROR rather than WARNING Remove some sql_print_error() calls which were triggered by user error (i.e., not server-level events at all). Also, convert an sql_print_error -> sql_print_information for a non-error server event. sql/slave.cc: Change sql_print_error to sql_print_information for non-error status message. sql/sql_acl.cc: Remove sql_print_error calls for events which are not server errors --- sql/slave.cc | 2 +- sql/sql_acl.cc | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index b2862a437bb..bceeca1055c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2946,7 +2946,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) rli->is_until_satisfied()) { char buf[22]; - sql_print_error("Slave SQL thread stopped because it reached its" + sql_print_information("Slave SQL thread stopped because it reached its" " UNTIL position %s", llstr(rli->until_pos(), buf)); /* Setting abort_slave flag because we do not want additional message about diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 204a38dfb64..5b3e2619d21 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3669,17 +3669,11 @@ int mysql_drop_user(THD *thd, List &list) { if (!(acl_user= check_acl_user(user_name, &counter))) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; No such user", - user_name->user.str, - user_name->host.str); result= -1; continue; } if ((acl_user->access & ~0)) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Global privileges exists", - user_name->user.str, - user_name->host.str); result= -1; continue; } @@ -3700,9 +3694,6 @@ int mysql_drop_user(THD *thd, List &list) } if (counter != acl_dbs.elements) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Database privileges exists", - user_name->user.str, - user_name->host.str); result= -1; continue; } @@ -3723,9 +3714,6 @@ int mysql_drop_user(THD *thd, List &list) } if (counter != column_priv_hash.records) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Table privileges exists", - user_name->user.str, - user_name->host.str); result= -1; continue; } @@ -3791,9 +3779,6 @@ int mysql_revoke_all(THD *thd, List &list) { if (!check_acl_user(lex_user, &counter)) { - sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists", - lex_user->user.str, - lex_user->host.str); result= -1; continue; } From b2a0d025e3f3dc2a8e9ab83634f542d50c4f99a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Aug 2006 18:02:31 -0600 Subject: [PATCH 32/52] Bug #21531: EXPORT_SET() doesn't accept args with coercible character sets - Fix typo in Item_func_export_set::fix_length_and_dec() which caused character set aggregation to fail - Remove default argument from last arg of agg_arg_charsets() function, to reduce potential errors mysql-test/r/func_misc.result: Test EXPORT_SET() with charset coersion (bug #21531) mysql-test/t/func_misc.test: Test EXPORT_SET() with charset coersion (bug #21531) sql/item_func.h: Remove default argument from last arg of agg_arg_charsets() function, to reduce potential errors. sql/item_strfunc.cc: Fix typo in Item_func_export_set::fix_length_and_dec() which caused character set aggregation to fail. --- mysql-test/r/func_misc.result | 4 ++++ mysql-test/t/func_misc.test | 7 ++++++- sql/item_func.h | 3 +-- sql/item_strfunc.cc | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 8bcdd8b7cbc..adf2035173f 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -93,3 +93,7 @@ SELECT IS_USED_LOCK('bug16501'); IS_USED_LOCK('bug16501') NULL DROP TABLE t1; +select export_set(3, _latin1'foo', _utf8'bar', ',', 4); +export_set(3, _latin1'foo', _utf8'bar', ',', 4) +foo,foo,bar,bar +End of 4.1 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index e2641f8d6cd..a7dc9e7c966 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -83,4 +83,9 @@ connection default; DROP TABLE t1; -# End of 4.1 tests +# +# Bug #21531: EXPORT_SET() doesn't accept args with coercible character sets +# +select export_set(3, _latin1'foo', _utf8'bar', ',', 4); + +--echo End of 4.1 tests diff --git a/sql/item_func.h b/sql/item_func.h index 51f9d3fb36f..aaf74e4f7af 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -156,8 +156,7 @@ public: return agg_item_collations_for_comparison(c, func_name(), items, nitems, flags); } - bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, - uint flags= 0) + bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, uint flags) { return agg_item_charsets(c, func_name(), items, nitems, flags); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 56a31d074ac..a43f8b5a22a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2624,8 +2624,8 @@ void Item_func_export_set::fix_length_and_dec() uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; - if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1), - MY_COLL_ALLOW_CONV) + if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1, + MY_COLL_ALLOW_CONV)) return; } From 5d82bec5b880a20d537b9c84b9353ae5607bac1d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Aug 2006 07:14:46 +0200 Subject: [PATCH 33/52] ndb - bug#21800 read TransactionDeadlockTimeout (for scans) to cater for insane settings ndb/src/ndbapi/NdbScanOperation.cpp: read TransactionDeadlockTimeout to cater for insane settings --- ndb/src/ndbapi/NdbScanOperation.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 0a39651ce28..469231512f5 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -504,6 +504,8 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend) idx = m_current_api_receiver; last = m_api_receivers_count; + + Uint32 timeout = tp->m_waitfor_timeout; do { if(theError.code){ @@ -531,7 +533,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend) */ theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { continue; } else { @@ -1372,6 +1374,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, return -1; Uint32 seq = theNdbCon->theNodeSequence; Uint32 nodeId = theNdbCon->theDBnode; + Uint32 timeout = tp->m_waitfor_timeout; if(seq == tp->getNodeSequence(nodeId) && !send_next_scan_ordered(s_idx, forceSend)){ Uint32 tmp = m_sent_receivers_count; @@ -1379,7 +1382,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed, while(m_sent_receivers_count > 0 && !theError.code){ theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) { continue; } @@ -1520,6 +1523,8 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ return -1; } + Uint32 timeout = tp->m_waitfor_timeout; + /** * Wait for outstanding */ @@ -1527,7 +1532,7 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ { theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); switch(return_code){ case 0: break; @@ -1597,7 +1602,7 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){ { theNdb->theImpl->theWaiter.m_node = nodeId; theNdb->theImpl->theWaiter.m_state = WAIT_SCAN; - int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT); + int return_code = theNdb->receiveResponse(3*timeout); switch(return_code){ case 0: break; From c74c8195330ff1e7b3274f6c78d968bf026e5037 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Aug 2006 19:14:36 +0400 Subject: [PATCH 34/52] Bug #16255: Subquery in WHERE (the cset by Georgi Kodinov) Must not use Item_direct_ref in HAVING because it points to the new value (witch is not yet calculated for the first row). mysql-test/r/subselect.result: Bug #16255: Subquery in where - test case mysql-test/t/subselect.test: Bug #16255: Subquery in where - test case sql/item_subselect.cc: Bug #16255: Subquery in where Must not use Item_direct_ref in HAVING because it points to the new value (witch is not yet calculated for the first row). --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/t/subselect.test | 12 ++++++++++++ sql/item_subselect.cc | 10 +++++----- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e84c3957760 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,3 +2895,14 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES(26, 1), (48, 2); +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); +a b +26 1 +48 2 +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); +a b +26 1 +48 2 +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index fc97d22cbb1..780a4f3a002 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1861,4 +1861,16 @@ select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); select * from t1 where (s1 = ALL (select s1/s1 from t1)); select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); drop table t1; + +# +# Bug #16255: Subquery in where +# +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); + +INSERT INTO t1 VALUES(26, 1), (48, 2); + +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); +SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); + +DROP TABLE t1; # End of 4.1 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c95a91de13e..13beb022c9d 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -976,18 +976,18 @@ Item_in_subselect::row_value_transformer(JOIN *join) DBUG_RETURN(RES_ERROR); Item *item_eq= new Item_func_eq(new - Item_direct_ref((*optimizer->get_cache())-> + Item_ref((*optimizer->get_cache())-> addr(i), (char *)"", (char *)in_left_expr_name), new - Item_direct_ref(select_lex->ref_pointer_array + i, + Item_ref(select_lex->ref_pointer_array + i, (char *)"", (char *)"") ); Item *item_isnull= new Item_func_isnull(new - Item_direct_ref( select_lex-> + Item_ref( select_lex-> ref_pointer_array+i, (char *)"", (char *)"") @@ -1000,7 +1000,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) new Item_is_not_null_test(this, new - Item_direct_ref(select_lex-> + Item_ref(select_lex-> ref_pointer_array + i, (char *)"", (char *)"") @@ -1057,7 +1057,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) new Item_is_not_null_test(this, new - Item_direct_ref(select_lex-> + Item_ref(select_lex-> ref_pointer_array + i, (char *)"", (char *)"") From f895a16c721265c75f6492d5ada096e223cae59b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Aug 2006 19:16:27 +0400 Subject: [PATCH 35/52] BUG#16255: Post-review fixes: adjust the testcase. mysql-test/r/subselect.result: BUG#16255: A proper testcase mysql-test/t/subselect.test: BUG#16255: A proper testcase --- mysql-test/r/subselect.result | 33 ++++++++++++++++++++++----------- mysql-test/t/subselect.test | 22 +++++++++++++++++----- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index e84c3957760..f5abc4ed42a 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,14 +2895,25 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; -CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); -INSERT INTO t1 VALUES(26, 1), (48, 2); -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); -a b -26 1 -48 2 -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); -a b -26 1 -48 2 -DROP TABLE t1; +create table t1 ( +retailerID varchar(8) NOT NULL, +statusID int(10) unsigned NOT NULL, +changed datetime NOT NULL, +UNIQUE KEY retailerID (retailerID, statusID, changed) +); +INSERT INTO t1 VALUES("0026", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0026", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50"); +INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50"); +select * from t1 r1 +where (r1.retailerID,(r1.changed)) in +(SELECT r2.retailerId,(max(changed)) from t1 r2 +group by r2.retailerId); +retailerID statusID changed +0026 2 2006-01-06 12:25:53 +0037 2 2006-01-06 12:25:53 +0048 1 2006-01-06 12:37:50 +0059 1 2006-01-06 12:37:50 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 780a4f3a002..10dfb788c10 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1865,12 +1865,24 @@ drop table t1; # # Bug #16255: Subquery in where # -CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); +create table t1 ( + retailerID varchar(8) NOT NULL, + statusID int(10) unsigned NOT NULL, + changed datetime NOT NULL, + UNIQUE KEY retailerID (retailerID, statusID, changed) +); -INSERT INTO t1 VALUES(26, 1), (48, 2); +INSERT INTO t1 VALUES("0026", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0026", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56"); +INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53"); +INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50"); +INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50"); -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a,MAX(b) FROM t1 GROUP BY a); -SELECT * FROM t1 r WHERE (r.a,r.b) IN (SELECT a + 0,MAX(b) FROM t1 GROUP BY a); +select * from t1 r1 + where (r1.retailerID,(r1.changed)) in + (SELECT r2.retailerId,(max(changed)) from t1 r2 + group by r2.retailerId); +drop table t1; -DROP TABLE t1; # End of 4.1 tests From 72695c3fae1281ccf535907edf847077446e971d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 10:11:15 +0200 Subject: [PATCH 36/52] Backport fix for finding executables from 5.0 mysql-test/lib/mtr_misc.pl: On windows the exe does not need to be executable for it to be found --- mysql-test/lib/mtr_misc.pl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 26d5b9ed283..08c99e90906 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -82,7 +82,14 @@ sub mtr_path_exists (@) { sub mtr_script_exists (@) { foreach my $path ( @_ ) { - return $path if -x $path; + if($::glob_win32) + { + return $path if -f $path; + } + else + { + return $path if -x $path; + } } if ( @_ == 1 ) { @@ -99,7 +106,14 @@ sub mtr_exe_exists (@) { map {$_.= ".exe"} @path if $::glob_win32; foreach my $path ( @path ) { - return $path if -x $path; + if($::glob_win32) + { + return $path if -f $path; + } + else + { + return $path if -x $path; + } } if ( @path == 1 ) { From db2a86ce8fcb58fe67a73ec8bf1aa35e73490c77 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 10:46:14 +0200 Subject: [PATCH 37/52] Fix running tests suite with non standard tmp dir. Default is "var/tmp" mysql-test/r/myisam.result: Update result file mysql-test/t/myisam.test: If running test suite with a non standard tmp dir, the "show create table" will print "DATA DIRECTORY=" Use replace_result to mask it out Set tmpdir to var/log to get the printout of DATA DIRECTORY also when running with standard tmpdir --- mysql-test/r/myisam.result | 4 ++-- mysql-test/t/myisam.test | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index ce601944f97..d7c9ba19a8a 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -773,12 +773,12 @@ show create table t1; Table Create Table t1 CREATE TEMPORARY TABLE `t1` ( `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQL_TEST_DIR/var/log/' show create table t1; Table Create Table t1 CREATE TEMPORARY TABLE `t1` ( `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQL_TEST_DIR/var/log/' create table t1 (a int) engine=myisam select 42 a; select * from t1; a diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index be7bec117f3..11d0693b511 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -734,14 +734,20 @@ connect (session2,localhost,root,,); connection session1; disable_query_log; -eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/tmp" select 9 a; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/log" select 9 a; enable_query_log; +# If running test suite with a non standard tmp dir, the "show create table" +# will print "DATA_DIRECTORY=". Use replace_result to mask it out +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR show create table t1; connection session2; disable_query_log; -eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/tmp" select 99 a; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/log" select 99 a; enable_query_log; +# If running test suite with a non standard tmp dir, the "show create table" +# will print "DATA_DIRECTORY=". Use replace_result to mask it out +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR show create table t1; connection default; From 28db55a79535ffa22e3de32db0115bac4985e8b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 15:17:03 +0200 Subject: [PATCH 38/52] Backport from 5.0 a fix that will start ndb only for tests that needs it mysql-test/lib/mtr_cases.pl: Detect which tests that need ndb mysql-test/lib/mtr_match.pl: Add function mtr_match_substring mysql-test/mysql-test-run.pl: Only start cluster for test cases that need it --- mysql-test/lib/mtr_cases.pl | 22 ++++++++++++++++++++++ mysql-test/lib/mtr_match.pl | 17 +++++++++++++++++ mysql-test/mysql-test-run.pl | 28 ++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 3666c1aa01b..650fb79155d 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -193,6 +193,28 @@ sub collect_one_test_case($$$$$$) { $tinfo->{'slave_restart'}= 1; } + # Cluster is needed by test case if testname contains ndb + if ( defined mtr_match_substring($tname,"ndb") ) + { + $tinfo->{'ndb_test'}= 1; + if ( $::opt_skip_ndbcluster ) + { + # Skip all ndb tests + $tinfo->{'skip'}= 1; + return; + } + if ( ! $::opt_with_ndbcluster ) + { + # Ndb is not supported, skip them + $tinfo->{'skip'}= 1; + return; + } + } + else + { + $tinfo->{'ndb_test'}= 0; + } + # FIXME what about embedded_server + ndbcluster, skip ?! my $master_opt_file= "$testdir/$tname-master.opt"; diff --git a/mysql-test/lib/mtr_match.pl b/mysql-test/lib/mtr_match.pl index eb5de655520..66b639c7f8e 100644 --- a/mysql-test/lib/mtr_match.pl +++ b/mysql-test/lib/mtr_match.pl @@ -50,6 +50,23 @@ sub mtr_match_extension ($$) { } +# Match a substring anywere in a string + +sub mtr_match_substring ($$) { + my $string= shift; + my $substring= shift; + + if ( $string =~ /(.*)\Q$substring\E(.*)$/ ) # strncmp + { + return $1; + } + else + { + return undef; # NULL + } +} + + sub mtr_match_any_exact ($$) { my $string= shift; my $mlist= shift; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8cf14faec0c..eff6c7ccfbe 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1581,6 +1581,16 @@ sub run_testcase ($) { { $do_restart= 1; # Always restart if script to run } + elsif ( $tinfo->{'ndb_test'} and $master->[0]->{'ndbcluster'} == 1 ) + { + $do_restart= 1; # Restart with cluster + # print "Restarting because cluster need to be enabled\n"; + } + elsif ($tinfo->{'ndb_test'} == 0 and $master->[0]->{'ndbcluster'} == 0) + { + $do_restart= 1; # Restart without cluster + # print "Restarting because cluster need to be disabled\n"; + } elsif ( $master->[0]->{'running_master_is_special'} and $master->[0]->{'running_master_is_special'}->{'timezone'} eq $tinfo->{'timezone'} and @@ -1646,7 +1656,7 @@ sub run_testcase ($) { if ( ! $opt_local_master ) { - if ( $master->[0]->{'ndbcluster'} ) + if ( $master->[0]->{'ndbcluster'} && $tinfo->{'ndb_test'}) { $master->[0]->{'ndbcluster'}= ndbcluster_start(); if ( $master->[0]->{'ndbcluster'} ) @@ -1659,8 +1669,22 @@ sub run_testcase ($) { { # FIXME not correct location for do_before_start_master() do_before_start_master($tname,$tinfo->{'master_sh'}); + + # Save skip_ndbcluster + my $save_opt_skip_ndbcluster= $opt_skip_ndbcluster; + if (!$tinfo->{'ndb_test'}) + { + # Modify skip_ndbcluster so cluster is skipped for this + # and subsequent testcases(until we find one that does not cluster) + $opt_skip_ndbcluster= 1; + } + $master->[0]->{'pid'}= mysqld_start('master',0,$tinfo->{'master_opt'},[]); + + # Restore skip_ndbcluster + $opt_skip_ndbcluster= $save_opt_skip_ndbcluster; + if ( ! $master->[0]->{'pid'} ) { report_failure_and_restart($tinfo); @@ -2026,7 +2050,7 @@ sub mysqld_arguments ($$$$$) { } } - if ( $opt_with_ndbcluster ) + if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster) { mtr_add_arg($args, "%s--ndbcluster", $prefix); mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix, From 30031bbf37d7e277d2b67ccd8432f3c59343c34f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 15:23:42 +0200 Subject: [PATCH 39/52] Add mysqld-max-nt to list of mysqld executales to look for on windows --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index eff6c7ccfbe..54b680c6f0f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -898,7 +898,8 @@ sub executable_setup () { $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt", "$path_client_bindir/mysqld", "$path_client_bindir/mysqld-debug", - "$path_client_bindir/mysqld-max"); + "$path_client_bindir/mysqld-max", + "$path_client_bindir/mysqld-max-nt"); $path_language= mtr_path_exists("$glob_basedir/share/english/"); $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); $exe_my_print_defaults= From 48966da630a80d4cad22900c3aade2719809be70 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 17:01:04 +0200 Subject: [PATCH 40/52] Ignore --skip-im if specified on command line Null merge to 5.0 mysql-test/mysql-test-run.pl: Ignore --skip-im if specified on command line --- mysql-test/mysql-test-run.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 54b680c6f0f..aafc266a2f2 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -233,6 +233,7 @@ our $opt_result_ext; our $opt_skip; our $opt_skip_rpl; +our $opt_skip_im; # --skip-im on command line will just be ignored our $opt_skip_test; our $opt_sleep; @@ -519,6 +520,7 @@ sub command_line_setup () { 'do-test=s' => \$opt_do_test, 'suite=s' => \$opt_suite, 'skip-rpl' => \$opt_skip_rpl, + 'skip-im' => \$opt_skip_im, 'skip-test=s' => \$opt_skip_test, # Specify ports From 9aa12815b3a5e71beda2072e11f27bcc3c139b33 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Aug 2006 18:38:42 +0200 Subject: [PATCH 41/52] Dont' ever use cluster for slave in 4.1 --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index aafc266a2f2..d1e049ff883 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2053,7 +2053,7 @@ sub mysqld_arguments ($$$$$) { } } - if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster) + if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster && $type eq 'master') { mtr_add_arg($args, "%s--ndbcluster", $prefix); mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix, From 06707e20bc63698e6b97bc91fe7b644f65271e72 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Aug 2006 01:13:06 +0200 Subject: [PATCH 42/52] minor portability fix in SETUP.sh --- BUILD/SETUP.sh | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 150f9e28b41..2b47f0daacd 100644 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -1,4 +1,4 @@ -if ! test -f sql/mysqld.cc +if test ! -f sql/mysqld.cc then echo "You must run this script from the MySQL top-level directory" exit 1 @@ -81,12 +81,6 @@ fi # (returns 0 if finds lines) if ccache -V > /dev/null 2>&1 then - if ! (echo "$CC" | grep "ccache" > /dev/null) - then - CC="ccache $CC" - fi - if ! (echo "$CXX" | grep "ccache" > /dev/null) - then - CXX="ccache $CXX" - fi + echo "$CC" | grep "ccache" > /dev/null || CC="ccache $CC" + echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX" fi From ddb9f8668fa10166e4ffb761dc54a25a007c5bfa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 15:56:17 +0500 Subject: [PATCH 43/52] Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte include/mysql_com.h: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte added new constants NAME_BYTE_LEN, USERNAME_BYTE_LENGTH, SYSTEM_CHARSET_MBMAXLEN mysql-test/r/ctype_utf8.result: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte test case mysql-test/t/ctype_utf8.test: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte test case sql-common/client.c: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte increased buffers for user name & db sql/sql_acl.cc: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte check that user name is not longer than USERNAME_LENGTH symbols sql/sql_parse.cc: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte increased buffers for user name & db sql/table.cc: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte check that db name is not longer than NAME_LEN symbols --- include/mysql_com.h | 3 +++ mysql-test/r/ctype_utf8.result | 12 ++++++++++++ mysql-test/t/ctype_utf8.test | 16 ++++++++++++++++ sql-common/client.c | 6 +++--- sql/sql_acl.cc | 6 +++++- sql/sql_parse.cc | 4 ++-- sql/table.cc | 6 ++++-- 7 files changed, 45 insertions(+), 8 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 56c7f7d2ab5..28c3f86701f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -26,6 +26,9 @@ #define USERNAME_LENGTH 16 #define SERVER_VERSION_LENGTH 60 #define SQLSTATE_LENGTH 5 +#define SYSTEM_CHARSET_MBMAXLEN 3 +#define NAME_BYTE_LEN NAME_LEN*SYSTEM_CHARSET_MBMAXLEN +#define USERNAME_BYTE_LENGTH USERNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 5a175ba1713..941b834a733 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,3 +1340,15 @@ select a from t1 group by a; a e drop table t1; +set names utf8; +grant select on test.* to юзер_юзер@localhost; +user() +юзер_юзер@localhost +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; +create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +database() +имя_базы_в_кодировке_утф8_длиной_больше_чем_45 +drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index eb395680cc9..7272cb79089 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1072,4 +1072,20 @@ explain select a from t1 group by a; select a from t1 group by a; drop table t1; +# +# Bug#20393: User name truncation in mysql client +# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte +# +set names utf8; +#create user юзер_юзер@localhost; +grant select on test.* to юзер_юзер@localhost; +--exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; + +create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; + # End of 4.1 tests diff --git a/sql-common/client.c b/sql-common/client.c index ff5f1ef150a..4d37b850bcb 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1618,7 +1618,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,ulong client_flag) { - char buff[NAME_LEN+USERNAME_LENGTH+100]; + char buff[NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+100]; char *end,*host_info; my_socket sock; in_addr_t ip_addr; @@ -2063,7 +2063,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->server_status, client_flag)); /* This needs to be changed as it's not useful with big packets */ if (user && user[0]) - strmake(end,user,USERNAME_LENGTH); /* Max user name */ + strmake(end,user,USERNAME_BYTE_LENGTH); /* Max user name */ else read_user_name((char*) end); @@ -2093,7 +2093,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Add database if needed */ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { - end= strmake(end, db, NAME_LEN) + 1; + end= strmake(end, db, NAME_BYTE_LEN) + 1; mysql->db= my_strdup(db,MYF(MY_WME)); db= 0; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0ad5432f3eb..6ede19d0e96 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2640,7 +2640,11 @@ int mysql_grant(THD *thd, const char *db, List &list, while ((Str = str_list++)) { if (Str->host.length > HOSTNAME_LENGTH || - Str->user.length > USERNAME_LENGTH) + system_charset_info->cset->charpos(system_charset_info, + Str->user.str, + Str->user.str + + Str->user.length, + USERNAME_LENGTH) < Str->user.length) { my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0)); result= -1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cf1f50aed63..89ecceeb1bf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -902,8 +902,8 @@ static int check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; char *db= passwd; - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 - char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 + char db_buff[NAME_BYTE_LEN + 1]; // buffer to store db in utf8 + char user_buff[USERNAME_BYTE_LENGTH + 1]; // buffer to store user in utf8 uint dummy_errors; /* diff --git a/sql/table.cc b/sql/table.cc index 29e7d5ebf26..7587531b2f9 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1413,7 +1413,7 @@ char *get_field(MEM_ROOT *mem, Field *field) bool check_db_name(char *name) { - char *start=name; + uint name_length= 0; // name length in symbols /* Used to catch empty names and names with end space */ bool last_char_is_space= TRUE; @@ -1430,6 +1430,7 @@ bool check_db_name(char *name) name+system_charset_info->mbmaxlen); if (len) { + name_length++; name += len; continue; } @@ -1437,12 +1438,13 @@ bool check_db_name(char *name) #else last_char_is_space= *name==' '; #endif + name_length++; if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR || *name == FN_EXTCHAR) return 1; name++; } - return last_char_is_space || (uint) (name - start) > NAME_LEN; + return (last_char_is_space || name_length > NAME_LEN); } From 71583c893afba17533d59ed8863674ade47ede5f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 21:24:09 +0200 Subject: [PATCH 44/52] portability fix in BUILD/* for solaris --- BUILD/check-cpu | 363 ++++++++++++++++++++++++------------------------ 1 file changed, 183 insertions(+), 180 deletions(-) diff --git a/BUILD/check-cpu b/BUILD/check-cpu index b970a4b9a5b..e207d12d972 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -3,203 +3,206 @@ # Check cpu of current machine and find the # best compiler optimization flags for gcc # -# -if test -r /proc/cpuinfo ; then - # on Linux (and others?) we can get detailed CPU information out of /proc - cpuinfo="cat /proc/cpuinfo" +check_cpu () { + if test -r /proc/cpuinfo ; then + # on Linux (and others?) we can get detailed CPU information out of /proc + cpuinfo="cat /proc/cpuinfo" - # detect CPU family - cpu_family=`$cpuinfo | grep 'family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` - if test -z "$cpu_family" ; then - cpu_family=`$cpuinfo | grep 'cpu' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + # detect CPU family + cpu_family=`$cpuinfo | grep 'family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + if test -z "$cpu_family" ; then + cpu_family=`$cpuinfo | grep 'cpu' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + fi + + # detect CPU vendor and model + cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` + model_name=`$cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -1` + if test -z "$model_name" ; then + model_name=`$cpuinfo | grep 'cpu model' | cut -d ':' -f 2 | head -1` + fi + + # fallback: get CPU model from uname output + if test -z "$model_name" ; then + model_name=`uname -m` + fi + + # parse CPU flags + for flag in `$cpuinfo | grep '^flags' | sed -e 's/^flags.*: //'`; do + eval cpu_flag_$flag=yes + done + else + # Fallback when there is no /proc/cpuinfo + case "`uname -s`" in + FreeBSD|OpenBSD) + cpu_family=`uname -m`; + model_name=`sysctl -n hw.model` + ;; + Darwin) + cpu_family=`uname -p` + model_name=`machine` + ;; + *) + cpu_family=`uname -m`; + model_name=`uname -p`; + ;; + esac fi - # detect CPU vendor and model - cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1` - model_name=`$cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -1` - if test -z "$model_name" ; then - model_name=`$cpuinfo | grep 'cpu model' | cut -d ':' -f 2 | head -1` - fi - - # fallback: get CPU model from uname output - if test -z "$model_name" ; then - model_name=`uname -m` - fi - - # parse CPU flags - for flag in `$cpuinfo | grep '^flags' | sed -e 's/^flags.*: //'`; do - eval cpu_flag_$flag=yes - done -else - # Fallback when there is no /proc/cpuinfo - case "`uname -s`" in - FreeBSD|OpenBSD) - cpu_family=`uname -m`; - model_name=`sysctl -n hw.model` + # detect CPU shortname as used by gcc options + # this list is not complete, feel free to add further entries + cpu_arg="" + case "$cpu_family--$model_name" in + # DEC Alpha + Alpha*EV6*) + cpu_arg="ev6"; ;; - Darwin) - cpu_family=`uname -p` - model_name=`machine` + + # Intel ia32 + *Xeon*) + # a Xeon is just another pentium4 ... + # ... unless it has the "lm" (long-mode) flag set, + # in that case it's a Xeon with EM64T support + if [ -z "$cpu_flag_lm" ]; then + cpu_arg="pentium4"; + else + cpu_arg="nocona"; + fi ;; + *Pentium*4*Mobile*) + cpu_arg="pentium4m"; + ;; + *Pentium*4*) + cpu_arg="pentium4"; + ;; + *Pentium*III*Mobile*) + cpu_arg="pentium3m"; + ;; + *Pentium*III*) + cpu_arg="pentium3"; + ;; + *Pentium*M*pro*) + cpu_arg="pentium-m"; + ;; + *Athlon*64*) + cpu_arg="athlon64"; + ;; + *Athlon*) + cpu_arg="athlon"; + ;; + + # Intel ia64 + *Itanium*) + # Don't need to set any flags for itanium(at the moment) + cpu_arg=""; + ;; + + # + *ppc*) + cpu_arg='powerpc' + ;; + + *powerpc*) + cpu_arg='powerpc' + ;; + + # unknown *) - cpu_family=`uname -m`; - model_name=`uname -p`; + cpu_arg=""; ;; esac -fi - -# detect CPU shortname as used by gcc options -# this list is not complete, feel free to add further entries -cpu_arg="" -case "$cpu_family--$model_name" in - # DEC Alpha - Alpha*EV6*) - cpu_arg="ev6"; - ;; - - # Intel ia32 - *Xeon*) - # a Xeon is just another pentium4 ... - # ... unless it has the "lm" (long-mode) flag set, - # in that case it's a Xeon with EM64T support - if [ -z "$cpu_flag_lm" ]; then - cpu_arg="pentium4"; - else - cpu_arg="nocona"; - fi - ;; - *Pentium*4*Mobile*) - cpu_arg="pentium4m"; - ;; - *Pentium*4*) - cpu_arg="pentium4"; - ;; - *Pentium*III*Mobile*) - cpu_arg="pentium3m"; - ;; - *Pentium*III*) - cpu_arg="pentium3"; - ;; - *Pentium*M*pro*) - cpu_arg="pentium-m"; - ;; - *Athlon*64*) - cpu_arg="athlon64"; - ;; - *Athlon*) - cpu_arg="athlon"; - ;; - - # Intel ia64 - *Itanium*) - # Don't need to set any flags for itanium(at the moment) - cpu_arg=""; - ;; - - # - *ppc*) - cpu_arg='powerpc' - ;; - - *powerpc*) - cpu_arg='powerpc' - ;; - - # unknown - *) - cpu_arg=""; - ;; -esac -if test -z "$cpu_arg"; then - echo "BUILD/check-cpu: Oops, could not find out what kind of cpu this machine is using." - check_cpu_cflags="" - return -fi - -# different compiler versions have different option names -# for CPU specific command line options -if test -z "$CC" ; then - cc="gcc"; -else - cc=$CC -fi - -cc_ver=`$cc --version | sed 1q` -cc_verno=`echo $cc_ver | sed -e 's/[^0-9. ]//g; s/^ *//g; s/ .*//g'` - -case "$cc_ver--$cc_verno" in - *GCC*) - # different gcc backends (and versions) have different CPU flags - case `gcc -dumpmachine` in - i?86-*) - case "$cc_verno" in - 3.4*|3.5*|4.*) - check_cpu_args='-mtune=$cpu_arg -march=$cpu_arg' - ;; - *) - check_cpu_args='-mcpu=$cpu_arg -march=$cpu_arg' - ;; - esac - ;; - ppc-*) - check_cpu_args='-mcpu=$cpu_arg -mtune=$cpu_arg' - ;; - *) - check_cpu_cflags="" - return - ;; - esac - ;; - 2.95.*) - # GCC 2.95 doesn't expose its name in --version output - check_cpu_args='-m$cpu_arg' - ;; - *) + if test -z "$cpu_arg"; then + echo "BUILD/check-cpu: Oops, could not find out what kind of cpu this machine is using." >&2 check_cpu_cflags="" return - ;; -esac - -# now we check whether the compiler really understands the cpu type -touch __test.c - -while [ "$cpu_arg" ] ; do - echo -n testing $cpu_arg "... " - - # compile check - check_cpu_cflags=`eval echo $check_cpu_args` - if $cc -c $check_cpu_cflags __test.c 2>/dev/null; then - echo ok - break; fi - echo failed - check_cpu_cflags="" + # different compiler versions have different option names + # for CPU specific command line options + if test -z "$CC" ; then + cc="gcc"; + else + cc=$CC + fi - # if compile failed: check whether it supports a predecessor of this CPU - # this list is not complete, feel free to add further entries - case "$cpu_arg" in - # Intel ia32 - nocona) cpu_arg=pentium4 ;; - prescott) cpu_arg=pentium4 ;; - pentium4m) cpu_arg=pentium4 ;; - pentium4) cpu_arg=pentium3 ;; - pentium3m) cpu_arg=pentium3 ;; - pentium3) cpu_arg=pentium2 ;; - pentium2) cpu_arg=pentiumpro ;; - pentiumpro) cpu_arg=pentium ;; - pentium) cpu_arg=i486 ;; - i486) cpu_arg=i386 ;; + cc_ver=`$cc --version | sed 1q` + cc_verno=`echo $cc_ver | sed -e 's/[^0-9. ]//g; s/^ *//g; s/ .*//g'` - # power / powerPC - 7450) cpu_arg=7400 ;; - - *) cpu_arg="" ;; + case "$cc_ver--$cc_verno" in + *GCC*) + # different gcc backends (and versions) have different CPU flags + case `gcc -dumpmachine` in + i?86-*) + case "$cc_verno" in + 3.4*|3.5*|4.*) + check_cpu_args='-mtune=$cpu_arg -march=$cpu_arg' + ;; + *) + check_cpu_args='-mcpu=$cpu_arg -march=$cpu_arg' + ;; + esac + ;; + ppc-*) + check_cpu_args='-mcpu=$cpu_arg -mtune=$cpu_arg' + ;; + *) + check_cpu_cflags="" + return + ;; + esac + ;; + 2.95.*) + # GCC 2.95 doesn't expose its name in --version output + check_cpu_args='-m$cpu_arg' + ;; + *) + check_cpu_cflags="" + return + ;; esac -done -rm __test.* + # now we check whether the compiler really understands the cpu type + touch __test.c + while [ "$cpu_arg" ] ; do + # FIXME: echo -n isn't portable - see contortions autoconf goes through + echo -n testing $cpu_arg "... " >&2 + + # compile check + check_cpu_cflags=`eval echo $check_cpu_args` + if $cc -c $check_cpu_cflags __test.c 2>/dev/null; then + echo ok >&2 + break; + fi + + echo failed >&2 + check_cpu_cflags="" + + # if compile failed: check whether it supports a predecessor of this CPU + # this list is not complete, feel free to add further entries + case "$cpu_arg" in + # Intel ia32 + nocona) cpu_arg=pentium4 ;; + prescott) cpu_arg=pentium4 ;; + pentium4m) cpu_arg=pentium4 ;; + pentium4) cpu_arg=pentium3 ;; + pentium3m) cpu_arg=pentium3 ;; + pentium3) cpu_arg=pentium2 ;; + pentium2) cpu_arg=pentiumpro ;; + pentiumpro) cpu_arg=pentium ;; + pentium) cpu_arg=i486 ;; + i486) cpu_arg=i386 ;; + + # power / powerPC + 7450) cpu_arg=7400 ;; + + *) cpu_arg="" ;; + esac + done + + rm __test.* +} + +check_cpu From 077b649aef8c7432e8b08606465d5954d07289ed Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 22:39:23 +0200 Subject: [PATCH 45/52] Remove ^Z from ctype_ucs.test data, to avoid problems testing on Windows --- mysql-test/r/ctype_ucs.result | 14 +++++++------- mysql-test/t/ctype_ucs.test | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 3a65287ffc5..05866ea4966 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -726,26 +726,26 @@ drop table if exists bug20536; set names latin1; create table bug20536 (id bigint not null auto_increment primary key, name varchar(255) character set ucs2 not null); -insert into `bug20536` (`id`,`name`) values (1, _latin1 x'74657374311a'), (2, "'test\\_2'"); +insert into `bug20536` (`id`,`name`) values (1, _latin1 x'7465737431'), (2, "'test\\_2'"); select md5(name) from bug20536; md5(name) -3417d830fe24ffb2f81a28e54df2d1b3 +f4b7ce8b45a20e3c4e84bef515d1525c 48d95db0d8305c2fe11548a3635c9385 select sha1(name) from bug20536; sha1(name) -72228a6d56efb7a89a09543068d5d8fa4c330881 +e0b52f38deddb9f9e8d5336b153592794cb49baf 677d4d505355eb5b0549b865fcae4b7f0c28aef5 select make_set(3, name, upper(name)) from bug20536; make_set(3, name, upper(name)) -test1,TEST1 +test1,TEST1 'test\_2','TEST\_2' select export_set(5, name, upper(name)) from bug20536; export_set(5, name, upper(name)) -test1,TEST1,test1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1 +test1,TEST1,test1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1,TEST1 'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2','TEST\_2' select export_set(5, name, upper(name), ",", 5) from bug20536; export_set(5, name, upper(name), ",", 5) -test1,TEST1,test1,TEST1,TEST1 +test1,TEST1,test1,TEST1,TEST1 'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2' select password(name) from bug20536; password(name) @@ -761,7 +761,7 @@ SA5pDi1UPZdys SA5pDi1UPZdys select quote(name) from bug20536; quote(name) -?????????? +???????? ???????????????? drop table bug20536; End of 4.1 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 0ad38d98403..62244b3d8f5 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -475,7 +475,7 @@ drop table if exists bug20536; set names latin1; create table bug20536 (id bigint not null auto_increment primary key, name varchar(255) character set ucs2 not null); -insert into `bug20536` (`id`,`name`) values (1, _latin1 x'74657374311a'), (2, "'test\\_2'"); +insert into `bug20536` (`id`,`name`) values (1, _latin1 x'7465737431'), (2, "'test\\_2'"); select md5(name) from bug20536; select sha1(name) from bug20536; select make_set(3, name, upper(name)) from bug20536; From 626abc5205745ff002be2c4910460999df294439 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 17:28:34 -0400 Subject: [PATCH 46/52] Bug#4053: too many of "error 1236: 'binlog truncated in the middle of \ event' from master" Since there is no repeatable test case, and this is obviously wrong, this is the most conservative change that might possibly work. The syscall read() wasn't checked for a negative return value for an interrupted read. The kernel sys_read() returns -EINTR, and the "library" layer maps that to return value of -1 and sets errno to EINTR. It's impossible (on Linux) for read() to set errno EINTR without the return value being -1 . So, if we're checking for EINTR behavior, we should not require that the return value be zero. mysys/my_read.c: The read() syscall should check for negative one, since that (usually) signals errors (like being interrupted) and zero (usually) signals end-of-file . --- mysys/my_read.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/mysys/my_read.c b/mysys/my_read.c index b7621ac99eb..bca28694295 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -36,48 +36,51 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags) { - uint readbytes,save_count; + uint readbytes, save_count; DBUG_ENTER("my_read"); DBUG_PRINT("my",("Fd: %d Buffer: %lx Count: %u MyFlags: %d", - Filedes, Buffer, Count, MyFlags)); - save_count=Count; + Filedes, Buffer, Count, MyFlags)); + save_count= Count; for (;;) { - errno=0; /* Linux doesn't reset this */ - if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count) + errno= 0; /* Linux doesn't reset this */ + if ((readbytes= (uint) read(Filedes, Buffer, Count)) != Count) { - my_errno=errno ? errno : -1; + my_errno= errno ? errno : -1; DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d", - readbytes,Count,Filedes,my_errno)); + readbytes, Count, Filedes, my_errno)); #ifdef THREAD - if (readbytes == 0 && errno == EINTR) - continue; /* Interrupted */ + if ((int) readbytes <= 0 && errno == EINTR) + { + DBUG_PRINT("debug", ("my_read() was interrupted and returned %d", (int) readbytes)); + continue; /* Interrupted */ + } #endif if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - if ((int) readbytes == -1) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - else if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); + if ((int) readbytes == -1) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + else if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); } if ((int) readbytes == -1 || - ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) - DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ + ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) + DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ if (readbytes > 0 && (MyFlags & MY_FULL_IO)) { - Buffer+=readbytes; - Count-=readbytes; - continue; + Buffer+= readbytes; + Count-= readbytes; + continue; } } if (MyFlags & (MY_NABP | MY_FNABP)) - readbytes=0; /* Ok on read */ + readbytes= 0; /* Ok on read */ else if (MyFlags & MY_FULL_IO) - readbytes=save_count; + readbytes= save_count; break; } DBUG_RETURN(readbytes); From 22da915b62dce66f87bb7e29898d99265b31cfa2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Aug 2006 11:14:04 -0400 Subject: [PATCH 47/52] Bitkeeper's Tk interface uses UTF8 by default, so mixing charsets in a single file is a bad practice. tests/mysql_client_test.c: Replace literal characters which don't make sense in UTF8 with ubiquitously- understood numbers. --- tests/mysql_client_test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 94034141d81..bb4fb649a44 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -9952,8 +9952,9 @@ static void test_ps_i18n() const char *stmt_text; MYSQL_BIND bind_array[2]; - const char *koi8= ", "; - const char *cp1251= ", "; + /* Represented as numbers to keep UTF8 tools from clobbering them. */ + const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5"; + const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3"; char buf1[16], buf2[16]; ulong buf1_len, buf2_len; From 1bb1679c19614f3a2883e76fd03b09a216be4892 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 10:21:08 +0200 Subject: [PATCH 48/52] Add target to make "mtr", shortcut for running test suite BitKeeper/etc/ignore: Added mysql-test/mtr to the ignore list --- .bzrignore | 1 + mysql-test/Makefile.am | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index 6dd06504096..4325a9177fa 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1059,3 +1059,4 @@ vio/test-sslserver vio/viotest-ssl libmysql/libmysql.ver libmysqld/sql_locale.cc +mysql-test/mtr diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index cd939417e64..1e6eb12f7b2 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -34,7 +34,7 @@ benchdir_root= $(prefix) testdir = $(benchdir_root)/mysql-test EXTRA_SCRIPTS = mysql-test-run.sh install_test_db.sh $(PRESCRIPTS) EXTRA_DIST = $(EXTRA_SCRIPTS) -GENSCRIPTS = mysql-test-run install_test_db +GENSCRIPTS = mysql-test-run install_test_db mtr PRESCRIPTS = mysql-test-run.pl test_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS) test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem \ @@ -105,6 +105,11 @@ std_data/server-cert.pem: std_data/server-key.pem: @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data +# mtr - a shortcut for executing mysql-test-run.pl +mtr: + $(RM) -f mtr + $(LN_S) mysql-test-run.pl mtr + SUFFIXES = .sh .sh: From 49e2267ebda7809a1f93e61b4544ae800ed0705a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 11:21:12 +0200 Subject: [PATCH 49/52] Backport from 5.0 - Dont test "encrypt" in ctype_ucs mysql-test/r/ctype_ucs.result: Don't test "encrypt" function in ctype_ucs.test mysql-test/t/ctype_ucs.test: Don't test "encrypt" function in ctype_ucs.test --- mysql-test/r/ctype_ucs.result | 4 ---- mysql-test/t/ctype_ucs.test | 6 ------ 2 files changed, 10 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 05866ea4966..24a4ca9a85f 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -755,10 +755,6 @@ select old_password(name) from bug20536; old_password(name) ???????? ???????? -select encrypt(name, 'SALT') from bug20536; -encrypt(name, 'SALT') -SA5pDi1UPZdys -SA5pDi1UPZdys select quote(name) from bug20536; quote(name) ???????? diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 62244b3d8f5..d96b9938f1b 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -489,12 +489,6 @@ select export_set(5, name, upper(name), ",", 5) from bug20536; select password(name) from bug20536; select old_password(name) from bug20536; -# ENCRYPT relies on OS function crypt() which takes a NUL-terminated string; it -# doesn't return good results for strings with embedded 0 bytes. It won't be -# fixed unless we choose to re-implement the crypt() function ourselves to take -# an extra size_t string_length argument. -select encrypt(name, 'SALT') from bug20536; - # QUOTE doesn't work with UCS2 data. It would require a total rewrite # of Item_func_quote::val_str(), which isn't worthwhile until UCS2 is # supported fully as a client character set. From b017caefbd5f95fcdc81f1f545fdc944a454d168 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 15:07:04 +0300 Subject: [PATCH 50/52] Fix for BUG#21787: COUNT(*) + ORDER BY + LIMIT returns wrong result The problem was due to a prior fix for BUG 9676, which limited the rows stored in a temporary table to the LIMIT clause. This optimization is not applicable to non-group queries with aggregate functions. The fix disables the optimization in this case. mysql-test/r/limit.result: Test case for BUG#21787 mysql-test/t/limit.test: Test case for BUG#21787 sql/sql_select.cc: If there is an aggregate function in a non-group query, materialize all rows in the temporary table no matter if there is a LIMIT clause. This is necessary, since the aggregate functions must be computed over all result rows, not just the first LIMIT rows. --- mysql-test/r/limit.result | 14 ++++++++++++++ mysql-test/t/limit.test | 10 ++++++++++ sql/sql_select.cc | 19 ++++++++++++++----- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 6a3d2bffab0..92803ec3449 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -76,3 +76,17 @@ a a 1 drop table t1; +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5),(6),(7); +explain select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where; Using temporary +select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +c +7 +explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where; Using temporary +select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +c +28 diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index ef9f63067a4..f70cf835588 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -60,4 +60,14 @@ select 1 as a from t1 union all select 1 from dual limit 1; (select 1 as a from t1) union all (select 1 from dual) limit 1; drop table t1; +# +# Bug #21787: COUNT(*) + ORDER BY + LIMIT returns wrong result +# +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5),(6),(7); +explain select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +select count(*) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +explain select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; +select sum(a) c FROM t1 WHERE a > 0 ORDER BY c LIMIT 3; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 605ef49bb07..4c086f08af3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5612,11 +5612,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length+= key_part_info->length; } } - else - { - set_if_smaller(table->max_rows, rows_limit); - param->end_write_records= rows_limit; - } if (distinct && field_count != param->hidden_field_count) { @@ -5679,6 +5674,20 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, 0 : FIELDFLAG_BINARY; } } + + /* + Push the LIMIT clause to the temporary table creation, so that we + materialize only up to 'rows_limit' records instead of all result records. + This optimization is not applicable when there is GROUP BY or there is + no GROUP BY, but there are aggregate functions, because both must be + computed for all result rows. + */ + if (!group && !thd->lex->current_select->with_sum_func) + { + set_if_smaller(table->max_rows, rows_limit); + param->end_write_records= rows_limit; + } + if (thd->is_fatal_error) // If end of memory goto err; /* purecov: inspected */ table->db_record_offset=1; From d2d605e4ea578cf49adb52ebd834363962d099d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 13:43:34 +0200 Subject: [PATCH 51/52] bug#21965 - replication fix deadlock if master switches log file in parallell with "show master logs" sql/log.cc: add raw_get_current_log which dont take log mutex sql/sql_class.h: add raw_get_current_log which dont take log mutex sql/sql_repl.cc: Fix lock order i.e first log_lock then index_lock --- sql/log.cc | 11 ++++++++--- sql/sql_class.h | 1 + sql/sql_repl.cc | 8 ++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index c530f15a84f..5ae89dfeb50 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -409,12 +409,17 @@ shutdown the MySQL server and restart it.", log_name, errno); int MYSQL_LOG::get_current_log(LOG_INFO* linfo) { pthread_mutex_lock(&LOCK_log); - strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1); - linfo->pos = my_b_tell(&log_file); + int ret = raw_get_current_log(linfo); pthread_mutex_unlock(&LOCK_log); - return 0; + return ret; } +int MYSQL_LOG::raw_get_current_log(LOG_INFO* linfo) +{ + strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1); + linfo->pos = my_b_tell(&log_file); + return 0; +} /* Move all data up in a file in an filename index file diff --git a/sql/sql_class.h b/sql/sql_class.h index e8fe175cd7c..a995a492bc8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -177,6 +177,7 @@ public: bool need_mutex); int find_next_log(LOG_INFO* linfo, bool need_mutex); int get_current_log(LOG_INFO* linfo); + int raw_get_current_log(LOG_INFO* linfo); uint next_file_id(); inline bool is_open() { return log_type != LOG_CLOSED; } inline char* get_index_fname() { return index_file_name;} diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 963c4ccf5a6..2a7ab55b8c4 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1359,10 +1359,14 @@ int show_binlogs(THD* thd) MYSQL_TYPE_LONGLONG)); if (protocol->send_fields(&field_list, 1)) DBUG_RETURN(1); + + pthread_mutex_lock(mysql_bin_log.get_log_lock()); mysql_bin_log.lock_index(); index_file=mysql_bin_log.get_index_file(); - - mysql_bin_log.get_current_log(&cur); + + mysql_bin_log.raw_get_current_log(&cur); // dont take mutex + pthread_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK + cur_dir_len= dirname_length(cur.log_file_name); reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0); From 1039540807b39419ef523436672abb4ea888f585 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 16:53:03 +0300 Subject: [PATCH 52/52] BUG#21787: COUNT(*) + ORDER BY + LIMIT returns wrong result Fix an error in the bug fix. sql/sql_select.cc: Use a local variable to iterate over group items, since 'group' is used later in a condition. --- sql/sql_select.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3b973f5d092..f0859564a5e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5576,10 +5576,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length=0; keyinfo->rec_per_key=0; keyinfo->algorithm= HA_KEY_ALG_UNDEF; - for (; group ; group=group->next,key_part_info++) + ORDER *cur_group= group; + for (; cur_group ; cur_group= cur_group->next, key_part_info++) { - Field *field=(*group->item)->get_tmp_table_field(); - bool maybe_null=(*group->item)->maybe_null; + Field *field=(*cur_group->item)->get_tmp_table_field(); + bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; key_part_info->offset= field->offset(); @@ -5591,8 +5592,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, 0 : FIELDFLAG_BINARY; if (!using_unique_constraint) { - group->buff=(char*) group_buff; - if (!(group->field=field->new_field(thd->mem_root,table))) + cur_group->buff=(char*) group_buff; + if (!(cur_group->field=field->new_field(thd->mem_root,table))) goto err; /* purecov: inspected */ if (maybe_null) { @@ -5606,11 +5607,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, key_part_info->null_bit=field->null_bit; key_part_info->null_offset= (uint) (field->null_ptr - (uchar*) table->record[0]); - group->field->move_field((char*) ++group->buff); + cur_group->field->move_field((char*) ++cur_group->buff); group_buff++; } else - group->field->move_field((char*) group_buff); + cur_group->field->move_field((char*) group_buff); group_buff+= key_part_info->length; } keyinfo->key_length+= key_part_info->length;