From bb4cc70d53e70239fe8524f33432a9963df9b254 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Apr 2005 13:14:03 +0200 Subject: [PATCH 1/9] ndb - csc#4847 release scan op early to save memory ndb/include/ndbapi/NdbConnection.hpp: release scan op of hupped trans at scan close to save memory ndb/include/ndbapi/NdbScanOperation.hpp: release scan op of hupped trans at scan close to save memory ndb/src/ndbapi/NdbConnection.cpp: release scan op of hupped trans at scan close to save memory ndb/src/ndbapi/NdbResultSet.cpp: release scan op of hupped trans at scan close to save memory ndb/src/ndbapi/NdbScanOperation.cpp: release scan op of hupped trans at scan close to save memory ndb/tools/desc.cpp: release scan op of hupped trans at scan close to save memory --- ndb/include/ndbapi/NdbConnection.hpp | 1 + ndb/include/ndbapi/NdbScanOperation.hpp | 2 +- ndb/src/ndbapi/NdbConnection.cpp | 31 +++++++++++++++++++++++++ ndb/src/ndbapi/NdbResultSet.cpp | 2 +- ndb/src/ndbapi/NdbScanOperation.cpp | 21 +++++++++++------ ndb/tools/desc.cpp | 2 +- 6 files changed, 49 insertions(+), 10 deletions(-) diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 3a9f18665e9..2ab6f7d6f64 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -542,6 +542,7 @@ private: // Release all cursor operations in connection void releaseOps(NdbOperation*); void releaseScanOperations(NdbIndexScanOperation*); + void releaseExecutedScanOperation(NdbIndexScanOperation*); // Set the transaction identity of the transaction void setTransactionId(Uint64 aTransactionId); diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index f25f9405033..f6e68dd4abe 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -93,7 +93,7 @@ protected: int nextResult(bool fetchAllowed = true, bool forceSend = false); virtual void release(); - void closeScan(bool forceSend = false); + void closeScan(bool forceSend = false, bool releaseOp = false); int close_impl(class TransporterFacade*, bool forceSend = false); // Overloaded methods from NdbCursorOperation diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index 0a1c7303771..e1f70160fb7 100644 --- a/ndb/src/ndbapi/NdbConnection.cpp +++ b/ndb/src/ndbapi/NdbConnection.cpp @@ -963,6 +963,37 @@ NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp) } }//NdbConnection::releaseScanOperations() +/***************************************************************************** +void releaseExecutedScanOperation(); + +Remark: Release scan op when hupp'ed trans closed (save memory) +******************************************************************************/ +void +NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp) +{ + DBUG_ENTER("NdbConnection::releaseExecutedScanOperation"); + DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp)) + + // here is one reason to make op lists doubly linked + if (m_firstExecutedScanOp == cursorOp) { + m_firstExecutedScanOp = (NdbIndexScanOperation*)cursorOp->theNext; + cursorOp->release(); + theNdb->releaseScanOperation(cursorOp); + } else if (m_firstExecutedScanOp != NULL) { + NdbIndexScanOperation* tOp = m_firstExecutedScanOp; + while (tOp->theNext != NULL) { + if (tOp->theNext == cursorOp) { + tOp->theNext = cursorOp->theNext; + cursorOp->release(); + theNdb->releaseScanOperation(cursorOp); + break; + } + tOp = (NdbIndexScanOperation*)tOp->theNext; + } + } + DBUG_VOID_RETURN; +}//NdbConnection::releaseExecutedScanOperation() + /***************************************************************************** NdbOperation* getNdbOperation(const char* aTableName); diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp index d9d71464026..87b304126ba 100644 --- a/ndb/src/ndbapi/NdbResultSet.cpp +++ b/ndb/src/ndbapi/NdbResultSet.cpp @@ -69,7 +69,7 @@ int NdbResultSet::nextResult(bool fetchAllowed, bool forceSend) void NdbResultSet::close(bool forceSend) { - m_operation->closeScan(forceSend); + m_operation->closeScan(forceSend, true); } NdbOperation* diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 670a18f72a0..fc5a22cce17 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -674,7 +674,7 @@ NdbScanOperation::doSend(int ProcessorId) return 0; } -void NdbScanOperation::closeScan(bool forceSend) +void NdbScanOperation::closeScan(bool forceSend, bool releaseOp) { if(m_transConnection){ if(DEBUG_NEXT_RESULT) @@ -691,13 +691,20 @@ void NdbScanOperation::closeScan(bool forceSend) Guard guard(tp->theMutexPtr); close_impl(tp, forceSend); - } while(0); - - theNdbCon->theScanningOp = 0; - theNdb->closeTransaction(theNdbCon); - - theNdbCon = 0; + } + + NdbConnection* tCon = theNdbCon; + NdbConnection* tTransCon = m_transConnection; + theNdbCon = NULL; m_transConnection = NULL; + + if (releaseOp && tTransCon) { + NdbIndexScanOperation* tOp = (NdbIndexScanOperation*)this; + tTransCon->releaseExecutedScanOperation(tOp); + } + + tCon->theScanningOp = 0; + theNdb->closeTransaction(tCon); } void diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp index 4287a771694..aac47c9042c 100644 --- a/ndb/tools/desc.cpp +++ b/ndb/tools/desc.cpp @@ -89,7 +89,7 @@ int main(int argc, char** argv){ unsigned j; for (j= 0; (int)j < pTab->getNoOfPrimaryKeys(); j++) { - const NdbDictionary::Column * col = pTab->getColumn(j); + const NdbDictionary::Column * col = pTab->getColumn(pTab->getPrimaryKey(j)); ndbout << col->getName(); if ((int)j < pTab->getNoOfPrimaryKeys()-1) ndbout << ", "; From f50dc99d24617fbbe9c532070e9e4fd0d69dfe3f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Apr 2005 15:16:15 +0200 Subject: [PATCH 2/9] add changeset key to the bk commit mail --- BitKeeper/triggers/post-commit | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index d2a4f9153b2..4c28b408658 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -27,6 +27,7 @@ then fi CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet` +CSETKEY=`bk -R prs -r+ -h -d':KEY:' ChangeSet` BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/\1/p'` if [ "$BUG" = "" ] @@ -51,6 +52,7 @@ List-ID: From: $FROM To: $TO Subject: bk commit - $VERSION tree ($CHANGESET)$BS +X-CSetKey: <$CSETKEY> $BH EOF bk changes -v -r+ @@ -67,6 +69,7 @@ List-ID: From: $FROM To: $INTERNALS Subject: bk commit into $VERSION tree ($CHANGESET)$BS +X-CSetKey: <$CSETKEY> $BH Below is the list of changes that have just been committed into a local $VERSION repository of $USER. When $USER does a push these changes will From ce10cefda6de5f184e3132b1985941cdac336b00 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Apr 2005 18:42:34 +0200 Subject: [PATCH 3/9] Per Heikki's request make trans_register_ha tolerant to multiple registrations --- sql/handler.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 3eead37482b..96fe3937198 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -505,10 +505,16 @@ void ha_close_connection(THD* thd) "beginning of transaction" and "beginning of statement"). Only storage engines registered for the transaction/statement will know when to commit/rollback it. + + NOTE + trans_register_ha is idempotent - storage engine may register many + times per transaction. + */ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) { THD_TRANS *trans; + handlerton **ht; DBUG_ENTER("trans_register_ha"); DBUG_PRINT("enter",("%s", all ? "all" : "stmt")); @@ -520,15 +526,12 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) else trans= &thd->transaction.stmt; -#ifndef DBUG_OFF - handlerton **ht=trans->ht; - while (*ht) - { - DBUG_ASSERT(*ht != ht_arg); - ht++; - } -#endif + for (ht=trans->ht; *ht; ht++) + if (*ht == ht_arg) + DBUG_VOID_RETURN; + trans->ht[trans->nht++]=ht_arg; + DBUG_ASSERT(*ht == ht_arg); trans->no_2pc|=(ht_arg->prepare==0); if (thd->transaction.xid.is_null()) thd->transaction.xid.set(thd->query_id); From 5687fe36bf21add03b96871215c58bd2e12a4666 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Apr 2005 11:53:15 +0500 Subject: [PATCH 4/9] Adding a new parameter for well_formed_length to return error. We'll use it for better warnign reporting. --- include/m_ctype.h | 9 ++++++--- ndb/src/ndbapi/NdbIndexOperation.cpp | 4 +++- ndb/src/ndbapi/NdbOperationDefine.cpp | 4 +++- ndb/src/ndbapi/NdbOperationSearch.cpp | 4 +++- sql/field.cc | 15 ++++++++------- sql/sql_yacc.yy | 3 ++- strings/ctype-big5.c | 6 +++++- strings/ctype-mb.c | 9 ++++++--- strings/ctype-simple.c | 6 +++--- strings/ctype-sjis.c | 5 ++++- strings/ctype-ucs2.c | 6 +++--- strings/ctype-ujis.c | 13 +++++++++++-- 12 files changed, 57 insertions(+), 27 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index 26e285b9683..aab39156de1 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -147,7 +147,8 @@ typedef struct my_charset_handler_st uint (*numchars)(struct charset_info_st *, const char *b, const char *e); uint (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos); uint (*well_formed_len)(struct charset_info_st *, - const char *b,const char *e, uint nchars); + const char *b,const char *e, + uint nchars, int *error); uint (*lengthsp)(struct charset_info_st *, const char *ptr, uint length); uint (*numcells)(struct charset_info_st *, const char *b, const char *e); @@ -341,7 +342,8 @@ int my_wildcmp_8bit(CHARSET_INFO *, uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e); uint my_numcells_8bit(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); -uint my_well_formed_len_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos); +uint my_well_formed_len_8bit(CHARSET_INFO *, const char *b, const char *e, + uint pos, int *error); int my_mbcharlen_8bit(CHARSET_INFO *, uint c); @@ -359,7 +361,8 @@ int my_wildcmp_mb(CHARSET_INFO *, uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e); uint my_numcells_mb(CHARSET_INFO *, const char *b, const char *e); uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); -uint my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e, uint pos); +uint my_well_formed_len_mb(CHARSET_INFO *, const char *b, const char *e, + uint pos, int *error); uint my_instr_mb(struct charset_info_st *, const char *b, uint b_length, const char *s, uint s_length, diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp index 23af646c4c7..39da9c5f5d0 100644 --- a/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -354,12 +354,14 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo, *************************************************************************/ if ((tOpType == WriteRequest)) { if (!tAttrInfo->m_indexOnly){ + int dummy_error; // invalid data can crash kernel if (cs != NULL && (*cs->cset->well_formed_len)(cs, aValueToWrite, aValueToWrite + sizeInBytes, - sizeInBytes) != sizeInBytes) + sizeInBytes, + &dummy_error) != sizeInBytes) goto equal_error4; Uint32 ahValue; Uint32 sz = totalSizeInWords; diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp index c4aaffb3119..dfc54133e6c 100644 --- a/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -526,6 +526,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize; CHARSET_INFO* cs = tAttrInfo->m_cs; + int dummy_error; // invalid data can crash kernel if (cs != NULL && // fast fix bug#7340 @@ -533,7 +534,8 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, (*cs->cset->well_formed_len)(cs, aValue, aValue + sizeInBytes, - sizeInBytes) != sizeInBytes) { + sizeInBytes, + &dummy_error) != sizeInBytes) { setErrorCodeAbort(744); return -1; } diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp index 28a70abcb9b..97b2393e5ed 100644 --- a/ndb/src/ndbapi/NdbOperationSearch.cpp +++ b/ndb/src/ndbapi/NdbOperationSearch.cpp @@ -226,12 +226,14 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo, if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) { if (!tAttrInfo->m_indexOnly){ + int dummy_error; // invalid data can crash kernel if (cs != NULL && (*cs->cset->well_formed_len)(cs, aValueToWrite, aValueToWrite + sizeInBytes, - sizeInBytes) != sizeInBytes) + sizeInBytes, + &dummy_error) != sizeInBytes) goto equal_error4; Uint32 ahValue; const Uint32 sz = totalSizeInWords; diff --git a/sql/field.cc b/sql/field.cc index bf581e62f34..740c027350d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4939,9 +4939,10 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) as well as don't copy a malformed data. */ copy_length= field_charset->cset->well_formed_len(field_charset, - from,from+length, - field_length/ - field_charset->mbmaxlen); + from,from+length, + field_length/ + field_charset->mbmaxlen, + &error); memcpy(ptr,from,copy_length); if (copy_length < field_length) // Append spaces if shorter field_charset->cset->fill(field_charset,ptr+copy_length, @@ -4958,7 +4959,6 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) } if (error) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); - return error; } @@ -5577,9 +5577,10 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) the 'min()' call below. */ copy_length= field_charset->cset->well_formed_len(field_charset, - from,from + - min(length, copy_length), - copy_length); + from,from + + min(length, copy_length), + copy_length, + &error); if (copy_length < length) error= 1; Field_blob::store_length(copy_length); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9f25e17b6fd..dcda19a7080 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5032,9 +5032,10 @@ IDENT_sys: if (thd->charset_is_system_charset) { CHARSET_INFO *cs= system_charset_info; + int dummy_error; uint wlen= cs->cset->well_formed_len(cs, $1.str, $1.str+$1.length, - $1.length); + $1.length, &dummy_error); if (wlen < $1.length) { net_printf(YYTHD, ER_INVALID_CHARACTER_STRING, cs->csname, diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index e083d1371ec..07b30205f89 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6278,10 +6278,13 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), */ static uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) + const char *b, const char *e, + uint pos, int *error) { const char *b0= b; const char *emb= e - 1; /* Last possible end of an MB character */ + + *error= 0; while (pos && b < e) { if ((uchar) b[0] < 128) @@ -6297,6 +6300,7 @@ uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)), else { /* Wrong byte sequence */ + *error= 1; break; } } diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 6cf48291c91..dbe3a24324e 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -264,18 +264,21 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), } -uint my_well_formed_len_mb(CHARSET_INFO *cs, - const char *b, const char *e, uint pos) +uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e, + uint pos, int *error) { const char *b_start= b; - + *error= 0; while (pos) { my_wc_t wc; int mblen; if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0) + { + *error= 1; break; + } b+= mblen; pos--; } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 080e0b780b7..bd5131b7448 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1093,11 +1093,11 @@ uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)), uint my_well_formed_len_8bit(CHARSET_INFO *cs __attribute__((unused)), - const char *start, - const char *end, - uint nchars) + const char *start, const char *end, + uint nchars, int *error) { uint nbytes= (uint) (end-start); + *error= 0; return min(nbytes, nchars); } diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 20f0081888f..35182db3345 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4571,9 +4571,11 @@ uint my_numcells_sjis(CHARSET_INFO *cs __attribute__((unused)), */ static uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) + const char *b, const char *e, + uint pos, int *error) { const char *b0= b; + *error= 0; while (pos && b < e) { if ((uchar) b[0] < 128) @@ -4594,6 +4596,7 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)), else { /* Wrong byte sequence */ + *error= 1; break; } } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 9c67d1b7846..f5d0721fa9b 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1267,11 +1267,11 @@ uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)), static uint my_well_formed_len_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *b, - const char *e, - uint nchars) + const char *b, const char *e, + uint nchars, int *error) { uint nbytes= (e-b) & ~ (uint)1; + *error= 0; nchars*= 2; return min(nbytes, nchars); } diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index fc1496df280..612dda2b3eb 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8253,11 +8253,12 @@ my_jisx0212_uni_onechar(int code){ static uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), - const char *beg, const char *end, uint pos) + const char *beg, const char *end, + uint pos, int *error) { const uchar *b= (uchar *) beg; - for ( ; pos && b < (uchar*) end; pos--, b++) + for ( *error= 0 ; pos && b < (uchar*) end; pos--, b++) { char *chbeg; uint ch= *b; @@ -8267,12 +8268,16 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), chbeg= (char *) b++; if (b >= (uchar *) end) /* need more bytes */ + { + *error= 1; return chbeg - beg; /* unexpected EOL */ + } if (ch == 0x8E) /* [x8E][xA0-xDF] */ { if (*b >= 0xA0 && *b <= 0xDF) continue; + *error= 1; return chbeg - beg; /* invalid sequence */ } @@ -8280,12 +8285,16 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), { ch= *b++; if (b >= (uchar*) end) + { + *error= 1; return chbeg - beg; /* unexpected EOL */ + } } if (ch >= 0xA1 && ch <= 0xFE && *b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */ continue; + *error= 1; return chbeg - beg; /* invalid sequence */ } return b - (uchar *) beg; From 97b26d3b93abef87bc6918af326202467212e103 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Apr 2005 10:27:40 +0300 Subject: [PATCH 5/9] row0sel.c, btr0pcur.c, btr0pcur.ic, btr0pcur.h: Add diagnostic code to track assertion failure in ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); the failure happened in OPTIMIZE TABLE, and in 4.0.24 in some other context innobase/include/btr0pcur.h: Add diagnostic code to track assertion failure in ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); the failure happened in OPTIMIZE TABLE, and in 4.0.24 in some other context innobase/include/btr0pcur.ic: Add diagnostic code to track assertion failure in ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); the failure happened in OPTIMIZE TABLE, and in 4.0.24 in some other context innobase/btr/btr0pcur.c: Add diagnostic code to track assertion failure in ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); the failure happened in OPTIMIZE TABLE, and in 4.0.24 in some other context innobase/row/row0sel.c: Add diagnostic code to track assertion failure in ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); the failure happened in OPTIMIZE TABLE, and in 4.0.24 in some other context --- innobase/btr/btr0pcur.c | 10 +++++++++- innobase/include/btr0pcur.h | 4 ++++ innobase/include/btr0pcur.ic | 10 ++++++++++ innobase/row/row0sel.c | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index cf8a612ef28..0dcf6c2f3fc 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -14,6 +14,7 @@ Created 2/23/1996 Heikki Tuuri #include "ut0byte.h" #include "rem0cmp.h" +#include "trx0trx.h" /****************************************************************** Allocates memory for a persistent cursor object and initializes the cursor. */ @@ -203,7 +204,14 @@ btr_pcur_restore_position( ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED || cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); + if (cursor->old_stored != BTR_PCUR_OLD_STORED) { + ut_print_buf(stderr, (const byte*)cursor, sizeof(btr_pcur_t)); + if (cursor->trx_if_known) { + trx_print(stderr, cursor->trx_if_known); + } + + ut_a(0); + } if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h index 81f19af4d40..9339eb5d0ee 100644 --- a/innobase/include/btr0pcur.h +++ b/innobase/include/btr0pcur.h @@ -477,6 +477,10 @@ struct btr_pcur_struct{ BTR_PCUR_WAS_POSITIONED, BTR_PCUR_NOT_POSITIONED */ ulint search_mode; /* PAGE_CUR_G, ... */ + trx_t* trx_if_known; /* the transaction, if we know it; + otherwise this field is not defined; + can ONLY BE USED in error prints in + fatal assertion failures! */ /*-----------------------------*/ /* NOTE that the following fields may possess dynamically allocated memory which should be freed if not needed anymore! */ diff --git a/innobase/include/btr0pcur.ic b/innobase/include/btr0pcur.ic index b553a569bda..9a7d7867025 100644 --- a/innobase/include/btr0pcur.ic +++ b/innobase/include/btr0pcur.ic @@ -493,6 +493,8 @@ btr_pcur_open( btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, btr_cursor, 0, mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; + + cursor->trx_if_known = NULL; } /****************************************************************** @@ -535,6 +537,8 @@ btr_pcur_open_with_no_init( cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; + + cursor->trx_if_known = NULL; } /********************************************************************* @@ -568,6 +572,8 @@ btr_pcur_open_at_index_side( pcur->pos_state = BTR_PCUR_IS_POSITIONED; pcur->old_stored = BTR_PCUR_OLD_NOT_STORED; + + pcur->trx_if_known = NULL; } /************************************************************************** @@ -592,6 +598,8 @@ btr_pcur_open_at_rnd_pos( btr_pcur_get_btr_cur(cursor), mtr); cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; + + cursor->trx_if_known = NULL; } /****************************************************************** @@ -617,4 +625,6 @@ btr_pcur_close( cursor->latch_mode = BTR_NO_LATCHES; cursor->pos_state = BTR_PCUR_NOT_POSITIONED; + + cursor->trx_if_known = NULL; } diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 07140e74e54..eb88ac31ba9 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2507,6 +2507,8 @@ row_sel_get_clust_rec_for_mysql( clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur); + prebuilt->clust_pcur->trx_if_known = trx; + /* Note: only if the search ends up on a non-infimum record is the low_match value the real match to the search tuple */ @@ -3222,6 +3224,8 @@ shortcut_fails_too_big_rec: btr_pcur_open_with_no_init(index, search_tuple, mode, BTR_SEARCH_LEAF, pcur, 0, &mtr); + + pcur->trx_if_known = trx; } else { if (mode == PAGE_CUR_G) { btr_pcur_open_at_index_side(TRUE, index, From 31d15c3f76f84e3ebf6d6158cff7a454c5a8d222 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Apr 2005 14:13:06 +0500 Subject: [PATCH 6/9] Fix for bug #9286: SESSION/GLOBAL should be disallowed for user variables BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/user_var.result | 4 +++ mysql-test/t/user_var.test | 8 +++++ sql/sql_yacc.yy | 66 +++++++++++++++++++++--------------- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 90e6c3c100d..9237eea21c4 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -51,6 +51,7 @@ georg@lmy002.wdf.sap.corp gerberb@ou800.zenez.com gluh@gluh.(none) gluh@gluh.mysql.r18.ru +gluh@mysql.com gordon@zero.local.lan greg@gcw.ath.cx greg@mysql.com diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 9edeea404ec..e42849abdf1 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -175,3 +175,7 @@ set @v1=null, @v2=1, @v3=1.1, @v4=now(); select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4) 2 2 2 2 +set session @honk=99; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@honk=99' at line 1 +set one_shot @honk=99; +ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index b907f21056c..a288b7ef708 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -111,3 +111,11 @@ select FIELD( @var,'1it','Hit') as my_column; select @v, coercibility(@v); set @v1=null, @v2=1, @v3=1.1, @v4=now(); select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); + +# +# Bug #9286 SESSION/GLOBAL should be disallowed for user variables +# +--error 1064 +set session @honk=99; +--error 1105 +set one_shot @honk=99; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9f25e17b6fd..4a23a393fa9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5360,17 +5360,26 @@ opt_option: | OPTION {}; option_value_list: - option_type option_value - | option_value_list ',' option_type option_value; + option_value_ext + | option_value_list ',' option_value_ext; -option_type: - /* empty */ {} +option_value_ext: + option_type_ext sys_option_value {} + | option_type option_value {} + ; + +option_type_ext: + option_type {} | GLOBAL_SYM { Lex->option_type= OPT_GLOBAL; } | LOCAL_SYM { Lex->option_type= OPT_SESSION; } | SESSION_SYM { Lex->option_type= OPT_SESSION; } - | ONE_SHOT_SYM { Lex->option_type= OPT_SESSION; Lex->one_shot_set= 1; } ; +option_type: + /* empty */ {} + | ONE_SHOT_SYM { Lex->option_type= OPT_SESSION; Lex->one_shot_set= 1; } + ; + opt_var_type: /* empty */ { $$=OPT_SESSION; } | GLOBAL_SYM { $$=OPT_GLOBAL; } @@ -5385,34 +5394,37 @@ opt_var_ident_type: | SESSION_SYM '.' { $$=OPT_SESSION; } ; +sys_option_value: + internal_variable_name equal set_expr_or_default + { + LEX *lex=Lex; + lex->var_list.push_back(new set_var(lex->option_type, $1.var, + &$1.base_name, $3)); + } + | TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types + { + LEX *lex=Lex; + LEX_STRING tmp; + tmp.str=0; + tmp.length=0; + lex->var_list.push_back(new set_var(lex->option_type, + find_sys_var("tx_isolation"), + &tmp, + new Item_int((int32) $4))); + } + ; + option_value: '@' ident_or_text equal expr { Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4))); } - | internal_variable_name equal set_expr_or_default - { - LEX *lex=Lex; - lex->var_list.push_back(new set_var(lex->option_type, $1.var, - &$1.base_name, $3)); - } | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default - { - LEX *lex=Lex; - lex->var_list.push_back(new set_var((enum_var_type) $3, $4.var, - &$4.base_name, $6)); - } - | TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types - { - LEX *lex=Lex; - LEX_STRING tmp; - tmp.str=0; - tmp.length=0; - lex->var_list.push_back(new set_var(lex->option_type, - find_sys_var("tx_isolation"), - &tmp, - new Item_int((int32) $4))); - } + { + LEX *lex=Lex; + lex->var_list.push_back(new set_var((enum_var_type) $3, $4.var, + &$4.base_name, $6)); + } | charset old_or_new_charset_name_or_default { THD *thd= YYTHD; From 3683fc3453ad0fdd0f0437aaf562dd19a2defa5a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Apr 2005 15:12:44 +0500 Subject: [PATCH 7/9] Minor clean-ups for the previous commit. sql/field.cc: Use a separate variable. Otherwise "error" value gets lost after well_formed_length call. strings/ctype-mb.c: Don't return an error if we reached end of line. --- sql/field.cc | 8 ++++---- strings/ctype-mb.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 740c027350d..d73257a673f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4914,7 +4914,7 @@ void Field_datetime::sql_type(String &res) const int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0; + int error= 0, well_formed_error; uint32 not_used; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); @@ -4942,7 +4942,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) from,from+length, field_length/ field_charset->mbmaxlen, - &error); + &well_formed_error); memcpy(ptr,from,copy_length); if (copy_length < field_length) // Append spaces if shorter field_charset->cset->fill(field_charset,ptr+copy_length, @@ -5545,7 +5545,7 @@ void Field_blob::put_length(char *pos, uint32 length) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0; + int error= 0, well_formed_error; if (!length) { bzero(ptr,Field_blob::pack_length()); @@ -5580,7 +5580,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) from,from + min(length, copy_length), copy_length, - &error); + &well_formed_error); if (copy_length < length) error= 1; Field_blob::store_length(copy_length); diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index dbe3a24324e..cbbd035c631 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -276,7 +276,7 @@ uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e, if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0) { - *error= 1; + *error= b < e ? 1 : 0; break; } b+= mblen; From cde615c9cbff404b6a6c82a1ab7a6bcb8742b88e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Apr 2005 15:09:15 +0300 Subject: [PATCH 8/9] InnoDB: Avoid test suite failures caused by a locking conflict between two server instances at server shutdown/startup. This conflict on advisory locks appears to be the result of a bug in the operating system; these locks should be released when the files are closed, but somehow that does not always happen immediately in Linux. (Bug #9381) innobase/include/os0file.h: Add OS_FILE_OPEN_RETRY for os_file_create()ing ibdata1 innobase/os/os0file.c: os_file_lock(): Do not close the file on failure, but let the callers do that. os_file_create(): If create_mode==OS_FILE_OPEN_RETRY and os_file_lock() fails, keep retrying for 100 seconds. innobase/srv/srv0start.c: open_or_create_data_files(): Open the first data file with OS_FILE_OPEN_RETRY, to resolve a conflict with a shutting-down instance of the MySQL server. --- innobase/include/os0file.h | 2 ++ innobase/os/os0file.c | 27 +++++++++++++++++++++++---- innobase/srv/srv0start.c | 5 +++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index d1439faf29f..ebc014df9fd 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -65,6 +65,8 @@ log. */ #define OS_FILE_OVERWRITE 53 #define OS_FILE_OPEN_RAW 54 #define OS_FILE_CREATE_PATH 55 +#define OS_FILE_OPEN_RETRY 56 /* for os_file_create() on + the first ibdata file */ #define OS_FILE_READ_ONLY 333 #define OS_FILE_READ_WRITE 444 diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 8d1ad895aa9..15f5bf40e51 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -402,8 +402,6 @@ os_file_lock( "InnoDB: using the same InnoDB data or log files.\n"); } - close(fd); - return(-1); } @@ -978,6 +976,7 @@ try_again: } else if (access_type == OS_FILE_READ_WRITE && os_file_lock(file, name)) { *success = FALSE; + close(file); file = -1; #endif } else { @@ -1090,6 +1089,7 @@ os_file_create_simple_no_error_handling( } else if (access_type == OS_FILE_READ_WRITE && os_file_lock(file, name)) { *success = FALSE; + close(file); file = -1; #endif } else { @@ -1141,7 +1141,8 @@ try_again: if (create_mode == OS_FILE_OPEN_RAW) { create_flag = OPEN_EXISTING; share_mode = FILE_SHARE_WRITE; - } else if (create_mode == OS_FILE_OPEN) { + } else if (create_mode == OS_FILE_OPEN + || create_mode == OS_FILE_OPEN_RETRY) { create_flag = OPEN_EXISTING; } else if (create_mode == OS_FILE_CREATE) { create_flag = CREATE_NEW; @@ -1232,7 +1233,8 @@ try_again: try_again: ut_a(name); - if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW) { + if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW + || create_mode == OS_FILE_OPEN_RETRY) { mode_str = "OPEN"; create_flag = O_RDWR; } else if (create_mode == OS_FILE_CREATE) { @@ -1305,6 +1307,23 @@ try_again: } else if (create_mode != OS_FILE_OPEN_RAW && os_file_lock(file, name)) { *success = FALSE; + if (create_mode == OS_FILE_OPEN_RETRY) { + int i; + ut_print_timestamp(stderr); + fputs(" InnoDB: Retrying to lock the first data file\n", + stderr); + for (i = 0; i < 100; i++) { + os_thread_sleep(1000000); + if (!os_file_lock(file, name)) { + *success = TRUE; + return(file); + } + } + ut_print_timestamp(stderr); + fputs(" InnoDB: Unable to open the first data file\n", + stderr); + } + close(file); file = -1; #endif } else { diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 44cf645f170..62df7301cc9 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -789,6 +789,11 @@ open_or_create_data_files( files[i] = os_file_create( name, OS_FILE_OPEN_RAW, OS_FILE_NORMAL, OS_DATA_FILE, &ret); + } else if (i == 0) { + files[i] = os_file_create( + name, OS_FILE_OPEN_RETRY, + OS_FILE_NORMAL, + OS_DATA_FILE, &ret); } else { files[i] = os_file_create( name, OS_FILE_OPEN, OS_FILE_NORMAL, From 1fcebd5549f1055954254fc77160a424177351ad Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Apr 2005 23:12:10 +0200 Subject: [PATCH 9/9] after merge fix mysql-test/r/user_var.result: after merge fixes - old (erroneous) results restored. Should be corrected when the fix is applied mysql-test/t/user_var.test: after merge fixes - old (erroneous) results restored. Should be corrected when the fix is applied --- mysql-test/r/user_var.result | 3 +-- mysql-test/t/user_var.test | 3 +-- ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp | 3 ++- strings/ctype-cp932.c | 4 +++- strings/ctype-eucjpms.c | 11 +++++++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index d36dca86e39..68eae111111 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -180,6 +180,5 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); coercibility(@v1) coercibility(@v2) coercibility(@v3) coercibility(@v4) 2 2 2 2 set session @honk=99; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@honk=99' at line 1 set one_shot @honk=99; -ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server +ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 49941bc81f3..ef360f2231d 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -116,7 +116,6 @@ select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4); # # Bug #9286 SESSION/GLOBAL should be disallowed for user variables # ---error 1064 set session @honk=99; ---error 1105 +--error 1382 set one_shot @honk=99; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index c3f85cdebd5..3170d23499a 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -813,6 +813,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer, ndbrequire(i < regTabPtr->noOfCharsets); // not const in MySQL CHARSET_INFO* cs = regTabPtr->charsetArray[i]; + int not_used; const char* ssrc = (const char*)&inBuffer[tInBufIndex + 1]; Uint32 lb, len; if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) { @@ -822,7 +823,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer, } // fast fix bug#7340 if (typeId != NDB_TYPE_TEXT && - (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL) != len) { + (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, ¬_used) != len) { ljam(); terrorCode = ZINVALID_CHAR_FORMAT; return false; diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index c47f2c2d8ce..47bf1167c8c 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5413,9 +5413,10 @@ uint my_numcells_cp932(CHARSET_INFO *cs __attribute__((unused)), */ static uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)), - const char *b, const char *e, uint pos) + const char *b, const char *e, uint pos, int *error) { const char *b0= b; + *error= 0; while (pos && b < e) { /* @@ -5441,6 +5442,7 @@ uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)), else { /* Wrong byte sequence */ + *error= 1; break; } } diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 8c8d237cf48..346b5ecdf6b 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -8380,17 +8380,18 @@ my_jisx0212_uni_onechar(int code){ /* EUC-JP encoding subcomponents: - [x00-x7F] # ASCII/JIS-Roman (one-byte/character) - [x8E][xA0-xDF] # half-width katakana (two bytes/char) - [x8F][xA1-xFE][xA1-xFE] # JIS X 0212-1990 (three bytes/char) + [x00-x7F] # ASCII/JIS-Roman (one-byte/character) + [x8E][xA0-xDF] # half-width katakana (two bytes/char) + [x8F][xA1-xFE][xA1-xFE] # JIS X 0212-1990 (three bytes/char) [xA1-xFE][xA1-xFE] # JIS X 0208:1997 (two bytes/char) */ static uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), - const char *beg, const char *end, uint pos) + const char *beg, const char *end, uint pos, int *error) { const uchar *b= (uchar *) beg; + *error=0; for ( ; pos && b < (uchar*) end; pos--, b++) { @@ -8408,6 +8409,7 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), { if (*b >= 0xA0 && *b <= 0xDF) continue; + *error=1; return chbeg - beg; /* invalid sequence */ } @@ -8421,6 +8423,7 @@ uint my_well_formed_len_eucjpms(CHARSET_INFO *cs __attribute__((unused)), if (ch >= 0xA1 && ch <= 0xFE && *b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */ continue; + *error=1; return chbeg - beg; /* invalid sequence */ } return b - (uchar *) beg;