From 0feec183b27838bf2fb0b8fc3abcc6bd0097dcc6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Jun 2006 09:20:55 +0200 Subject: [PATCH 01/47] 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 02/47] 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 3845856cc65eacd397d1ccf84ad283d223a52e9d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 16:33:26 -0600 Subject: [PATCH 03/47] 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 e80d95a7d68ccd0602778fe1502aa39639fbadbb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Aug 2006 16:55:41 +0200 Subject: [PATCH 04/47] 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 05/47] 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 06/47] 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 8462d3a46a262b0974f9bcf2bb2fc766df2ae631 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Aug 2006 19:20:30 +0300 Subject: [PATCH 07/47] Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result Reseting subqueries with "quick" access methods was incomplete. Partially backported the correct reseting of QUICK_SELECTs from 5.x. mysql-test/r/subselect.result: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - test case mysql-test/t/subselect.test: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - test case sql/opt_range.cc: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - partially backported the correct reseting of QUICK_SELECTs from 5.x. sql/opt_range.h: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - partially backported the correct reseting of QUICK_SELECTs from 5.x. --- mysql-test/r/subselect.result | 29 +++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/opt_range.cc | 14 +++++++++++++- sql/opt_range.h | 4 ++-- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e92d9d83d3f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,3 +2895,32 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; +create table t1(a int, primary key (a)); +insert into t1 values (10); +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +a a b +10 3 35989 +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +a a b +10 1 359 +drop table t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index fc97d22cbb1..ca3854833f4 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1861,4 +1861,30 @@ 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 #21180: Subselect with index for both WHERE and ORDER BY +# produces empty result +# +create table t1(a int, primary key (a)); +insert into t1 values (10); + +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; + +drop table t1,t2; # End of 4.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 57903ffe7b9..85125a4521a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2980,6 +2980,14 @@ int QUICK_SELECT::get_next() } } +void QUICK_SELECT::reset(void) +{ + next= 0; + it.rewind(); + range= 0; + if (file->inited == handler::NONE) + file->ha_index_init(index); +} /* Get next for geometrical indexes */ @@ -3201,7 +3209,11 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, return 0; } #endif - +void QUICK_SELECT_DESC::reset(void) +{ + rev_it.rewind(); + QUICK_SELECT::reset(); +} /***************************************************************************** ** Print a quick range for debugging diff --git a/sql/opt_range.h b/sql/opt_range.h index 15f0bf02b34..367a85dc6f2 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(); } + virtual void reset(void); int init() { key_part_info= head->key_info[index].key_part; @@ -120,7 +120,7 @@ private: #ifdef NOT_USED bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts); #endif - void reset(void) { next=0; rev_it.rewind(); } + void reset(void); List rev_ranges; List_iterator rev_it; }; From f287b4a8c8eb5890a38f18461b94fa11fc85e600 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 Aug 2006 08:41:32 +0200 Subject: [PATCH 08/47] 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 09/47] 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 10/47] 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 11/47] 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 12/47] 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 13/47] 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 d3dd6fa0084d6c89b71cb7d700a164a9f6e0da87 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 16:45:02 +0300 Subject: [PATCH 14/47] Bug #16792 query with subselect, join, and group not returning proper values Treat queries with no FROM and aggregate functions as normal queries, so the aggregate function get correctly calculated as if there is 1 row. This means that they will be considered to have one row, so COUNT(*) will return 1 instead of 0. Other aggregates will behave in compatible manner. mysql-test/r/func_gconcat.result: Bug #16792 query with subselect, join, and group not returning proper values - test case. Note how it improves the support for DUAL. mysql-test/r/func_group.result: Bug #16792 query with subselect, join, and group not returning proper values - test case. Note how it improves the support for DUAL. mysql-test/r/subselect.result: Bug #16792 query with subselect, join, and group not returning proper values - consequence of (SELECT MAX()) now returning instead of 0 mysql-test/t/func_group.test: Bug #16792 query with subselect, join, and group not returning proper values - test case. sql/opt_sum.cc: Bug #16792 query with subselect, join, and group not returning proper values - cannot do the optimization if the index is already opened by (say) UPDATE as it invloves opening reading and closing the index. sql/sql_select.cc: Bug #16792 query with subselect, join, and group not returning proper values - Treat queries with no FROM and aggregate functions as normal queries, so the aggregate function get correctly calculated as if there is 1 row. --- mysql-test/r/func_gconcat.result | 4 ++-- mysql-test/r/func_group.result | 24 ++++++++++++++++++++---- mysql-test/r/subselect.result | 4 ++-- mysql-test/t/func_group.test | 14 ++++++++++++++ sql/opt_sum.cc | 4 ++-- sql/sql_select.cc | 20 +++++++++++++++----- 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 2c79b8f8ab1..db0125b7d4f 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -559,14 +559,14 @@ COUNT(*) GROUP_CONCAT(DISTINCT t2.somename SEPARATOR ' |') DROP TABLE t1,t2; select * from (select group_concat('c') from DUAL) t; group_concat('c') -NULL +c create table t1 ( a int not null default 0); select * from (select group_concat(a) from t1) t2; group_concat(a) NULL select group_concat('x') UNION ALL select 1; group_concat('x') -NULL +x 1 drop table t1; CREATE TABLE t1 (id int, a varchar(9)); diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 932ef133087..04f6ebe6398 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -794,7 +794,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -809,7 +809,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -848,7 +848,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -864,7 +864,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -942,3 +942,19 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b)) +1 +1 +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT 12)) +1 +1 +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), +COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), +GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) +2.0000 2 2 2 1 1 1 2 2 0.0000 0.0000 2 2 2 +DROP TABLE t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e6b86980fbb 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1001,7 +1001,7 @@ INSERT INTO t1 VALUES (1); UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); select * from t1; i -1 +2 drop table t1; CREATE TABLE t1 (a int(1)); EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1; @@ -1193,7 +1193,7 @@ UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t); ERROR 42S02: Unknown table 't' in field list select * from t1; i -1 +3 drop table t1; CREATE TABLE t1 ( id int(11) default NULL diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index f8a3ed0f25e..18cb5d0a430 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -617,4 +617,18 @@ SELECT MAX(b) FROM t1; EXPLAIN SELECT MAX(b) FROM t1; DROP TABLE t1; +# +# Bug #16792 query with subselect, join, and group not returning proper values +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); + +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +# an attempt to test all aggregate function with no table. +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), + COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), + GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index b53fbfd3f80..bc98c96b5a8 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -182,7 +182,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(0, &ref, item_field->field, conds, &range_fl, &prefix_len)) { @@ -269,7 +269,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(1, &ref, item_field->field, conds, &range_fl, &prefix_len)) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 605ef49bb07..6a3b9fe54cf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1131,7 +1131,7 @@ JOIN::exec() DBUG_VOID_RETURN; } - if (!tables_list) + if (!tables_list && (tables || !select_lex->with_sum_func)) { // Only test of functions if (select_options & SELECT_DESCRIBE) select_describe(this, FALSE, FALSE, FALSE, @@ -1170,7 +1170,12 @@ JOIN::exec() thd->examined_row_count= 0; DBUG_VOID_RETURN; } - thd->limit_found_rows= thd->examined_row_count= 0; + /* + don't reset the found rows count if there're no tables + as FOUND_ROWS() may be called. + */ + if (tables) + thd->limit_found_rows= thd->examined_row_count= 0; if (zero_result_cause) { @@ -1209,7 +1214,8 @@ JOIN::exec() having= tmp_having; select_describe(this, need_tmp, order != 0 && !skip_sort_order, - select_distinct); + select_distinct, + !tables ? "No tables used" : NullS); DBUG_VOID_RETURN; } @@ -6028,9 +6034,12 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) else end_select=end_send; } - join->join_tab[join->tables-1].next_select=end_select; + if (join->tables) + { + join->join_tab[join->tables-1].next_select=end_select; - join_tab=join->join_tab+join->const_tables; + join_tab=join->join_tab+join->const_tables; + } join->send_records=0; if (join->tables == join->const_tables) { @@ -6048,6 +6057,7 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) } else { + DBUG_ASSERT(join_tab); error= sub_select(join,join_tab,0); if (error >= 0) error= sub_select(join,join_tab,1); From 3212b399a85b3c985655b950443fe09133c0922c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Aug 2006 17:09:19 -0600 Subject: [PATCH 15/47] 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 9907e970aea28ce186e110084c3a4f2d6ac0c602 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Aug 2006 20:33:14 +0400 Subject: [PATCH 16/47] 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 17/47] 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 18/47] 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 19/47] 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 20/47] 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 21/47] 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 22/47] 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 23/47] 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 24/47] 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 25/47] 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 26/47] 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 27/47] 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 28/47] 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 29/47] 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 30/47] 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 31/47] 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 32/47] 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 33/47] 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 34/47] 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 35/47] 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 36/47] 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 37/47] 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 38/47] 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 39/47] 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 40/47] 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 41/47] 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 42/47] 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; From 1431966d029ffd710c678080bee9e1d884205127 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 18:40:30 +0300 Subject: [PATCH 43/47] Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name in multi-table DELETE the set of tables to delete from actually references then tables in the other list, e.g: DELETE alias_of_t1 FROM t1 alias_of_t1 WHERE .... is a valid statement. So we must turn off table name syntactical validity check for alias_of_t1 because it's not a table name (even if it looks like one). In order to do that we add a special flag (TL_OPTION_ALIAS) to disable the name checking for the aliases in multi-table DELETE. mysql-test/r/delete.result: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - test case mysql-test/t/delete.test: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - test case sql/mysql_priv.h: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - add a special flag to disable the name checking for the aliases in multi-table DELETE sql/sql_parse.cc: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - add a special flag to disable the name checking for the aliases in multi-table DELETE sql/sql_yacc.yy: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - add a special flag to disable the name checking for the aliases in multi-table DELETE --- mysql-test/r/delete.result | 4 ++++ mysql-test/t/delete.test | 10 ++++++++++ sql/mysql_priv.h | 1 + sql/sql_parse.cc | 4 +++- sql/sql_yacc.yy | 7 +++++-- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 411cd52b4ca..cb632fcd6c8 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -172,3 +172,7 @@ a 0 2 DROP TABLE t1; +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 98e4c4e35fa..d4eb01cab23 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -153,4 +153,14 @@ DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a LIMIT 1; SELECT * FROM t1; DROP TABLE t1; +# +# Bug #21392: multi-table delete with alias table name fails with +# 1003: Incorrect table name +# + +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; + # End of 4.1 tests diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9c5bcc2d53f..4a5658c5ccf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -305,6 +305,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define TL_OPTION_UPDATING 1 #define TL_OPTION_FORCE_INDEX 2 #define TL_OPTION_IGNORE_LEAVES 4 +#define TL_OPTION_ALIAS 8 /* Some portable defines */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cf1f50aed63..c84c96e1e75 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4863,6 +4863,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) table_options A set of the following bits: TL_OPTION_UPDATING Table will be updated TL_OPTION_FORCE_INDEX Force usage of index + TL_OPTION_ALIAS an alias in multi table DELETE lock_type How table should be locked use_index List of indexed used in USE INDEX ignore_index List of indexed used in IGNORE INDEX @@ -4888,7 +4889,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, if (!table) DBUG_RETURN(0); // End of memory alias_str= alias ? alias->str : table->table.str; - if (check_table_name(table->table.str,table->table.length) || + if (!test(table_options & TL_OPTION_ALIAS) && + check_table_name(table->table.str,table->table.length) || table->db.str && check_db_name(table->db.str)) { net_printf(thd, ER_WRONG_TABLE_NAME, table->table.str); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..53e7b103f32 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4345,14 +4345,17 @@ table_wild_one: ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, - TL_OPTION_UPDATING, Lex->lock_option)) + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } | ident '.' ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident(YYTHD, $1, $3, 0), - $5, TL_OPTION_UPDATING, + $5, + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } From aa840645e632294393d1ca5d32fedbde2fb6c97e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 00:59:34 +0400 Subject: [PATCH 44/47] query_cache.result, func_time.test, type_date.result, func_time.result: Corrected test case after removal of fix for bug#16377 type_date.test: Corrected test case after removal of fix for bug#16377 item_cmpfunc.cc: Removed changes to the agg_cmp_type() made in the for bug#16377 mysql-test/t/type_date.test: Corrected test case after removal of fix for bug#16377 mysql-test/t/func_time.test: Corrected test case after removal of fix for bug#16377 mysql-test/r/type_date.result: Corrected test case after removal of fix for bug#16377 mysql-test/r/query_cache.result: Corrected test case after removal of fix for bug#16377 mysql-test/r/func_time.result: Corrected test case after removal of fix for bug#16377 sql/item_cmpfunc.cc: Removed changes to the agg_cmp_type() made in the for bug#16377 --- mysql-test/r/func_time.result | 23 ++++--- mysql-test/r/query_cache.result | 3 - mysql-test/r/type_date.result | 4 +- mysql-test/t/func_time.test | 22 +++---- mysql-test/t/type_date.test | 4 +- sql/item_cmpfunc.cc | 111 +------------------------------- 6 files changed, 29 insertions(+), 138 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 47a0f83802c..97dd8e243b2 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -646,37 +646,36 @@ drop table t1; create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); f1 2006-01-01 -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f1 from t1 where "2006-1-1" between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; f1 2006-01-01 -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; f1 -Warnings: -Warning 1292 Truncated incorrect date value: 'zzz' +2006-01-01 select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 24363ea27ab..2a57e06e330 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -907,19 +907,16 @@ COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' -Warning 1292 Truncated incorrect datetime value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050328 invalid' -Warning 1292 Truncated incorrect datetime value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' -Warning 1292 Truncated incorrect datetime value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 3428b5969d9..d8d6aa89684 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -27,12 +27,12 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); datum 2000-01-02 2000-01-03 2000-01-04 -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; datum DROP TABLE t1; CREATE TABLE t1 ( diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 472f3d81d2b..04bfc741d1c 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -341,20 +341,20 @@ drop table t1; # # Bug#16377 result of DATE/TIME functions were compared as strings which # can lead to a wrong result. -# +# Now wrong dates should be compared only with CAST() create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f1 from t1 where "2006-1-1" between f1 and f3; -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 78bdd9b8a80..5556d7f2831 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -36,8 +36,8 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; DROP TABLE t1; # diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a32bd0a7337..b766d1e857b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -75,119 +75,14 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. - - NOTES - Aggregation rules: - If there are DATE/TIME fields/functions in the list and no string - fields/functions in the list then: - The INT_RESULT type will be used for aggregation instead of original - result type of any DATE/TIME field/function in the list - All constant items in the list will be converted to a DATE/TIME using - found field or result field of found function. - - Implementation notes: - The code is equivalent to: - 1. Check the list for presence of a STRING field/function. - Collect the is_const flag. - 2. Get a Field* object to use for type coercion - 3. Perform type conversion. - 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME - field/function and checks presence of a STRING field/function. - The second loop works only if a DATE/TIME field/function is found. - It checks presence of a STRING field/function in the rest of the list. - - TODO - 1) The current implementation can produce false comparison results for - expressions like: - date_time_field BETWEEN string_field_with_dates AND string_constant - if the string_constant will omit some of leading zeroes. - In order to fully implement correct comparison of DATE/TIME the new - DATETIME_RESULT result type should be introduced and agg_cmp_type() - should return the DATE/TIME field used for the conversion. Later - this field can be used by comparison functions like Item_func_between to - convert string values to ints on the fly and thus return correct results. - This modification will affect functions BETWEEN, IN and CASE. - - 2) If in the list a DATE field/function and a DATETIME field/function - are present in the list then the first found field/function will be - used for conversion. This may lead to wrong results and probably should - be fixed. */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; - Item::Type res= (Item::Type)0; - /* Used only for date/time fields, max_length = 19 */ - char buff[20]; - uchar null_byte; - Field *field= NULL; - - /* Search for date/time fields/functions */ - for (i= 0; i < nitems; i++) - { - if (!items[i]->result_as_longlong()) - { - /* Do not convert anything if a string field/function is present */ - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT) - { - i= nitems; - break; - } - continue; - } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && - items[i]->result_type() != INT_RESULT) - { - field= ((Item_field *)items[i]->real_item())->field; - break; - } - else if (res == Item::FUNC_ITEM) - { - field= items[i]->tmp_table_field_from_field_type(0); - if (field) - field->move_field(buff, &null_byte, 0); - break; - } - } - if (field) - { - /* Check the rest of the list for presence of a string field/function. */ - for (i++ ; i < nitems; i++) - { - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT && - !items[i]->result_as_longlong()) - { - if (res == Item::FUNC_ITEM) - delete field; - field= 0; - break; - } - } - } - /* - If the first item is a date/time function then its result should be - compared as int - */ - if (field) - /* Suppose we are comparing dates */ - type[0]= INT_RESULT; - else - type[0]= items[0]->result_type(); - - for (i= 0; i < nitems ; i++) - { - Item_result result= items[i]->result_type(); - if (field && - ((!items[i]->const_item() && items[i]->result_as_longlong()) || - (items[i]->const_item() && convert_constant_item(thd, field, - &items[i])))) - result= INT_RESULT; - type[0]= item_cmp_type(type[0], result); - } - - if (res == Item::FUNC_ITEM && field) - delete field; + type[0]= items[0]->result_type(); + for (i= 1 ; i < nitems ; i++) + type[0]= item_cmp_type(type[0], items[i]->result_type()); } static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, From 54caf667ca45de1e81d306177147b53aab03fdff Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 10:24:14 +0300 Subject: [PATCH 45/47] Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES VALUES() was considered a constant. This caused replacing (or pre-calculating) it using uninitialized values before the actual execution takes place. Mark it as a non-constant (still not dependent of tables) to prevent the pre-calculation. mysql-test/r/insert_update.result: Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES - test case. - EXPLAIN output changed due to VALUES() not being considered a constant anymore mysql-test/t/insert_update.test: Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES - test case. sql/item.h: Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES - mark Item_insert_value as non-constant to prevent early calculation. --- mysql-test/r/insert_update.result | 26 ++++++++++++++++++++++++-- mysql-test/t/insert_update.test | 23 +++++++++++++++++++++++ sql/item.h | 6 +++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 9e674cc4aae..c41aab29853 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -63,9 +63,9 @@ Warnings: Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c`,values(test.t1.a) AS `VALUES(a)` from test.t1 explain extended select * from t1 where values(a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: -Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 +Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 where values(test.t1.a) DROP TABLE t1; create table t1(a int primary key, b int); insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5); @@ -197,3 +197,25 @@ PRIMARY KEY (a) ) ENGINE=MyISAM; INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +CREATE TABLE t1 +( +a BIGINT UNSIGNED, +b BIGINT UNSIGNED, +PRIMARY KEY (a) +); +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 1 +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +DROP TABLE t1; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index 8038bd7bfe7..56885a555fd 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -115,4 +115,27 @@ INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +# +# Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES +# + + # End of 4.1 tests +CREATE TABLE t1 +( + a BIGINT UNSIGNED, + b BIGINT UNSIGNED, + PRIMARY KEY (a) +); + +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index 3eab695cb5e..ad8bea663f1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1241,7 +1241,11 @@ public: { return Item_field::save_in_field(field_arg, no_conversions); } - table_map used_tables() const { return (table_map)0L; } + /* + We use RAND_TABLE_BIT to prevent Item_insert_value from + being treated as a constant and precalculated before execution + */ + table_map used_tables() const { return RAND_TABLE_BIT; } bool walk(Item_processor processor, byte *args) { From f3e838706d831b26fb9ca429bcfbc6a43f0fb533 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 19:06:26 +0400 Subject: [PATCH 46/47] item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 query_cache.result: Corrected a test case after removing a fix for bug#16377 mysql-test/r/query_cache.result: Corrected a test case after removing a fix for bug#16377 sql/item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 --- mysql-test/r/query_cache.result | 3 +++ sql/item_cmpfunc.cc | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 2a57e06e330..24363ea27ab 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -907,16 +907,19 @@ COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect datetime value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050328 invalid' +Warning 1292 Truncated incorrect datetime value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect datetime value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b766d1e857b..6b6996160a1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -916,8 +916,30 @@ void Item_func_between::fix_length_and_dec() if (!args[0] || !args[1] || !args[2]) return; agg_cmp_type(thd, &cmp_type, args, 3); - if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV); + if (cmp_type == STRING_RESULT && + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV)) + return; + + /* + Make a special case of compare with date/time and longlong fields. + They are compared as integers, so for const item this time-consuming + conversion can be done only once, not for every single comparison + */ + if (args[0]->type() == FIELD_ITEM) + { + Field *field=((Item_field*) args[0])->field; + if (field->can_be_compared_as_longlong()) + { + /* + The following can't be recoded with || as convert_constant_item + changes the argument + */ + if (convert_constant_item(thd, field,&args[1])) + cmp_type=INT_RESULT; // Works for all types. + if (convert_constant_item(thd, field,&args[2])) + cmp_type=INT_RESULT; // Works for all types. + } + } } From cca7be1c952680a72d6185d02955286824f546a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 18:45:23 +0400 Subject: [PATCH 47/47] type_date.test, type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN mysql-test/t/type_date.test: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN mysql-test/r/type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN --- mysql-test/r/type_date.result | 6 ++++++ mysql-test/t/type_date.test | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index d8d6aa89684..99e9adf84ca 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -104,3 +104,9 @@ SELECT * FROM t1; y 0000 DROP TABLE t1; +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +1 +1 +drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 5556d7f2831..c6050753943 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -115,4 +115,11 @@ INSERT INTO t1 VALUES ('abc'); SELECT * FROM t1; DROP TABLE t1; +# +# Bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN +# +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +drop table t1; # End of 4.1 tests