From 2d47b244b2fca7048fc9c4e5103c5653636e0784 Mon Sep 17 00:00:00 2001 From: "jmiller/root@mysql.com/ndbqa01.mysql.com" <> Date: Thu, 5 Jul 2007 07:42:12 -0500 Subject: [PATCH 01/92] ndb api test case for bug 29501 --- storage/ndb/test/ndbapi/testDict.cpp | 255 ++++++++++++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 8 + 2 files changed, 263 insertions(+) diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp index 13c071f968e..b17cc4d159f 100644 --- a/storage/ndb/test/ndbapi/testDict.cpp +++ b/storage/ndb/test/ndbapi/testDict.cpp @@ -2706,7 +2706,262 @@ runDictRestart(NDBT_Context* ctx, NDBT_Step* step) return NDBT_OK; } +int +runBug29501(NDBT_Context* ctx, NDBT_Step* step) { + NdbRestarter res; + NdbDictionary::LogfileGroup lg; + lg.setName("DEFAULT-LG"); + lg.setUndoBufferSize(8*1024*1024); + + if (res.getNumDbNodes() < 2) + return NDBT_OK; + + Ndb* pNdb = GETNDB(step); + NdbDictionary::Dictionary* pDict = pNdb->getDictionary(); + + int node = res.getRandomNotMasterNodeId(rand()); + res.restartOneDbNode(node, true, true, false); + + if(pDict->createLogfileGroup(lg) != 0){ + g_err << "Failed to create logfilegroup:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + NdbDictionary::Undofile uf; + uf.setPath("undofile01.dat"); + uf.setSize(5*1024*1024); + uf.setLogfileGroup("DEFAULT-LG"); + + if(pDict->createUndofile(uf) != 0){ + g_err << "Failed to create undofile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + res.waitNodesNoStart(&node, 1); + res.startNodes(&node, 1); + + if (res.waitClusterStarted()){ + g_err << "Node restart failed" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lg.getName())) != 0){ + g_err << "Drop of LFG Failed" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int +runDropDDObjects(NDBT_Context* ctx, NDBT_Step* step){ + //Purpose is to drop all tables, data files, Table spaces and LFG's + Uint32 i = 0; + + Ndb* pNdb = GETNDB(step); + NdbDictionary::Dictionary* pDict = pNdb->getDictionary(); + + NdbDictionary::Dictionary::List list; + if (pDict->listObjects(list) == -1) + return NDBT_FAILED; + + //Search the list and drop all tables found + const char * tableFound = 0; + for (i = 0; i < list.count; i++){ + switch(list.elements[i].type){ + case NdbDictionary::Object::UserTable: + tableFound = list.elements[i].name; + if(tableFound != 0){ + if(pDict->dropTable(tableFound) != 0){ + g_err << "Failed to drop table: " << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + tableFound = 0; + break; + default: + break; + } + } + + //Search the list and drop all data file found + const char * dfFound = 0; + for (i = 0; i < list.count; i++){ + switch(list.elements[i].type){ + case NdbDictionary::Object::Datafile: + dfFound = list.elements[i].name; + if(dfFound != 0){ + if(pDict->dropDatafile(pDict->getDatafile(0, dfFound)) != 0){ + g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + dfFound = 0; + break; + default: + break; + } + } + + //Search the list and drop all Table Spaces Found + const char * tsFound = 0; + for (i = 0; i dropTablespace(pDict->getTablespace(tsFound)) != 0){ + g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + tsFound = 0; + break; + default: + break; + } + } + + //Search the list and drop all LFG Found + //Currently only 1 LGF is supported, but written for future + //when more then one is supported. + const char * lgFound = 0; + for (i = 0; i < list.count; i++){ + switch(list.elements[i].type){ + case NdbDictionary::Object::LogfileGroup: + lgFound = list.elements[i].name; + if(lgFound != 0){ + if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgFound)) != 0){ + g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + } + lgFound = 0; + break; + default: + break; + } + } + + return NDBT_OK; +} + +int +runWaitStarted(NDBT_Context* ctx, NDBT_Step* step){ + + NdbRestarter restarter; + restarter.waitClusterStarted(300); + + NdbSleep_SecSleep(3); + return NDBT_OK; +} + +int +testDropDDObjectsSetup(NDBT_Context* ctx, NDBT_Step* step){ + //Purpose is to setup to test DropDDObjects + char tsname[256]; + char dfname[256]; + + Ndb* pNdb = GETNDB(step); + NdbDictionary::Dictionary* pDict = pNdb->getDictionary(); + + NdbDictionary::LogfileGroup lg; + lg.setName("DEFAULT-LG"); + lg.setUndoBufferSize(8*1024*1024); + + + if(pDict->createLogfileGroup(lg) != 0){ + g_err << "Failed to create logfilegroup:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + NdbDictionary::Undofile uf; + uf.setPath("undofile01.dat"); + uf.setSize(5*1024*1024); + uf.setLogfileGroup("DEFAULT-LG"); + + if(pDict->createUndofile(uf) != 0){ + g_err << "Failed to create undofile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand()); + BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand()); + + if (create_tablespace(pDict, lg.getName(), tsname, dfname)){ + g_err << "Failed to create undofile:" + << endl << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + return NDBT_OK; +} + +int +DropDDObjectsVerify(NDBT_Context* ctx, NDBT_Step* step){ + //Purpose is to verify test DropDDObjects worked + Uint32 i = 0; + + Ndb* pNdb = GETNDB(step); + NdbDictionary::Dictionary* pDict = pNdb->getDictionary(); + + NdbDictionary::Dictionary::List list; + if (pDict->listObjects(list) == -1) + return NDBT_FAILED; + + bool ddFound = false; + for (i = 0; i Date: Fri, 14 Sep 2007 00:10:47 +0200 Subject: [PATCH 02/92] BUG#30996: Committed too early when autocommit and lock table Moved out a lot of code into functions from external_lock and start_stmt Fixed a crashing bug at memory alloc failure Merged the stmt and all variables into one trans variable Always register start of statement as according to the interface of the handlers. Also register for start of transaction when not statement commit == not autocommit AND no begin - commit ongoing Now that we registered in a proper manner we also needed to handle the commit call when end of statement and transaction is ongoing Added start_stmt_count to know when we have start of statement for first table --- mysql-test/suite/ndb/r/ndb_lock_table.result | 11 + mysql-test/suite/ndb/t/ndb_lock_table.test | 15 + sql/ha_ndbcluster.cc | 329 ++++++++++--------- sql/ha_ndbcluster.h | 8 +- 4 files changed, 198 insertions(+), 165 deletions(-) create mode 100644 mysql-test/suite/ndb/r/ndb_lock_table.result create mode 100644 mysql-test/suite/ndb/t/ndb_lock_table.test diff --git a/mysql-test/suite/ndb/r/ndb_lock_table.result b/mysql-test/suite/ndb/r/ndb_lock_table.result new file mode 100644 index 00000000000..a0550273e1a --- /dev/null +++ b/mysql-test/suite/ndb/r/ndb_lock_table.result @@ -0,0 +1,11 @@ +drop table if exists t1; +create table t1 (a int) engine ndb; +set autocommit=1; +lock table t1 write; +set autocommit=0; +insert into t1 values (0); +rollback; +select * from t1; +a +unlock tables; +drop table t1; diff --git a/mysql-test/suite/ndb/t/ndb_lock_table.test b/mysql-test/suite/ndb/t/ndb_lock_table.test new file mode 100644 index 00000000000..6c21e8e8232 --- /dev/null +++ b/mysql-test/suite/ndb/t/ndb_lock_table.test @@ -0,0 +1,15 @@ +-- source include/have_ndb.inc + +# BUG 30996 +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int) engine ndb; +set autocommit=1; +lock table t1 write; +set autocommit=0; +insert into t1 values (0); +rollback; +select * from t1; +unlock tables; +drop table t1; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 1ec6898078f..c090f2a4cde 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -325,9 +325,9 @@ Thd_ndb::Thd_ndb() { ndb= new Ndb(g_ndb_cluster_connection, ""); lock_count= 0; + start_stmt_count= 0; count= 0; - all= NULL; - stmt= NULL; + trans= NULL; m_error= FALSE; m_error_code= 0; query_state&= NDB_QUERY_NORMAL; @@ -382,6 +382,11 @@ Thd_ndb::get_open_table(THD *thd, const void *key) { thd_ndb_share= (THD_NDB_SHARE *) alloc_root(&thd->transaction.mem_root, sizeof(THD_NDB_SHARE)); + if (!thd_ndb_share) + { + mem_alloc_error(sizeof(THD_NDB_SHARE)); + DBUG_RETURN(NULL); + } thd_ndb_share->key= key; thd_ndb_share->stat.last_count= count; thd_ndb_share->stat.no_uncommitted_rows_count= 0; @@ -4327,7 +4332,7 @@ static int ndbcluster_update_apply_status(THD *thd, int do_update) Ndb *ndb= thd_ndb->ndb; NDBDICT *dict= ndb->getDictionary(); const NDBTAB *ndbtab; - NdbTransaction *trans= thd_ndb->all ? thd_ndb->all : thd_ndb->stmt; + NdbTransaction *trans= thd_ndb->trans; ndb->setDatabaseName(NDB_REP_DB); Ndb_table_guard ndbtab_g(dict, NDB_APPLY_TABLE); if (!(ndbtab= ndbtab_g.get_table())) @@ -4371,10 +4376,110 @@ static int ndbcluster_update_apply_status(THD *thd, int do_update) } #endif /* HAVE_NDB_BINLOG */ +void ha_ndbcluster::transaction_checks(THD *thd) +{ + if (thd->lex->sql_command == SQLCOM_LOAD) + { + m_transaction_on= FALSE; + /* Would be simpler if has_transactions() didn't always say "yes" */ + thd->transaction.all.modified_non_trans_table= + thd->transaction.stmt.modified_non_trans_table= TRUE; + } + else if (!thd->transaction.on) + m_transaction_on= FALSE; + else + m_transaction_on= thd->variables.ndb_use_transactions; +} + +int ha_ndbcluster::start_statement(THD *thd, + Thd_ndb *thd_ndb, + Ndb *ndb) +{ + DBUG_ENTER("ha_ndbcluster::start_statement"); + PRINT_OPTION_FLAGS(thd); + + trans_register_ha(thd, FALSE, ndbcluster_hton); + if (!thd_ndb->trans) + { + if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + trans_register_ha(thd, TRUE, ndbcluster_hton); + DBUG_PRINT("trans",("Starting transaction")); + thd_ndb->trans= ndb->startTransaction(); + if (thd_ndb->trans == NULL) + ERR_RETURN(ndb->getNdbError()); + thd_ndb->init_open_tables(); + thd_ndb->query_state&= NDB_QUERY_NORMAL; + thd_ndb->trans_options= 0; + thd_ndb->m_slow_path= FALSE; + if (!(thd->options & OPTION_BIN_LOG) || + thd->variables.binlog_format == BINLOG_FORMAT_STMT) + { + thd_ndb->trans_options|= TNTO_NO_LOGGING; + thd_ndb->m_slow_path= TRUE; + } + else if (thd->slave_thread) + thd_ndb->m_slow_path= TRUE; + } + /* + If this is the start of a LOCK TABLE, a table look + should be taken on the table in NDB + + Check if it should be read or write lock + */ + if (thd->options & (OPTION_TABLE_LOCK)) + { + //lockThisTable(); + DBUG_PRINT("info", ("Locking the table..." )); + } + DBUG_RETURN(0); +} + +int ha_ndbcluster::init_handler_for_statement(THD *thd, Thd_ndb *thd_ndb) +{ + /* + This is the place to make sure this handler instance + has a started transaction. + + The transaction is started by the first handler on which + MySQL Server calls external lock + + Other handlers in the same stmt or transaction should use + the same NDB transaction. This is done by setting up the m_active_trans + pointer to point to the NDB transaction. + */ + + DBUG_ENTER("ha_ndbcluster::init_handler_for_statement"); + // store thread specific data first to set the right context + m_force_send= thd->variables.ndb_force_send; + m_ha_not_exact_count= !thd->variables.ndb_use_exact_count; + m_autoincrement_prefetch= + (ha_rows) thd->variables.ndb_autoincrement_prefetch_sz; + + m_active_trans= thd_ndb->trans; + DBUG_ASSERT(m_active_trans); + // Start of transaction + m_rows_changed= 0; + m_ops_pending= 0; + m_slow_path= thd_ndb->m_slow_path; +#ifdef HAVE_NDB_BINLOG + if (unlikely(m_slow_path)) + { + if (m_share == ndb_apply_status_share && thd->slave_thread) + thd_ndb->trans_options|= TNTO_INJECTED_APPLY_STATUS; + } +#endif + // TODO remove double pointers... + if (!(m_thd_ndb_share= thd_ndb->get_open_table(thd, m_table))) + { + DBUG_RETURN(1); + } + m_table_info= &m_thd_ndb_share->stat; + DBUG_RETURN(0); +} + int ha_ndbcluster::external_lock(THD *thd, int lock_type) { int error=0; - NdbTransaction* trans= NULL; DBUG_ENTER("external_lock"); /* @@ -4395,124 +4500,15 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if (lock_type != F_UNLCK) { DBUG_PRINT("info", ("lock_type != F_UNLCK")); - if (thd->lex->sql_command == SQLCOM_LOAD) - { - m_transaction_on= FALSE; - /* Would be simpler if has_transactions() didn't always say "yes" */ - thd->transaction.all.modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table= TRUE; - } - else if (!thd->transaction.on) - m_transaction_on= FALSE; - else - m_transaction_on= thd->variables.ndb_use_transactions; + transaction_checks(thd); if (!thd_ndb->lock_count++) { - PRINT_OPTION_FLAGS(thd); - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) - { - // Autocommit transaction - DBUG_ASSERT(!thd_ndb->stmt); - DBUG_PRINT("trans",("Starting transaction stmt")); - - trans= ndb->startTransaction(); - if (trans == NULL) - { - thd_ndb->lock_count= 0; - ERR_RETURN(ndb->getNdbError()); - } - thd_ndb->init_open_tables(); - thd_ndb->stmt= trans; - thd_ndb->query_state&= NDB_QUERY_NORMAL; - thd_ndb->trans_options= 0; - thd_ndb->m_slow_path= FALSE; - if (!(thd->options & OPTION_BIN_LOG) || - thd->variables.binlog_format == BINLOG_FORMAT_STMT) - { - thd_ndb->trans_options|= TNTO_NO_LOGGING; - thd_ndb->m_slow_path= TRUE; - } - else if (thd->slave_thread) - thd_ndb->m_slow_path= TRUE; - trans_register_ha(thd, FALSE, ndbcluster_hton); - } - else - { - if (!thd_ndb->all) - { - // Not autocommit transaction - // A "master" transaction ha not been started yet - DBUG_PRINT("trans",("starting transaction, all")); - - trans= ndb->startTransaction(); - if (trans == NULL) - { - thd_ndb->lock_count= 0; - ERR_RETURN(ndb->getNdbError()); - } - thd_ndb->init_open_tables(); - thd_ndb->all= trans; - thd_ndb->query_state&= NDB_QUERY_NORMAL; - thd_ndb->trans_options= 0; - thd_ndb->m_slow_path= FALSE; - if (!(thd->options & OPTION_BIN_LOG) || - thd->variables.binlog_format == BINLOG_FORMAT_STMT) - { - thd_ndb->trans_options|= TNTO_NO_LOGGING; - thd_ndb->m_slow_path= TRUE; - } - else if (thd->slave_thread) - thd_ndb->m_slow_path= TRUE; - trans_register_ha(thd, TRUE, ndbcluster_hton); - - /* - If this is the start of a LOCK TABLE, a table look - should be taken on the table in NDB - - Check if it should be read or write lock - */ - if (thd->options & (OPTION_TABLE_LOCK)) - { - //lockThisTable(); - DBUG_PRINT("info", ("Locking the table..." )); - } - - } - } + if ((error= start_statement(thd, thd_ndb, ndb))) + goto error; } - /* - This is the place to make sure this handler instance - has a started transaction. - - The transaction is started by the first handler on which - MySQL Server calls external lock - - Other handlers in the same stmt or transaction should use - the same NDB transaction. This is done by setting up the m_active_trans - pointer to point to the NDB transaction. - */ - - // store thread specific data first to set the right context - m_force_send= thd->variables.ndb_force_send; - m_ha_not_exact_count= !thd->variables.ndb_use_exact_count; - m_autoincrement_prefetch= - (ha_rows) thd->variables.ndb_autoincrement_prefetch_sz; - - m_active_trans= thd_ndb->all ? thd_ndb->all : thd_ndb->stmt; - DBUG_ASSERT(m_active_trans); - // Start of transaction - m_rows_changed= 0; - m_ops_pending= 0; - m_slow_path= thd_ndb->m_slow_path; -#ifdef HAVE_NDB_BINLOG - if (unlikely(m_slow_path)) - { - if (m_share == ndb_apply_status_share && thd->slave_thread) - thd_ndb->trans_options|= TNTO_INJECTED_APPLY_STATUS; - } -#endif - // TODO remove double pointers... - m_thd_ndb_share= thd_ndb->get_open_table(thd, m_table); - m_table_info= &m_thd_ndb_share->stat; + if ((error= init_handler_for_statement(thd, thd_ndb))) + goto error; + DBUG_RETURN(0); } else { @@ -4540,16 +4536,19 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("trans", ("Last external_lock")); PRINT_OPTION_FLAGS(thd); - if (thd_ndb->stmt) + if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - /* - Unlock is done without a transaction commit / rollback. - This happens if the thread didn't update any rows - We must in this case close the transaction to release resources - */ - DBUG_PRINT("trans",("ending non-updating transaction")); - ndb->closeTransaction(m_active_trans); - thd_ndb->stmt= NULL; + if (thd_ndb->trans) + { + /* + Unlock is done without a transaction commit / rollback. + This happens if the thread didn't update any rows + We must in this case close the transaction to release resources + */ + DBUG_PRINT("trans",("ending non-updating transaction")); + ndb->closeTransaction(thd_ndb->trans); + thd_ndb->trans= NULL; + } } } m_table_info= NULL; @@ -4578,7 +4577,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if (m_ops_pending) DBUG_PRINT("warning", ("ops_pending != 0L")); m_ops_pending= 0; + DBUG_RETURN(0); } +error: + thd_ndb->lock_count--; DBUG_RETURN(error); } @@ -4610,25 +4612,20 @@ int ha_ndbcluster::start_stmt(THD *thd, thr_lock_type lock_type) { int error=0; DBUG_ENTER("start_stmt"); - PRINT_OPTION_FLAGS(thd); Thd_ndb *thd_ndb= get_thd_ndb(thd); - NdbTransaction *trans= (thd_ndb->stmt)?thd_ndb->stmt:thd_ndb->all; - if (!trans){ + transaction_checks(thd); + if (!thd_ndb->start_stmt_count++) + { Ndb *ndb= thd_ndb->ndb; - DBUG_PRINT("trans",("Starting transaction stmt")); - trans= ndb->startTransaction(); - if (trans == NULL) - ERR_RETURN(ndb->getNdbError()); - no_uncommitted_rows_reset(thd); - thd_ndb->stmt= trans; - thd_ndb->query_state&= NDB_QUERY_NORMAL; - trans_register_ha(thd, FALSE, ndbcluster_hton); + if ((error= start_statement(thd, thd_ndb, ndb))) + goto error; } - m_active_trans= trans; - // Start of statement - m_ops_pending= 0; - + if ((error= init_handler_for_statement(thd, thd_ndb))) + goto error; + DBUG_RETURN(0); +error: + thd_ndb->start_stmt_count--; DBUG_RETURN(error); } @@ -4642,15 +4639,27 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) int res= 0; Thd_ndb *thd_ndb= get_thd_ndb(thd); Ndb *ndb= thd_ndb->ndb; - NdbTransaction *trans= all ? thd_ndb->all : thd_ndb->stmt; + NdbTransaction *trans= thd_ndb->trans; DBUG_ENTER("ndbcluster_commit"); - DBUG_PRINT("transaction",("%s", - trans == thd_ndb->stmt ? - "stmt" : "all")); DBUG_ASSERT(ndb); - if (trans == NULL) + thd_ndb->start_stmt_count= 0; + if (trans == NULL || (!all && + thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + { + /* + An odditity in the handler interface is that commit on handlerton + is called to indicate end of statement only in cases where + autocommit isn't used and the all flag isn't set. + + We also leave quickly when a transaction haven't even been started, + in this case we are safe that no clean up is needed. In this case + the MySQL Server could handle the query without contacting the + NDB kernel. + */ + DBUG_PRINT("info", ("Commit before start or end-of-statement only")); DBUG_RETURN(0); + } #ifdef HAVE_NDB_BINLOG if (unlikely(thd_ndb->m_slow_path)) @@ -4671,11 +4680,7 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) ndbcluster_print_error(res, error_op); } ndb->closeTransaction(trans); - - if (all) - thd_ndb->all= NULL; - else - thd_ndb->stmt= NULL; + thd_ndb->trans= NULL; /* Clear commit_count for tables changed by transaction */ NDB_SHARE* share; @@ -4704,13 +4709,15 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) int res= 0; Thd_ndb *thd_ndb= get_thd_ndb(thd); Ndb *ndb= thd_ndb->ndb; - NdbTransaction *trans= all ? thd_ndb->all : thd_ndb->stmt; + NdbTransaction *trans= thd_ndb->trans; DBUG_ENTER("ndbcluster_rollback"); - DBUG_PRINT("transaction",("%s", - trans == thd_ndb->stmt ? - "stmt" : "all")); - DBUG_ASSERT(ndb && trans); + DBUG_ASSERT(ndb); + thd_ndb->start_stmt_count= 0; + if (!trans) + { + DBUG_RETURN(0); + } if (trans->execute(NdbTransaction::Rollback) != 0) { @@ -4722,11 +4729,7 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) ndbcluster_print_error(res, error_op); } ndb->closeTransaction(trans); - - if (all) - thd_ndb->all= NULL; - else - thd_ndb->stmt= NULL; + thd_ndb->trans= NULL; /* Clear list of tables changed by transaction */ thd_ndb->changed_tables.empty(); diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index a6f992226c2..808ffe20f3e 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -204,8 +204,8 @@ class Thd_ndb Ndb *ndb; ulong count; uint lock_count; - NdbTransaction *all; - NdbTransaction *stmt; + uint start_stmt_count; + NdbTransaction *trans; bool m_error; bool m_slow_path; int m_error_code; @@ -496,6 +496,10 @@ private: friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*, bool); friend int execute_no_commit_ie(ha_ndbcluster*, NdbTransaction*, bool); + void transaction_checks(THD *thd); + int start_statement(THD *thd, Thd_ndb *thd_ndb, Ndb* ndb); + int init_handler_for_statement(THD *thd, Thd_ndb *thd_ndb); + NdbTransaction *m_active_trans; NdbScanOperation *m_active_cursor; const NdbDictionary::Table *m_table; From f09169670b718d666e44dd43ec76bb884250eaa0 Mon Sep 17 00:00:00 2001 From: "mikael@dator6.(none)" <> Date: Sat, 15 Sep 2007 23:33:04 +0200 Subject: [PATCH 03/92] Fixed ndbcluster_rollback --- sql/ha_ndbcluster.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index c090f2a4cde..239b0fa13ec 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4643,6 +4643,8 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) DBUG_ENTER("ndbcluster_commit"); DBUG_ASSERT(ndb); + PRINT_OPTION_FLAGS(thd); + DBUG_PRINT("enter", ("Commit %s", (all ? "all" : "stmt"))); thd_ndb->start_stmt_count= 0; if (trans == NULL || (!all && thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) @@ -4714,8 +4716,11 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) DBUG_ENTER("ndbcluster_rollback"); DBUG_ASSERT(ndb); thd_ndb->start_stmt_count= 0; - if (!trans) + if (trans == NULL || (!all && + thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { + /* Ignore end-of-statement until real rollback or commit is called */ + DBUG_PRINT("info", ("Rollback before start or end-of-statement only")); DBUG_RETURN(0); } From 10ed82f8785ae4fa3447b89fa9ad88d08d0657c7 Mon Sep 17 00:00:00 2001 From: "jmiller/ndbdev@mysql.com/ndb15.mysql.com" <> Date: Wed, 19 Sep 2007 11:20:30 +0200 Subject: [PATCH 04/92] NDBT_Thread.cpp: Removed semicolon causing build syntax issues per pekka --- storage/ndb/test/src/NDBT_Thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/test/src/NDBT_Thread.cpp b/storage/ndb/test/src/NDBT_Thread.cpp index 56cf2f6815b..ff6785724ba 100644 --- a/storage/ndb/test/src/NDBT_Thread.cpp +++ b/storage/ndb/test/src/NDBT_Thread.cpp @@ -131,7 +131,7 @@ NDBT_Thread::exit() m_state = Exit; signal(); unlock(); -}; +} void NDBT_Thread::join() From 33412d2b8ec8e992dad7fe73f9ef132aba53e424 Mon Sep 17 00:00:00 2001 From: "stewart@flamingspork.com[stewart]" <> Date: Tue, 25 Sep 2007 12:01:23 +0200 Subject: [PATCH 05/92] [PATCH] BUG#30379 Better randomise time before retry in timeout check (DBTC) timoOutLoopStartLab() checks if any transactions have been delayed for so long that we are forced to perform some action (e.g. abort, resend etc). It is *MEANT* to (according to the comment): > To avoid aborting both transactions in a deadlock detected by time-out > we insert a random extra time-out of upto 630 ms by using the lowest > six bits of the api connect reference. > We spread it out from 0 to 630 ms if base time-out is larger than 3 sec, > we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec, > and otherwise we spread it out 310 ms. The comment (as all do) lies. the API connect reference is not very random, producing incredibly predictable "random" numbers. This could lead to both txns being aborted instead of just one. Before: timeout value: 123 3 timeout value: 122 2 timeout value: 122 2 timeout value: 122 2 timeout value: 123 3 After: timeout value: 127 7 timeout value: 126 6 timeout value: 129 9 timeout value: 139 19 timeout value: 137 17 timeout value: 151 31 timeout value: 130 10 timeout value: 132 12 Index: ndb-work/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp =================================================================== --- ndb/include/util/ndb_rand.h | 33 ++++++++++++++++++++ ndb/src/common/util/Makefile.am | 3 +- ndb/src/common/util/ndb_rand.c | 40 +++++++++++++++++++++++++ ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 4 ++- 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 ndb/include/util/ndb_rand.h create mode 100644 ndb/src/common/util/ndb_rand.c diff --git a/ndb/include/util/ndb_rand.h b/ndb/include/util/ndb_rand.h new file mode 100644 index 00000000000..1521ca9c4ff --- /dev/null +++ b/ndb/include/util/ndb_rand.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef NDB_RAND_H +#define NDB_RAND_H + +#define NDB_RAND_MAX 32767 + +#ifdef __cplusplus +extern "C" { +#endif + +int ndb_rand(void); + +void ndb_srand(unsigned seed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am index 4cc2e49f9ec..dc83a70990f 100644 --- a/ndb/src/common/util/Makefile.am +++ b/ndb/src/common/util/Makefile.am @@ -24,7 +24,8 @@ libgeneral_la_SOURCES = \ uucode.c random.c version.c \ strdup.c \ ConfigValues.cpp ndb_init.c basestring_vsnprintf.c \ - Bitmask.cpp + Bitmask.cpp \ + ndb_rand.c EXTRA_PROGRAMS = testBitmask testBitmask_SOURCES = testBitmask.cpp diff --git a/ndb/src/common/util/ndb_rand.c b/ndb/src/common/util/ndb_rand.c new file mode 100644 index 00000000000..4fcc483cd49 --- /dev/null +++ b/ndb/src/common/util/ndb_rand.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include + +static unsigned long next= 1; + +/** + * ndb_rand + * + * constant time, cheap, pseudo-random number generator. + * + * NDB_RAND_MAX assumed to be 32767 + * + * This is the POSIX example for "generating the same sequence on + * different machines". Although that is not one of our requirements. + */ +int ndb_rand(void) +{ + next= next * 1103515245 + 12345; + return((unsigned)(next/65536) % 32768); +} + +void ndb_srand(unsigned seed) +{ + next= seed; +} + diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 60024e82978..9697594d7d2 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -6278,7 +6279,8 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) jam(); if (api_timer != 0) { Uint32 error= ZTIME_OUT_ERROR; - time_out_value= time_out_param + (api_con_ptr & mask_value); + time_out_value= time_out_param + (ndb_rand() & mask_value); + ndbout_c("timeout value: %u %u",time_out_value, time_out_value-time_out_param); if (unlikely(old_mask_value)) // abort during single user mode { apiConnectptr.i = api_con_ptr; From 5a67e7ebd67ce27a3966127c89444f2153bff1be Mon Sep 17 00:00:00 2001 From: "stewart@willster.(none)" <> Date: Tue, 25 Sep 2007 12:16:39 +0200 Subject: [PATCH 06/92] ndb_rand.c: Rename: ndb/src/common/util/ndb_rand.c -> storage/ndb/src/common/util/ndb_rand.c ndb_rand.h: Rename: ndb/include/util/ndb_rand.h -> storage/ndb/include/util/ndb_rand.h --- {ndb => storage/ndb}/include/util/ndb_rand.h | 0 {ndb => storage/ndb}/src/common/util/ndb_rand.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {ndb => storage/ndb}/include/util/ndb_rand.h (100%) rename {ndb => storage/ndb}/src/common/util/ndb_rand.c (100%) diff --git a/ndb/include/util/ndb_rand.h b/storage/ndb/include/util/ndb_rand.h similarity index 100% rename from ndb/include/util/ndb_rand.h rename to storage/ndb/include/util/ndb_rand.h diff --git a/ndb/src/common/util/ndb_rand.c b/storage/ndb/src/common/util/ndb_rand.c similarity index 100% rename from ndb/src/common/util/ndb_rand.c rename to storage/ndb/src/common/util/ndb_rand.c From b62d7a318e27adbe86c5b078878285e36a0a058b Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Fri, 28 Sep 2007 09:58:56 +0200 Subject: [PATCH 07/92] ndb - add new testcases/error insert bug#30975 (recommit for correct merge order) --- storage/ndb/src/kernel/blocks/ERROR_codes.txt | 4 +- storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp | 32 ++++ .../ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 1 + storage/ndb/src/kernel/blocks/pgman.cpp | 26 ++- storage/ndb/test/include/HugoTransactions.hpp | 18 ++ storage/ndb/test/include/UtilTransactions.hpp | 5 + storage/ndb/test/ndbapi/testSystemRestart.cpp | 180 ++++++++++++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 32 ++++ storage/ndb/test/src/HugoTransactions.cpp | 131 ++++++++----- storage/ndb/test/src/UtilTransactions.cpp | 74 +++---- 10 files changed, 419 insertions(+), 84 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index 58479dfe7b6..abb1d858082 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -6,7 +6,7 @@ Next DBTUP 4029 Next DBLQH 5045 Next DBDICT 6007 Next DBDIH 7186 -Next DBTC 8040 +Next DBTC 8054 Next CMVMI 9000 Next BACKUP 10038 Next DBUTIL 11002 @@ -246,6 +246,8 @@ Delay execution of ABORTCONF signal 2 seconds to generate time-out. 8050: Send ZABORT_TIMEOUT_BREAK delayed +8053: Crash in timeOutFoundLab, state CS_WAIT_COMMIT_CONF + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC ------------------------------------------------- diff --git a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index 15e5f908460..f324f62a041 100644 --- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp +++ b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp @@ -1300,6 +1300,38 @@ Cmvmi::execDUMP_STATE_ORD(Signal* signal) } #endif #endif + + if (arg == 9999) + { + Uint32 delay = 1000; + switch(signal->getLength()){ + case 1: + break; + case 2: + delay = signal->theData[1]; + break; + default:{ + Uint32 dmin = signal->theData[1]; + Uint32 dmax = signal->theData[2]; + delay = dmin + (rand() % (dmax - dmin)); + break; + } + } + + signal->theData[0] = 9999; + if (delay == 0) + { + execNDB_TAMPER(signal); + } + else if (delay < 10) + { + sendSignal(reference(), GSN_NDB_TAMPER, signal, 1, JBB); + } + else + { + sendSignalWithDelay(reference(), GSN_NDB_TAMPER, signal, delay, 1); + } + } }//Cmvmi::execDUMP_STATE_ORD() void diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 5c52e145ae9..e8244ce0c66 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -6373,6 +6373,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode) return; case CS_WAIT_COMMIT_CONF: jam(); + CRASH_INSERTION(8053); tcConnectptr.i = apiConnectptr.p->currentTcConnect; ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord); arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS); diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp index edc3eac699e..a5558aa320d 100644 --- a/storage/ndb/src/kernel/blocks/pgman.cpp +++ b/storage/ndb/src/kernel/blocks/pgman.cpp @@ -238,6 +238,13 @@ Pgman::execCONTINUEB(Signal* signal) } else { + if (ERROR_INSERTED(11007)) + { + ndbout << "No more writes..." << endl; + SET_ERROR_INSERT_VALUE(11008); + signal->theData[0] = 9999; + sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 10000, 1); + } signal->theData[0] = m_end_lcp_req.senderData; sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF, signal, 1, JBB); } @@ -1303,6 +1310,13 @@ Pgman::process_lcp(Signal* signal) } else { + if (ERROR_INSERTED(11007)) + { + ndbout << "No more writes..." << endl; + signal->theData[0] = 9999; + sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 10000, 1); + SET_ERROR_INSERT_VALUE(11008); + } signal->theData[0] = m_end_lcp_req.senderData; sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF, signal, 1, JBB); } @@ -1590,8 +1604,11 @@ Pgman::fswritereq(Signal* signal, Ptr ptr) } #endif - sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, - FsReadWriteReq::FixedLength + 1, JBA); + if (!ERROR_INSERTED(11008)) + { + sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, + FsReadWriteReq::FixedLength + 1, JBA); + } } void @@ -2454,6 +2471,11 @@ Pgman::execDUMP_STATE_ORD(Signal* signal) { SET_ERROR_INSERT_VALUE(11006); } + + if (signal->theData[0] == 11007) + { + SET_ERROR_INSERT_VALUE(11007); + } } // page cache client diff --git a/storage/ndb/test/include/HugoTransactions.hpp b/storage/ndb/test/include/HugoTransactions.hpp index e2b12f261a8..e8f7b33e0ed 100644 --- a/storage/ndb/test/include/HugoTransactions.hpp +++ b/storage/ndb/test/include/HugoTransactions.hpp @@ -36,6 +36,16 @@ public: int updateValue = 0, bool abort = false); + int loadTableStartFrom(Ndb*, + int startFrom, + int records, + int batch = 512, + bool allowConstraintViolation = true, + int doSleep = 0, + bool oneTrans = false, + int updateValue = 0, + bool abort = false); + int scanReadRecords(Ndb*, int records, int abort = 0, @@ -56,6 +66,11 @@ public: int batchsize = 1, NdbOperation::LockMode = NdbOperation::LM_Read); + int scanUpdateRecords(Ndb*, NdbScanOperation::ScanFlag, + int records, + int abort = 0, + int parallelism = 0); + int scanUpdateRecords(Ndb*, int records, int abort = 0, @@ -90,9 +105,12 @@ public: int records, int percentToLock = 1, int lockTime = 1000); + int fillTable(Ndb*, int batch=512); + int fillTableStartFrom(Ndb*, int startFrom, int batch=512); + /** * Reading using UniqHashIndex with key = pk */ diff --git a/storage/ndb/test/include/UtilTransactions.hpp b/storage/ndb/test/include/UtilTransactions.hpp index 75bbcd9c776..193398c3da2 100644 --- a/storage/ndb/test/include/UtilTransactions.hpp +++ b/storage/ndb/test/include/UtilTransactions.hpp @@ -29,6 +29,11 @@ public: int closeTransaction(Ndb*); + int clearTable(Ndb*, + NdbScanOperation::ScanFlag, + int records = 0, + int parallelism = 0); + int clearTable(Ndb*, int records = 0, int parallelism = 0); diff --git a/storage/ndb/test/ndbapi/testSystemRestart.cpp b/storage/ndb/test/ndbapi/testSystemRestart.cpp index bd5cd3dd3c8..e4f9c627f4c 100644 --- a/storage/ndb/test/ndbapi/testSystemRestart.cpp +++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp @@ -20,6 +20,7 @@ #include #include #include +#include int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -1219,6 +1220,159 @@ runBug24664(NDBT_Context* ctx, NDBT_Step* step) return result; } +int runSR_DD_1(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* pNdb = GETNDB(step); + int result = NDBT_OK; + Uint32 loops = ctx->getNumLoops(); + int count; + NdbRestarter restarter; + NdbBackup backup(GETNDB(step)->getNodeId()+1); + bool lcploop = ctx->getProperty("LCP", (unsigned)0); + + Uint32 i = 1; + Uint32 backupId; + + int val[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + int lcp = DumpStateOrd::DihMinTimeBetweenLCP; + + int startFrom = 0; + + HugoTransactions hugoTrans(*ctx->getTab()); + while(i<=loops && result != NDBT_FAILED) + { + + if (lcploop) + { + CHECK(restarter.dumpStateAllNodes(&lcp, 1) == 0); + } + + int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes()); + //CHECK(restarter.dumpStateAllNodes(&val, 1) == 0); + + ndbout << "Loop " << i << "/"<< loops <<" started" << endl; + ndbout << "Loading records..." << startFrom << endl; + CHECK(hugoTrans.loadTable(pNdb, startFrom) == 0); + + ndbout << "Making " << nodeId << " crash" << endl; + int kill[] = { 9999, 1000, 3000 }; + CHECK(restarter.dumpStateOneNode(nodeId, val, 2) == 0); + CHECK(restarter.dumpStateOneNode(nodeId, kill, 3) == 0); + + Uint64 end = NdbTick_CurrentMillisecond() + 4000; + Uint32 row = startFrom; + do { + ndbout << "Loading from " << row << " to " << row + 1000 << endl; + if (hugoTrans.loadTableStartFrom(pNdb, row, 1000) != 0) + break; + row += 1000; + } while (NdbTick_CurrentMillisecond() < end); + + ndbout << "Waiting for " << nodeId << " to restart" << endl; + CHECK(restarter.waitNodesNoStart(&nodeId, 1) == 0); + + ndbout << "Restarting cluster" << endl; + CHECK(restarter.restartAll(false, true, true) == 0); + CHECK(restarter.waitClusterNoStart() == 0); + CHECK(restarter.startAll() == 0); + CHECK(restarter.waitClusterStarted() == 0); + + ndbout << "Starting backup..." << flush; + CHECK(backup.start(backupId) == 0); + ndbout << "done" << endl; + + int cnt = 0; + CHECK(hugoTrans.selectCount(pNdb, 0, &cnt) == 0); + ndbout << "Found " << cnt << " records..." << endl; + ndbout << "Clearing..." << endl; + CHECK(hugoTrans.clearTable(pNdb, + NdbScanOperation::SF_TupScan, cnt) == 0); + + if (cnt > startFrom) + { + startFrom = cnt; + } + startFrom += 1000; + i++; + } + + ndbout << "runSR_DD_1 finished" << endl; + + return result; +} + +int runSR_DD_2(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* pNdb = GETNDB(step); + int result = NDBT_OK; + Uint32 loops = ctx->getNumLoops(); + Uint32 rows = ctx->getNumRecords(); + int count; + NdbRestarter restarter; + NdbBackup backup(GETNDB(step)->getNodeId()+1); + bool lcploop = ctx->getProperty("LCP", (unsigned)0); + + Uint32 i = 1; + Uint32 backupId; + + int val[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + int lcp = DumpStateOrd::DihMinTimeBetweenLCP; + + int startFrom = 0; + + HugoTransactions hugoTrans(*ctx->getTab()); + while(i<=loops && result != NDBT_FAILED) + { + + if (lcploop) + { + CHECK(restarter.dumpStateAllNodes(&lcp, 1) == 0); + } + + int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes()); + + ndbout << "Making " << nodeId << " crash" << endl; + int kill[] = { 9999, 3000, 10000 }; + CHECK(restarter.dumpStateOneNode(nodeId, val, 2) == 0); + CHECK(restarter.dumpStateOneNode(nodeId, kill, 3) == 0); + + Uint64 end = NdbTick_CurrentMillisecond() + 11000; + Uint32 row = startFrom; + do { + if (hugoTrans.loadTable(pNdb, rows) != 0) + break; + + if (hugoTrans.clearTable(pNdb, NdbScanOperation::SF_TupScan, rows) != 0) + break; + } while (NdbTick_CurrentMillisecond() < end); + + ndbout << "Waiting for " << nodeId << " to restart" << endl; + CHECK(restarter.waitNodesNoStart(&nodeId, 1) == 0); + + ndbout << "Restarting cluster" << endl; + CHECK(restarter.restartAll(false, true, true) == 0); + CHECK(restarter.waitClusterNoStart() == 0); + CHECK(restarter.startAll() == 0); + CHECK(restarter.waitClusterStarted() == 0); + + ndbout << "Starting backup..." << flush; + CHECK(backup.start(backupId) == 0); + ndbout << "done" << endl; + + int cnt = 0; + CHECK(hugoTrans.selectCount(pNdb, 0, &cnt) == 0); + ndbout << "Found " << cnt << " records..." << endl; + ndbout << "Clearing..." << endl; + CHECK(hugoTrans.clearTable(pNdb, + NdbScanOperation::SF_TupScan, cnt) == 0); + i++; + } + + ndbout << "runSR_DD_2 finished" << endl; + + return result; +} + NDBT_TESTSUITE(testSystemRestart); TESTCASE("SR1", "Basic system restart test. Focus on testing restart from REDO log.\n" @@ -1399,6 +1553,32 @@ TESTCASE("Bug24664", STEP(runBug24664); FINALIZER(runClearTable); } +TESTCASE("SR_DD_1", "") +{ + INITIALIZER(runWaitStarted); + STEP(runSR_DD_1); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_1_LCP", "") +{ + TC_PROPERTY("LCP", 1); + INITIALIZER(runWaitStarted); + STEP(runSR_DD_1); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_2", "") +{ + INITIALIZER(runWaitStarted); + STEP(runSR_DD_2); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_2_LCP", "") +{ + TC_PROPERTY("LCP", 1); + INITIALIZER(runWaitStarted); + STEP(runSR_DD_2); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testSystemRestart); int main(int argc, const char** argv){ diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 74c8ea39c97..200b258280a 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -870,3 +870,35 @@ cmd: DbAsyncGenerator args: -time 60 -p 1 -proc 25 type: bench +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1 D1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1 D2 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1_LCP D1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1_LCP D2 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2 D1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2 D2 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2_LCP D1 + +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2_LCP D2 + diff --git a/storage/ndb/test/src/HugoTransactions.cpp b/storage/ndb/test/src/HugoTransactions.cpp index 920d2a1dc70..d4d5652bf1f 100644 --- a/storage/ndb/test/src/HugoTransactions.cpp +++ b/storage/ndb/test/src/HugoTransactions.cpp @@ -341,50 +341,14 @@ HugoTransactions::scanReadRecords(Ndb* pNdb, int HugoTransactions::scanUpdateRecords(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - if(m_defaultScanUpdateMethod == 1){ - return scanUpdateRecords1(pNdb, records, abortPercent, parallelism); - } else if(m_defaultScanUpdateMethod == 2){ - return scanUpdateRecords2(pNdb, records, abortPercent, parallelism); - } else { - return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); - } -} - -// Scan all records exclusive and update -// them one by one -int -HugoTransactions::scanUpdateRecords1(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - return scanUpdateRecords3(pNdb, records, abortPercent, 1); -} - -// Scan all records exclusive and update -// them batched by asking nextScanResult to -// give us all cached records before fetching new -// records from db -int -HugoTransactions::scanUpdateRecords2(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); -} - -int -HugoTransactions::scanUpdateRecords3(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - int retryAttempt = 0; + NdbScanOperation::ScanFlag flags, + int records, + int abortPercent, + int parallelism){ + int retryAttempt = 0; int check, a; NdbScanOperation *pOp; - while (true){ restart: if (retryAttempt++ >= m_retryMax){ @@ -411,8 +375,9 @@ restart: return NDBT_FAILED; } - if( pOp->readTuplesExclusive(parallelism) ) { - ERR(pTrans->getNdbError()); + if( pOp->readTuples(NdbOperation::LM_Exclusive, flags, + parallelism)) + { closeTransaction(pNdb); return NDBT_FAILED; } @@ -516,6 +481,52 @@ restart: return NDBT_FAILED; } +int +HugoTransactions::scanUpdateRecords(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + + return scanUpdateRecords(pNdb, + (NdbScanOperation::ScanFlag)0, + records, abortPercent, parallelism); +} + +// Scan all records exclusive and update +// them one by one +int +HugoTransactions::scanUpdateRecords1(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + return scanUpdateRecords(pNdb, + (NdbScanOperation::ScanFlag)0, + records, abortPercent, 1); +} + +// Scan all records exclusive and update +// them batched by asking nextScanResult to +// give us all cached records before fetching new +// records from db +int +HugoTransactions::scanUpdateRecords2(Ndb* pNdb, + int records, + int abortPercent, + int parallelism){ + return scanUpdateRecords(pNdb, (NdbScanOperation::ScanFlag)0, + records, abortPercent, parallelism); +} + +int +HugoTransactions::scanUpdateRecords3(Ndb* pNdb, + int records, + int abortPercent, + int parallelism) +{ + return scanUpdateRecords(pNdb, (NdbScanOperation::ScanFlag)0, + records, abortPercent, parallelism); +} + int HugoTransactions::loadTable(Ndb* pNdb, int records, @@ -524,7 +535,22 @@ HugoTransactions::loadTable(Ndb* pNdb, int doSleep, bool oneTrans, int value, - bool abort){ + bool abort) +{ + return loadTableStartFrom(pNdb, 0, records, batch, allowConstraintViolation, + doSleep, oneTrans, value, abort); +} + +int +HugoTransactions::loadTableStartFrom(Ndb* pNdb, + int startFrom, + int records, + int batch, + bool allowConstraintViolation, + int doSleep, + bool oneTrans, + int value, + bool abort){ int check; int retryAttempt = 0; int retryMax = 5; @@ -543,8 +569,9 @@ HugoTransactions::loadTable(Ndb* pNdb, << " -> rows/commit = " << batch << endl; } + Uint32 orgbatch = batch; g_info << "|- Inserting records..." << endl; - for (int c=0 ; c records) @@ -578,7 +605,7 @@ HugoTransactions::loadTable(Ndb* pNdb, } } - if(pkInsertRecord(pNdb, c, batch, value) != NDBT_OK) + if(pkInsertRecord(pNdb, c + startFrom, batch, value) != NDBT_OK) { ERR(pTrans->getNdbError()); closeTransaction(pNdb); @@ -625,6 +652,7 @@ HugoTransactions::loadTable(Ndb* pNdb, ERR(err); NdbSleep_MilliSleep(50); retryAttempt++; + batch = 1; continue; break; @@ -670,7 +698,14 @@ HugoTransactions::loadTable(Ndb* pNdb, int HugoTransactions::fillTable(Ndb* pNdb, - int batch){ + int batch){ + return fillTableStartFrom(pNdb, 0, batch); +} + +int +HugoTransactions::fillTableStartFrom(Ndb* pNdb, + int startFrom, + int batch){ int check; int retryAttempt = 0; int retryMax = 5; @@ -688,7 +723,7 @@ HugoTransactions::fillTable(Ndb* pNdb, << " -> rows/commit = " << batch << endl; } - for (int c=0 ; ; ){ + for (int c=startFrom ; ; ){ if (retryAttempt >= retryMax){ g_info << "Record " << c << " could not be inserted, has retried " diff --git a/storage/ndb/test/src/UtilTransactions.cpp b/storage/ndb/test/src/UtilTransactions.cpp index f5638a368c7..41c3d2f1d83 100644 --- a/storage/ndb/test/src/UtilTransactions.cpp +++ b/storage/ndb/test/src/UtilTransactions.cpp @@ -42,38 +42,9 @@ UtilTransactions::UtilTransactions(Ndb* ndb, int UtilTransactions::clearTable(Ndb* pNdb, - int records, - int parallelism){ - if(m_defaultClearMethod == 1){ - return clearTable1(pNdb, records, parallelism); - } else if(m_defaultClearMethod == 2){ - return clearTable2(pNdb, records, parallelism); - } else { - return clearTable3(pNdb, records, parallelism); - } -} - - -int -UtilTransactions::clearTable1(Ndb* pNdb, - int records, - int parallelism) -{ - return clearTable3(pNdb, records, 1); -} - -int -UtilTransactions::clearTable2(Ndb* pNdb, - int records, - int parallelism) -{ - return clearTable3(pNdb, records, parallelism); -} - -int -UtilTransactions::clearTable3(Ndb* pNdb, - int records, - int parallelism){ + NdbScanOperation::ScanFlag flags, + int records, + int parallelism){ // Scan all records exclusive and delete // them one by one int retryAttempt = 0; @@ -116,7 +87,7 @@ UtilTransactions::clearTable3(Ndb* pNdb, goto failed; } - if( pOp->readTuplesExclusive(par) ) { + if( pOp->readTuples(NdbOperation::LM_Exclusive, flags, par) ) { err = pTrans->getNdbError(); goto failed; } @@ -179,6 +150,43 @@ UtilTransactions::clearTable3(Ndb* pNdb, return (err.code != 0 ? err.code : NDBT_FAILED); } +int +UtilTransactions::clearTable(Ndb* pNdb, + int records, + int parallelism){ + + return clearTable(pNdb, (NdbScanOperation::ScanFlag)0, + records, parallelism); +} + + +int +UtilTransactions::clearTable1(Ndb* pNdb, + int records, + int parallelism) +{ + return clearTable(pNdb, (NdbScanOperation::ScanFlag)0, + records, 1); +} + +int +UtilTransactions::clearTable2(Ndb* pNdb, + int records, + int parallelism) +{ + return clearTable(pNdb, (NdbScanOperation::ScanFlag)0, + records, parallelism); +} + +int +UtilTransactions::clearTable3(Ndb* pNdb, + int records, + int parallelism) +{ + return clearTable(pNdb, (NdbScanOperation::ScanFlag)0, + records, parallelism); +} + int UtilTransactions::copyTableData(Ndb* pNdb, const char* destName){ From e4ca46610671c3185f8cead2314416f7913214c2 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Fri, 28 Sep 2007 10:22:54 +0200 Subject: [PATCH 08/92] post merge --- storage/ndb/test/src/HugoTransactions.cpp | 180 ---------------------- 1 file changed, 180 deletions(-) diff --git a/storage/ndb/test/src/HugoTransactions.cpp b/storage/ndb/test/src/HugoTransactions.cpp index 8aefe7d9577..0e5f7cd8115 100644 --- a/storage/ndb/test/src/HugoTransactions.cpp +++ b/storage/ndb/test/src/HugoTransactions.cpp @@ -477,186 +477,6 @@ restart: return NDBT_FAILED; } - -#define RESTART_SCAN 99 - -int -HugoTransactions::scanUpdateRecords(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - if(m_defaultScanUpdateMethod == 1){ - return scanUpdateRecords1(pNdb, records, abortPercent, parallelism); - } else if(m_defaultScanUpdateMethod == 2){ - return scanUpdateRecords2(pNdb, records, abortPercent, parallelism); - } else { - return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); - } -} - -// Scan all records exclusive and update -// them one by one -int -HugoTransactions::scanUpdateRecords1(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - return scanUpdateRecords3(pNdb, records, abortPercent, 1); -} - -// Scan all records exclusive and update -// them batched by asking nextScanResult to -// give us all cached records before fetching new -// records from db -int -HugoTransactions::scanUpdateRecords2(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - return scanUpdateRecords3(pNdb, records, abortPercent, parallelism); -} - -int -HugoTransactions::scanUpdateRecords3(Ndb* pNdb, - int records, - int abortPercent, - int parallelism){ - int retryAttempt = 0; - int check, a; - NdbScanOperation *pOp; - - - while (true){ -restart: - if (retryAttempt++ >= m_retryMax){ - g_info << "ERROR: has retried this operation " << retryAttempt - << " times, failing!" << endl; - return NDBT_FAILED; - } - - pTrans = pNdb->startTransaction(); - if (pTrans == NULL) { - const NdbError err = pNdb->getNdbError(); - ERR(err); - if (err.status == NdbError::TemporaryError){ - NdbSleep_MilliSleep(50); - continue; - } - return NDBT_FAILED; - } - - pOp = getScanOperation(pTrans); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - if( pOp->readTuplesExclusive(parallelism) ) { - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - - // Read all attributes from this table - for(a=0; agetValue(tab.getColumn(a)->getName())) == NULL){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - - check = pTrans->execute(NoCommit, AbortOnError); - if( check == -1 ) { - const NdbError err = pTrans->getNdbError(); - ERR(err); - closeTransaction(pNdb); - if (err.status == NdbError::TemporaryError){ - NdbSleep_MilliSleep(50); - continue; - } - return NDBT_FAILED; - } - - // Abort after 1-100 or 1-records rows - int ranVal = rand(); - int abortCount = ranVal % (records == 0 ? 100 : records); - bool abortTrans = false; - if (abort > 0){ - // Abort if abortCount is less then abortPercent - if (abortCount < abortPercent) - abortTrans = true; - } - - int rows = 0; - while((check = pOp->nextResult(true)) == 0){ - do { - rows++; - NdbOperation* pUp = pOp->updateCurrentTuple(); - if(pUp == 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - const int updates = calc.getUpdatesValue(&row) + 1; - const int r = calc.getIdValue(&row); - for(a = 0; agetPrimaryKey() == false){ - if(setValueForAttr(pUp, a, r, updates ) != 0){ - ERR(pTrans->getNdbError()); - closeTransaction(pNdb); - return NDBT_FAILED; - } - } - } - - if (rows == abortCount && abortTrans == true){ - g_info << "Scan is aborted" << endl; - // This scan should be aborted - closeTransaction(pNdb); - return NDBT_OK; - } - } while((check = pOp->nextResult(false)) == 0); - - if(check != -1){ - check = pTrans->execute(Commit, AbortOnError); - if(check != -1) - m_latest_gci = pTrans->getGCI(); - pTrans->restart(); - } - - const NdbError err = pTrans->getNdbError(); - if( check == -1 ) { - closeTransaction(pNdb); - ERR(err); - if (err.status == NdbError::TemporaryError){ - NdbSleep_MilliSleep(50); - goto restart; - } - return NDBT_FAILED; - } - } - - const NdbError err = pTrans->getNdbError(); - if( check == -1 ) { - closeTransaction(pNdb); - ERR(err); - if (err.status == NdbError::TemporaryError){ - NdbSleep_MilliSleep(50); - goto restart; - } - return NDBT_FAILED; - } - - closeTransaction(pNdb); - - g_info << rows << " rows have been updated" << endl; - return NDBT_OK; - } - return NDBT_FAILED; -} - int HugoTransactions::scanUpdateRecords(Ndb* pNdb, int records, From 40c83d3285e806984e406571f332b1078ea388dd Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Sat, 29 Sep 2007 11:10:12 +0200 Subject: [PATCH 09/92] ndb - bug#30975 add even more tests --- storage/ndb/test/ndbapi/testSystemRestart.cpp | 130 +++++++++++++++--- .../ndb/test/run-test/daily-basic-tests.txt | 32 +++++ 2 files changed, 141 insertions(+), 21 deletions(-) diff --git a/storage/ndb/test/ndbapi/testSystemRestart.cpp b/storage/ndb/test/ndbapi/testSystemRestart.cpp index e4f9c627f4c..2495bf15186 100644 --- a/storage/ndb/test/ndbapi/testSystemRestart.cpp +++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp @@ -1220,6 +1220,30 @@ runBug24664(NDBT_Context* ctx, NDBT_Step* step) return result; } +int +runStopper(NDBT_Context* ctx, NDBT_Step* step) +{ + NdbRestarter restarter; + Uint32 stop = 0; +loop: + while (!ctx->isTestStopped() && + ((stop = ctx->getProperty("StopAbort", Uint32(0))) == 0)) + { + NdbSleep_MilliSleep(30); + } + + if (ctx->isTestStopped()) + { + return NDBT_OK; + } + + ndbout << "Killing in " << stop << "ms..." << flush; + NdbSleep_MilliSleep(stop); + restarter.restartAll(false, true, true); + ctx->setProperty("StopAbort", Uint32(0)); + goto loop; +} + int runSR_DD_1(NDBT_Context* ctx, NDBT_Step* step) { Ndb* pNdb = GETNDB(step); @@ -1229,6 +1253,7 @@ int runSR_DD_1(NDBT_Context* ctx, NDBT_Step* step) NdbRestarter restarter; NdbBackup backup(GETNDB(step)->getNodeId()+1); bool lcploop = ctx->getProperty("LCP", (unsigned)0); + bool all = ctx->getProperty("ALL", (unsigned)0); Uint32 i = 1; Uint32 backupId; @@ -1254,11 +1279,18 @@ int runSR_DD_1(NDBT_Context* ctx, NDBT_Step* step) ndbout << "Loading records..." << startFrom << endl; CHECK(hugoTrans.loadTable(pNdb, startFrom) == 0); - ndbout << "Making " << nodeId << " crash" << endl; - int kill[] = { 9999, 1000, 3000 }; - CHECK(restarter.dumpStateOneNode(nodeId, val, 2) == 0); - CHECK(restarter.dumpStateOneNode(nodeId, kill, 3) == 0); - + if (!all) + { + ndbout << "Making " << nodeId << " crash" << endl; + int kill[] = { 9999, 1000, 3000 }; + CHECK(restarter.dumpStateOneNode(nodeId, val, 2) == 0); + CHECK(restarter.dumpStateOneNode(nodeId, kill, 3) == 0); + } + else + { + ndbout << "Crashing cluster" << endl; + ctx->setProperty("StopAbort", 1000 + rand() % (3000 - 1000)); + } Uint64 end = NdbTick_CurrentMillisecond() + 4000; Uint32 row = startFrom; do { @@ -1268,11 +1300,17 @@ int runSR_DD_1(NDBT_Context* ctx, NDBT_Step* step) row += 1000; } while (NdbTick_CurrentMillisecond() < end); - ndbout << "Waiting for " << nodeId << " to restart" << endl; - CHECK(restarter.waitNodesNoStart(&nodeId, 1) == 0); - - ndbout << "Restarting cluster" << endl; - CHECK(restarter.restartAll(false, true, true) == 0); + if (!all) + { + ndbout << "Waiting for " << nodeId << " to restart" << endl; + CHECK(restarter.waitNodesNoStart(&nodeId, 1) == 0); + ndbout << "Restarting cluster" << endl; + CHECK(restarter.restartAll(false, true, true) == 0); + } + else + { + ndbout << "Waiting for cluster to restart" << endl; + } CHECK(restarter.waitClusterNoStart() == 0); CHECK(restarter.startAll() == 0); CHECK(restarter.waitClusterStarted() == 0); @@ -1297,7 +1335,7 @@ int runSR_DD_1(NDBT_Context* ctx, NDBT_Step* step) } ndbout << "runSR_DD_1 finished" << endl; - + ctx->stopTest(); return result; } @@ -1311,6 +1349,7 @@ int runSR_DD_2(NDBT_Context* ctx, NDBT_Step* step) NdbRestarter restarter; NdbBackup backup(GETNDB(step)->getNodeId()+1); bool lcploop = ctx->getProperty("LCP", (unsigned)0); + bool all = ctx->getProperty("ALL", (unsigned)0); Uint32 i = 1; Uint32 backupId; @@ -1331,10 +1370,18 @@ int runSR_DD_2(NDBT_Context* ctx, NDBT_Step* step) int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes()); - ndbout << "Making " << nodeId << " crash" << endl; - int kill[] = { 9999, 3000, 10000 }; - CHECK(restarter.dumpStateOneNode(nodeId, val, 2) == 0); - CHECK(restarter.dumpStateOneNode(nodeId, kill, 3) == 0); + if (!all) + { + ndbout << "Making " << nodeId << " crash" << endl; + int kill[] = { 9999, 3000, 10000 }; + CHECK(restarter.dumpStateOneNode(nodeId, val, 2) == 0); + CHECK(restarter.dumpStateOneNode(nodeId, kill, 3) == 0); + } + else + { + ndbout << "Crashing cluster" << endl; + ctx->setProperty("StopAbort", 1000 + rand() % (3000 - 1000)); + } Uint64 end = NdbTick_CurrentMillisecond() + 11000; Uint32 row = startFrom; @@ -1346,11 +1393,18 @@ int runSR_DD_2(NDBT_Context* ctx, NDBT_Step* step) break; } while (NdbTick_CurrentMillisecond() < end); - ndbout << "Waiting for " << nodeId << " to restart" << endl; - CHECK(restarter.waitNodesNoStart(&nodeId, 1) == 0); - - ndbout << "Restarting cluster" << endl; - CHECK(restarter.restartAll(false, true, true) == 0); + if (!all) + { + ndbout << "Waiting for " << nodeId << " to restart" << endl; + CHECK(restarter.waitNodesNoStart(&nodeId, 1) == 0); + ndbout << "Restarting cluster" << endl; + CHECK(restarter.restartAll(false, true, true) == 0); + } + else + { + ndbout << "Waiting for cluster to restart" << endl; + } + CHECK(restarter.waitClusterNoStart() == 0); CHECK(restarter.startAll() == 0); CHECK(restarter.waitClusterStarted() == 0); @@ -1369,7 +1423,7 @@ int runSR_DD_2(NDBT_Context* ctx, NDBT_Step* step) } ndbout << "runSR_DD_2 finished" << endl; - + ctx->stopTest(); return result; } @@ -1554,12 +1608,29 @@ TESTCASE("Bug24664", FINALIZER(runClearTable); } TESTCASE("SR_DD_1", "") +{ + TC_PROPERTY("ALL", 1); + INITIALIZER(runWaitStarted); + STEP(runStopper); + STEP(runSR_DD_1); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_1b", "") { INITIALIZER(runWaitStarted); STEP(runSR_DD_1); FINALIZER(runClearTable); } TESTCASE("SR_DD_1_LCP", "") +{ + TC_PROPERTY("ALL", 1); + TC_PROPERTY("LCP", 1); + INITIALIZER(runWaitStarted); + STEP(runStopper); + STEP(runSR_DD_1); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_1b_LCP", "") { TC_PROPERTY("LCP", 1); INITIALIZER(runWaitStarted); @@ -1567,12 +1638,29 @@ TESTCASE("SR_DD_1_LCP", "") FINALIZER(runClearTable); } TESTCASE("SR_DD_2", "") +{ + TC_PROPERTY("ALL", 1); + INITIALIZER(runWaitStarted); + STEP(runStopper); + STEP(runSR_DD_2); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_2b", "") { INITIALIZER(runWaitStarted); STEP(runSR_DD_2); FINALIZER(runClearTable); } TESTCASE("SR_DD_2_LCP", "") +{ + TC_PROPERTY("ALL", 1); + TC_PROPERTY("LCP", 1); + INITIALIZER(runWaitStarted); + STEP(runStopper); + STEP(runSR_DD_2); + FINALIZER(runClearTable); +} +TESTCASE("SR_DD_2b_LCP", "") { TC_PROPERTY("LCP", 1); INITIALIZER(runWaitStarted); diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 200b258280a..2c654a13bcf 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -874,31 +874,63 @@ max-time: 1500 cmd: testSystemRestart args: -n SR_DD_1 D1 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1b D1 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_1 D2 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1b D2 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_1_LCP D1 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1b_LCP D1 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_1_LCP D2 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_1b_LCP D2 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_2 D1 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2b D1 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_2 D2 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2b D2 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_2_LCP D1 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2b_LCP D1 + max-time: 1500 cmd: testSystemRestart args: -n SR_DD_2_LCP D2 +max-time: 1500 +cmd: testSystemRestart +args: -n SR_DD_2b_LCP D2 + From f72c7d01089003e7ff38c4cccf3f288f12d79836 Mon Sep 17 00:00:00 2001 From: "stewart@willster.(none)" <> Date: Mon, 1 Oct 2007 14:32:22 +1000 Subject: [PATCH 10/92] remove debug printout --- ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 9697594d7d2..91adae183f4 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -6280,7 +6280,6 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) if (api_timer != 0) { Uint32 error= ZTIME_OUT_ERROR; time_out_value= time_out_param + (ndb_rand() & mask_value); - ndbout_c("timeout value: %u %u",time_out_value, time_out_value-time_out_param); if (unlikely(old_mask_value)) // abort during single user mode { apiConnectptr.i = api_con_ptr; From 403f0afc2926c6d2b3a438f6ba747bb9de5b13ec Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Tue, 2 Oct 2007 13:36:13 +0200 Subject: [PATCH 11/92] Bug#25817 UPDATE IGNORE doesn't check write_set when checking unique indexes: Added checks --- mysql-test/r/ndb_update.result | 8 +++++++ mysql-test/t/ndb_update.test | 5 +++++ sql/ha_ndbcluster.cc | 40 ++++++++++++++++++++++++++++++---- sql/ha_ndbcluster.h | 9 +++++++- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/ndb_update.result b/mysql-test/r/ndb_update.result index d75f82172ae..7848a47bcef 100644 --- a/mysql-test/r/ndb_update.result +++ b/mysql-test/r/ndb_update.result @@ -39,4 +39,12 @@ pk1 b c 10 0 0 12 2 2 14 1 1 +create unique index ib on t1(b); +update t1 set c = 4 where pk1 = 12; +update ignore t1 set b = 55 where pk1 = 14; +select * from t1 order by pk1; +pk1 b c +10 0 0 +12 2 4 +14 55 1 DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test index ebcc6995d74..0f8793300e0 100644 --- a/mysql-test/t/ndb_update.test +++ b/mysql-test/t/ndb_update.test @@ -33,6 +33,11 @@ UPDATE IGNORE t1 set pk1 = 1, c = 2 where pk1 = 4; select * from t1 order by pk1; UPDATE t1 set pk1 = pk1 + 10; select * from t1 order by pk1; +# bug#25817 +create unique index ib on t1(b); +update t1 set c = 4 where pk1 = 12; +update ignore t1 set b = 55 where pk1 = 14; +select * from t1 order by pk1; --disable_warnings DROP TABLE IF EXISTS t1; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b74b04f4238..90b8e77153c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1356,6 +1356,30 @@ int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *rec DBUG_RETURN(0); } +bool ha_ndbcluster::check_index_fields_in_write_set(uint keyno) +{ + KEY* key_info= table->key_info + keyno; + KEY_PART_INFO* key_part= key_info->key_part; + KEY_PART_INFO* end= key_part+key_info->key_parts; + uint i; + DBUG_ENTER("check_index_fields_in_write_set"); + + if (m_retrieve_all_fields) + { + DBUG_RETURN(true); + } + for (i= 0; key_part != end; key_part++, i++) + { + Field* field= key_part->field; + if (field->query_id != current_thd->query_id) + { + DBUG_RETURN(false); + } + } + + DBUG_RETURN(true); +} + int ha_ndbcluster::set_index_key_from_record(NdbOperation *op, const byte *record, uint keyno) { KEY* key_info= table->key_info + keyno; @@ -1643,7 +1667,8 @@ check_null_in_record(const KEY* key_info, const byte *record) * primary key or unique index values */ -int ha_ndbcluster::peek_indexed_rows(const byte *record, bool check_pk) +int ha_ndbcluster::peek_indexed_rows(const byte *record, + NDB_WRITE_OP write_op) { NdbTransaction *trans= m_active_trans; NdbOperation *op; @@ -1656,7 +1681,7 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, bool check_pk) (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); first= NULL; - if (check_pk && table->s->primary_key != MAX_KEY) + if (write_op != NDB_UPDATE && table->s->primary_key != MAX_KEY) { /* * Fetch any row with colliding primary key @@ -1690,6 +1715,12 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, bool check_pk) DBUG_PRINT("info", ("skipping check for key with NULL")); continue; } + if (write_op != NDB_INSERT && !check_index_fields_in_write_set(i)) + { + DBUG_PRINT("info", ("skipping check for key %u not in write_set", i)); + continue; + } + NdbIndexOperation *iop; NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index; key_part= key_info->key_part; @@ -2268,7 +2299,7 @@ int ha_ndbcluster::write_row(byte *record) start_bulk_insert will set parameters to ensure that each write_row is committed individually */ - int peek_res= peek_indexed_rows(record, true); + int peek_res= peek_indexed_rows(record, NDB_INSERT); if (!peek_res) { @@ -2456,7 +2487,8 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) if (m_ignore_dup_key && (thd->lex->sql_command == SQLCOM_UPDATE || thd->lex->sql_command == SQLCOM_UPDATE_MULTI)) { - int peek_res= peek_indexed_rows(new_data, pk_update); + NDB_WRITE_OP write_op= (pk_update) ? NDB_PK_UPDATE : NDB_UPDATE; + int peek_res= peek_indexed_rows(new_data, write_op); if (!peek_res) { diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 81cbdcd8fea..324969ad374 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -59,6 +59,12 @@ typedef struct ndb_index_data { bool null_in_unique_index; } NDB_INDEX_DATA; +typedef enum ndb_write_op { + NDB_INSERT = 0, + NDB_UPDATE = 1, + NDB_PK_UPDATE = 2 +} NDB_WRITE_OP; + typedef struct st_ndbcluster_share { THR_LOCK lock; pthread_mutex_t mutex; @@ -251,7 +257,7 @@ private: const NdbOperation *first, const NdbOperation *last, uint errcode); - int peek_indexed_rows(const byte *record, bool check_pk); + int peek_indexed_rows(const byte *record, NDB_WRITE_OP write_op); int unique_index_read(const byte *key, uint key_len, byte *buf); int ordered_index_scan(const key_range *start_key, @@ -286,6 +292,7 @@ private: int get_ndb_blobs_value(NdbBlob *last_ndb_blob, my_ptrdiff_t ptrdiff); int set_primary_key(NdbOperation *op, const byte *key); int set_primary_key_from_record(NdbOperation *op, const byte *record); + bool check_index_fields_in_write_set(uint keyno); int set_index_key_from_record(NdbOperation *op, const byte *record, uint keyno); int set_bounds(NdbIndexScanOperation*, const key_range *keys[2], uint= 0); From 87359889f3562df2234e5108b1817dc3c482c2cb Mon Sep 17 00:00:00 2001 From: "stewart@flamingspork.com[stewart]" <> Date: Wed, 3 Oct 2007 16:16:48 +1000 Subject: [PATCH 12/92] [PATCH] BUG#29565 managment server can log entries multiple times after mgmd restart Close the event log on shutdown of mgmd (in stopEventLog()) Index: ndb-work/ndb/src/mgmsrv/MgmtSrvr.cpp =================================================================== --- ndb/src/mgmsrv/MgmtSrvr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 409694fead1..d68f42cbbb4 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -227,10 +227,10 @@ MgmtSrvr::startEventLog() } } -void -MgmtSrvr::stopEventLog() +void +MgmtSrvr::stopEventLog() { - // Nothing yet + g_eventLogger.close(); } class ErrorItem From 5415286db8b242be396e40024800bd16f5dbfecb Mon Sep 17 00:00:00 2001 From: "stewart@flamingspork.com[stewart]" <> Date: Wed, 3 Oct 2007 17:25:46 +1000 Subject: [PATCH 13/92] [PATCH] BUG#25064 Remove newlines from cluster log Index: ndb/storage/ndb/src/common/debugger/EventLogger.cpp =================================================================== --- storage/ndb/src/common/debugger/EventLogger.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/ndb/src/common/debugger/EventLogger.cpp b/storage/ndb/src/common/debugger/EventLogger.cpp index 0964a54f906..bcc0d4a969c 100644 --- a/storage/ndb/src/common/debugger/EventLogger.cpp +++ b/storage/ndb/src/common/debugger/EventLogger.cpp @@ -498,9 +498,9 @@ void getTextTransReportCounters(QQQQ) { // ------------------------------------------------------------------- BaseString::snprintf(m_text, m_text_len, "Trans. Count = %u, Commit Count = %u, " - "Read Count = %u, Simple Read Count = %u,\n" + "Read Count = %u, Simple Read Count = %u, " "Write Count = %u, AttrInfo Count = %u, " - "Concurrent Operations = %u, Abort Count = %u\n" + "Concurrent Operations = %u, Abort Count = %u" " Scans: %u Range scans: %u", theData[1], theData[2], @@ -797,9 +797,9 @@ void getTextBackupFailedToStart(QQQQ) { } void getTextBackupCompleted(QQQQ) { BaseString::snprintf(m_text, m_text_len, - "Backup %u started from node %u completed\n" - " StartGCP: %u StopGCP: %u\n" - " #Records: %u #LogRecords: %u\n" + "Backup %u started from node %u completed." + " StartGCP: %u StopGCP: %u" + " #Records: %u #LogRecords: %u" " Data: %u bytes Log: %u bytes", theData[2], refToNode(theData[1]), theData[3], theData[4], theData[6], theData[8], From a43fa8e500bec1ea2d1b145ccf5725e72f31c2a7 Mon Sep 17 00:00:00 2001 From: "stewart@flamingspork.com[stewart]" <> Date: Wed, 3 Oct 2007 17:26:03 +1000 Subject: [PATCH 14/92] [PATCH] BUG#25064 make formatting of key=value consistent in getTextTransReportCounters Index: ndb/storage/ndb/src/common/debugger/EventLogger.cpp =================================================================== --- storage/ndb/src/common/debugger/EventLogger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/src/common/debugger/EventLogger.cpp b/storage/ndb/src/common/debugger/EventLogger.cpp index bcc0d4a969c..068b0c6ac18 100644 --- a/storage/ndb/src/common/debugger/EventLogger.cpp +++ b/storage/ndb/src/common/debugger/EventLogger.cpp @@ -501,7 +501,7 @@ void getTextTransReportCounters(QQQQ) { "Read Count = %u, Simple Read Count = %u, " "Write Count = %u, AttrInfo Count = %u, " "Concurrent Operations = %u, Abort Count = %u" - " Scans: %u Range scans: %u", + " Scans = %u Range scans = %u", theData[1], theData[2], theData[3], From 1b4b234748994b489a09ac2a685774af52b57100 Mon Sep 17 00:00:00 2001 From: "stewart@flamingspork.com[stewart]" <> Date: Wed, 3 Oct 2007 17:26:17 +1000 Subject: [PATCH 15/92] [PATCH] BUG#29509 ndb_mgm help needs to list the -a option for DN restart Index: ndb/storage/ndb/src/mgmclient/CommandInterpreter.cpp =================================================================== --- storage/ndb/src/mgmclient/CommandInterpreter.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/storage/ndb/src/mgmclient/CommandInterpreter.cpp b/storage/ndb/src/mgmclient/CommandInterpreter.cpp index 875cc2771ae..9e8910c9649 100644 --- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp @@ -269,8 +269,8 @@ static const char* helpText = "CLUSTERLOG TOGGLE [] ... Toggle severity filter on/off\n" "CLUSTERLOG INFO Print cluster log information\n" " START Start data node (started with -n)\n" -" RESTART [-n] [-i] Restart data or management server node\n" -" STOP Stop data or management server node\n" +" RESTART [-n] [-i] [-a] Restart data or management server node\n" +" STOP [-a] Stop data or management server node\n" "ENTER SINGLE USER MODE Enter single user mode\n" "EXIT SINGLE USER MODE Exit single user mode\n" " STATUS Print status\n" @@ -434,7 +434,7 @@ static const char* helpTextRestart = " NDB Cluster -- Management Client -- Help for RESTART command\n" "---------------------------------------------------------------------------\n" "RESTART Restart data or management server node\n\n" -" RESTART [-n] [-i] \n" +" RESTART [-n] [-i] [-a]\n" " Restart the data or management node (or All data nodes).\n\n" " -n (--nostart) restarts the node but does not\n" " make it join the cluster. Use ' START' to\n" @@ -445,6 +445,7 @@ static const char* helpTextRestart = " in the same node group during start up.\n\n" " Consult the documentation before using -i.\n\n" " INCORRECT USE OF -i WILL CAUSE DATA LOSS!\n" +" -a Aborts the node, not syncing GCP.\n" ; static const char* helpTextStop = @@ -452,10 +453,11 @@ static const char* helpTextStop = " NDB Cluster -- Management Client -- Help for STOP command\n" "---------------------------------------------------------------------------\n" "STOP Stop data or management server node\n\n" -" STOP Stop the data or management server node .\n\n" +" STOP [-a] Stop the data or management server node .\n\n" " ALL STOP will just stop all data nodes.\n\n" " If you desire to also shut down management servers,\n" -" use SHUTDOWN instead.\n" +" use SHUTDOWN instead.\n" +" -a Aborts the node, not syncing GCP.\n" ; static const char* helpTextEnterSingleUserMode = From 94e7bf9f4b553efbf0cf6b7ed2b153bf4f7b65b7 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Wed, 3 Oct 2007 09:29:10 +0200 Subject: [PATCH 16/92] Removed tabs --- sql/ha_ndbcluster.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 90b8e77153c..d35aa93d5d3 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1712,12 +1712,12 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, */ if (check_null_in_record(key_info, record)) { - DBUG_PRINT("info", ("skipping check for key with NULL")); + DBUG_PRINT("info", ("skipping check for key with NULL")); continue; } if (write_op != NDB_INSERT && !check_index_fields_in_write_set(i)) { - DBUG_PRINT("info", ("skipping check for key %u not in write_set", i)); + DBUG_PRINT("info", ("skipping check for key %u not in write_set", i)); continue; } From c91d8068d12b1dbb6df68afe785c68519537558a Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Wed, 3 Oct 2007 09:54:33 +0200 Subject: [PATCH 17/92] Bug#25817 UPDATE IGNORE doesn't check write_set when checking unique indexes: Post merge 5.0->5.1 --- sql/ha_ndbcluster.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 69512e5e7c7..b372849a183 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1651,14 +1651,10 @@ bool ha_ndbcluster::check_index_fields_in_write_set(uint keyno) uint i; DBUG_ENTER("check_index_fields_in_write_set"); - if (m_retrieve_all_fields) - { - DBUG_RETURN(true); - } for (i= 0; key_part != end; key_part++, i++) { Field* field= key_part->field; - if (field->query_id != current_thd->query_id) + if (!bitmap_is_set(table->write_set, field->field_index)) { DBUG_RETURN(false); } @@ -1985,7 +1981,7 @@ check_null_in_record(const KEY* key_info, const uchar *record) * primary key or unique index values */ -int ha_ndbcluster::peek_indexed_rows(const byte *record, +int ha_ndbcluster::peek_indexed_rows(const uchar *record, NDB_WRITE_OP write_op) { NdbTransaction *trans= m_active_trans; @@ -1998,7 +1994,7 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, NdbOperation::LockMode lm= (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); first= NULL; - if (check_pk && table->s->primary_key != MAX_KEY) + if (write_op != NDB_UPDATE && table->s->primary_key != MAX_KEY) { /* * Fetch any row with colliding primary key @@ -2048,6 +2044,11 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record, DBUG_PRINT("info", ("skipping check for key with NULL")); continue; } + if (write_op != NDB_INSERT && !check_index_fields_in_write_set(i)) + { + DBUG_PRINT("info", ("skipping check for key %u not in write_set", i)); + continue; + } NdbIndexOperation *iop; const NDBINDEX *unique_index = m_index[i].unique_index; key_part= key_info->key_part; From 82da7623d414086cc819302b4bca32fb40ce470c Mon Sep 17 00:00:00 2001 From: "pekka@sama.ndb.mysql.com" <> Date: Thu, 4 Oct 2007 11:32:49 +0200 Subject: [PATCH 18/92] ndb - bug#29390: if ScanFilter is too large, abort or optionally discard it --- mysql-test/r/ndb_condition_pushdown.result | 22 + mysql-test/t/ndb_condition_pushdown.test | 1025 ++++++++++++++++++++ ndb/include/kernel/signaldata/ScanTab.hpp | 1 + ndb/include/ndbapi/Ndb.hpp | 1 + ndb/include/ndbapi/NdbScanFilter.hpp | 27 +- ndb/include/ndbapi/ndbapi_limits.h | 2 + ndb/src/ndbapi/NdbScanFilter.cpp | 208 +++- ndb/src/ndbapi/NdbScanOperation.cpp | 4 + ndb/src/ndbapi/ndberror.c | 3 +- sql/ha_ndbcluster_cond.cc | 20 +- 10 files changed, 1287 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index 6012c9b6969..d49c0cd983e 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -1888,5 +1888,27 @@ set engine_condition_pushdown = 1; SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); fname lname Young Foo +drop table t1; +create table t1 (a int, b int, c int, d int, primary key using hash(a)) +engine=ndbcluster; +insert into t1 values (10,1,100,0+0x1111); +insert into t1 values (20,2,200,0+0x2222); +insert into t1 values (30,3,300,0+0x3333); +insert into t1 values (40,4,400,0+0x4444); +insert into t1 values (50,5,500,0+0x5555); +set engine_condition_pushdown = on; +select a,b,d from t1 +where b in (0,1,2,5) +order by b; +a b d +10 1 4369 +20 2 8738 +50 5 21845 +a b d +10 1 4369 +20 2 8738 +50 5 21845 +Warnings: +Warning 4294 Scan filter is too large, discarded set engine_condition_pushdown = @old_ecpd; DROP TABLE t1,t2,t3,t4,t5; diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index 748c26e2a9a..b5b7e41fb21 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -1718,5 +1718,1030 @@ SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); set engine_condition_pushdown = 1; SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); +# bug#29390 (scan filter is too large, discarded) + +drop table t1; + +create table t1 (a int, b int, c int, d int, primary key using hash(a)) + engine=ndbcluster; + +insert into t1 values (10,1,100,0+0x1111); +insert into t1 values (20,2,200,0+0x2222); +insert into t1 values (30,3,300,0+0x3333); +insert into t1 values (40,4,400,0+0x4444); +insert into t1 values (50,5,500,0+0x5555); + +set engine_condition_pushdown = on; + +select a,b,d from t1 + where b in (0,1,2,5) + order by b; + +--disable_query_log +select a,b,d from t1 + where b in ( +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2) + order by b; +--enable_query_log + set engine_condition_pushdown = @old_ecpd; DROP TABLE t1,t2,t3,t4,t5; diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp index 15a022e2cba..38ec4cccf7b 100644 --- a/ndb/include/kernel/signaldata/ScanTab.hpp +++ b/ndb/include/kernel/signaldata/ScanTab.hpp @@ -46,6 +46,7 @@ public: * Length of signal */ STATIC_CONST( StaticLength = 11 ); + STATIC_CONST( MaxTotalAttrInfo = 0xFFFF ); private: diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index f83db77739e..01bc899b4e1 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -1052,6 +1052,7 @@ class Ndb friend class NdbDictInterface; friend class NdbBlob; friend class NdbImpl; + friend class NdbScanFilterImpl; #endif public: diff --git a/ndb/include/ndbapi/NdbScanFilter.hpp b/ndb/include/ndbapi/NdbScanFilter.hpp index 1ef62558560..02fcb6215ba 100644 --- a/ndb/include/ndbapi/NdbScanFilter.hpp +++ b/ndb/include/ndbapi/NdbScanFilter.hpp @@ -17,6 +17,7 @@ #define NDB_SCAN_FILTER_HPP #include +#include /** * @class NdbScanFilter @@ -31,8 +32,13 @@ public: /** * Constructor * @param op The NdbOperation that the filter belongs to (is applied to). + * @param abort_on_too_large abort transaction on filter too large + * default: true + * @param max_size Maximum size of generated filter in words */ - NdbScanFilter(class NdbOperation * op); + NdbScanFilter(class NdbOperation * op, + bool abort_on_too_large = true, + Uint32 max_size = NDB_MAX_SCANFILTER_SIZE_IN_WORDS); ~NdbScanFilter(); /** @@ -166,6 +172,25 @@ public: /** @} *********************************************************************/ #endif + enum Error { + FilterTooLarge = 4294 + }; + + /** + * Get filter level error. + * + * Most errors are set only on operation level, and they abort the + * transaction. The error FilterTooLarge is set on filter level and + * by default it propagates to operation level and also aborts the + * transaction. + * + * If option abort_on_too_large is set to false, then FilterTooLarge + * does not propagate. One can then either ignore this error (in + * which case no filtering is done) or try to define a new filter + * immediately. + */ + const class NdbError & getNdbError() const; + private: #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL friend class NdbScanFilterImpl; diff --git a/ndb/include/ndbapi/ndbapi_limits.h b/ndb/include/ndbapi/ndbapi_limits.h index 63399e4bd0a..e283913d059 100644 --- a/ndb/include/ndbapi/ndbapi_limits.h +++ b/ndb/include/ndbapi/ndbapi_limits.h @@ -26,4 +26,6 @@ #define NDB_MAX_TUPLE_SIZE (NDB_MAX_TUPLE_SIZE_IN_WORDS*4) #define NDB_MAX_ACTIVE_EVENTS 100 +#define NDB_MAX_SCANFILTER_SIZE_IN_WORDS 50000 + #endif diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp index fb47772fdea..624122b5c55 100644 --- a/ndb/src/ndbapi/NdbScanFilter.cpp +++ b/ndb/src/ndbapi/NdbScanFilter.cpp @@ -14,11 +14,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include "NdbDictionaryImpl.hpp" #include #include #include +#include +#include "NdbApiSignal.hpp" #ifdef VM_TRACE #include @@ -52,14 +55,37 @@ public: int cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, const void * value, Uint32 len); + + bool m_abort_on_too_large; + + NdbOperation::OperationStatus m_initial_op_status; + Uint32 m_initial_AI_size; + Uint32 m_max_size; + + Uint32 get_size() { + assert(m_operation->theTotalCurrAI_Len >= m_initial_AI_size); + return m_operation->theTotalCurrAI_Len - m_initial_AI_size; + } + bool check_size() { + if (get_size() <= m_max_size) + return true; + handle_filter_too_large(); + return false; + } + void handle_filter_too_large(); + + NdbError m_error; }; const Uint32 LabelExit = ~0; -NdbScanFilter::NdbScanFilter(class NdbOperation * op) +NdbScanFilter::NdbScanFilter(class NdbOperation * op, + bool abort_on_too_large, + Uint32 max_size) : m_impl(* new NdbScanFilterImpl()) { + DBUG_ENTER("NdbScanFilter::NdbScanFilter"); m_impl.m_current.m_group = (NdbScanFilter::Group)0; m_impl.m_current.m_popCount = 0; m_impl.m_current.m_ownLabel = 0; @@ -69,6 +95,21 @@ NdbScanFilter::NdbScanFilter(class NdbOperation * op) m_impl.m_latestAttrib = ~0; m_impl.m_operation = op; m_impl.m_negative = 0; + + DBUG_PRINT("info", ("op status: %d tot AI: %u in curr: %u", + op->theStatus, + op->theTotalCurrAI_Len, op->theAI_LenInCurrAI)); + + m_impl.m_abort_on_too_large = abort_on_too_large; + + m_impl.m_initial_op_status = op->theStatus; + m_impl.m_initial_AI_size = op->theTotalCurrAI_Len; + if (max_size > NDB_MAX_SCANFILTER_SIZE_IN_WORDS) + max_size = NDB_MAX_SCANFILTER_SIZE_IN_WORDS; + m_impl.m_max_size = max_size; + + m_impl.m_error.code = 0; + DBUG_VOID_RETURN; } NdbScanFilter::~NdbScanFilter(){ @@ -200,30 +241,38 @@ NdbScanFilter::end(){ switch(tmp.m_group){ case NdbScanFilter::AND: if(tmp.m_trueLabel == (Uint32)~0){ - m_impl.m_operation->interpret_exit_ok(); + if (m_impl.m_operation->interpret_exit_ok() == -1) + return -1; } else { - m_impl.m_operation->branch_label(tmp.m_trueLabel); + if (m_impl.m_operation->branch_label(tmp.m_trueLabel) == -1) + return -1; } break; case NdbScanFilter::NAND: if(tmp.m_trueLabel == (Uint32)~0){ - m_impl.m_operation->interpret_exit_nok(); + if (m_impl.m_operation->interpret_exit_nok() == -1) + return -1; } else { - m_impl.m_operation->branch_label(tmp.m_falseLabel); + if (m_impl.m_operation->branch_label(tmp.m_falseLabel) == -1) + return -1; } break; case NdbScanFilter::OR: if(tmp.m_falseLabel == (Uint32)~0){ - m_impl.m_operation->interpret_exit_nok(); + if (m_impl.m_operation->interpret_exit_nok() == -1) + return -1; } else { - m_impl.m_operation->branch_label(tmp.m_falseLabel); + if (m_impl.m_operation->branch_label(tmp.m_falseLabel) == -1) + return -1; } break; case NdbScanFilter::NOR: if(tmp.m_falseLabel == (Uint32)~0){ - m_impl.m_operation->interpret_exit_ok(); + if (m_impl.m_operation->interpret_exit_ok() == -1) + return -1; } else { - m_impl.m_operation->branch_label(tmp.m_trueLabel); + if (m_impl.m_operation->branch_label(tmp.m_trueLabel) == -1) + return -1; } break; default: @@ -231,24 +280,29 @@ NdbScanFilter::end(){ return -1; } - m_impl.m_operation->def_label(tmp.m_ownLabel); + if (m_impl.m_operation->def_label(tmp.m_ownLabel) == -1) + return -1; if(m_impl.m_stack.size() == 0){ switch(tmp.m_group){ case NdbScanFilter::AND: case NdbScanFilter::NOR: - m_impl.m_operation->interpret_exit_nok(); + if (m_impl.m_operation->interpret_exit_nok() == -1) + return -1; break; case NdbScanFilter::OR: case NdbScanFilter::NAND: - m_impl.m_operation->interpret_exit_ok(); + if (m_impl.m_operation->interpret_exit_ok() == -1) + return -1; break; default: m_impl.m_operation->setErrorCodeAbort(4260); return -1; } } - + + if (!m_impl.check_size()) + return -1; return 0; } @@ -261,10 +315,16 @@ NdbScanFilter::istrue(){ } if(m_impl.m_current.m_trueLabel == (Uint32)~0){ - return m_impl.m_operation->interpret_exit_ok(); + if (m_impl.m_operation->interpret_exit_ok() == -1) + return -1; } else { - return m_impl.m_operation->branch_label(m_impl.m_current.m_trueLabel); + if (m_impl.m_operation->branch_label(m_impl.m_current.m_trueLabel) == -1) + return -1; } + + if (!m_impl.check_size()) + return -1; + return 0; } int @@ -276,10 +336,16 @@ NdbScanFilter::isfalse(){ } if(m_impl.m_current.m_falseLabel == (Uint32)~0){ - return m_impl.m_operation->interpret_exit_nok(); + if (m_impl.m_operation->interpret_exit_nok() == -1) + return -1; } else { - return m_impl.m_operation->branch_label(m_impl.m_current.m_falseLabel); + if (m_impl.m_operation->branch_label(m_impl.m_current.m_falseLabel) == -1) + return -1; } + + if (!m_impl.check_size()) + return -1; + return 0; } @@ -330,7 +396,11 @@ NdbScanFilterImpl::cond_col(Interpreter::UnaryCondition op, Uint32 AttrId){ } Branch1 branch = table2[op].m_branches[m_current.m_group]; - (m_operation->* branch)(AttrId, m_current.m_ownLabel); + if ((m_operation->* branch)(AttrId, m_current.m_ownLabel) == -1) + return -1; + + if (!check_size()) + return -1; return 0; } @@ -463,8 +533,12 @@ NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op, return -1; } - int ret = (m_operation->* branch)(AttrId, value, len, false, m_current.m_ownLabel); - return ret; + if ((m_operation->* branch)(AttrId, value, len, false, m_current.m_ownLabel) == -1) + return -1; + + if (!check_size()) + return -1; + return 0; } int @@ -490,7 +564,99 @@ NdbScanFilter::cmp(BinaryCondition cond, int ColId, return m_impl.cond_col_const(Interpreter::NOT_LIKE, ColId, val, len); } return -1; -} +} + +void +NdbScanFilterImpl::handle_filter_too_large() +{ + DBUG_ENTER("NdbScanFilterImpl::handle_filter_too_large"); + + NdbOperation* const op = m_operation; + m_error.code = NdbScanFilter::FilterTooLarge; + if (m_abort_on_too_large) + op->setErrorCodeAbort(m_error.code); + + /* + * Possible interpreted parts at this point are: + * + * 1. initial read + * 2. interpreted program + * + * It is assumed that NdbScanFilter has created all of 2 + * so that we don't have to save interpreter state. + */ + + const Uint32 size = get_size(); + assert(size != 0); + + // new ATTRINFO size + const Uint32 new_size = m_initial_AI_size; + + // find last signal for new size + assert(op->theFirstATTRINFO != NULL); + NdbApiSignal* lastSignal = op->theFirstATTRINFO; + Uint32 n = 0; + while (n + AttrInfo::DataLength < new_size) { + lastSignal = lastSignal->next(); + assert(lastSignal != NULL); + n += AttrInfo::DataLength; + } + assert(n < size); + + // release remaining signals + NdbApiSignal* tSignal = lastSignal->next(); + op->theNdb->releaseSignalsInList(&tSignal); + lastSignal->next(NULL); + + // length of lastSignal + const Uint32 new_curr = AttrInfo::HeaderLength + new_size - n; + assert(new_curr <= 25); + + DBUG_PRINT("info", ("op status: %d->%d tot AI: %u->%u in curr: %u->%u", + op->theStatus, m_initial_op_status, + op->theTotalCurrAI_Len, new_size, + op->theAI_LenInCurrAI, new_curr)); + + // reset op state + op->theStatus = m_initial_op_status; + + // reset interpreter state to initial + op->theFirstBranch = NULL; + op->theLastBranch = NULL; + op->theFirstCall = NULL; + op->theLastCall = NULL; + op->theFirstSubroutine = NULL; + op->theLastSubroutine = NULL; + op->theNoOfLabels = 0; + op->theNoOfSubroutines = 0; + + // reset AI size + op->theTotalCurrAI_Len = new_size; + op->theAI_LenInCurrAI = new_curr; + + // reset signal pointers + op->theCurrentATTRINFO = lastSignal; + op->theATTRINFOptr = &lastSignal->getDataPtrSend()[new_curr]; + + // interpreter sizes are set later somewhere + + DBUG_VOID_RETURN; +} + +static void +update(const NdbError & _err){ + NdbError & error = (NdbError &) _err; + ndberror_struct ndberror = (ndberror_struct)error; + ndberror_update(&ndberror); + error = NdbError(ndberror); +} + +const NdbError & +NdbScanFilter::getNdbError() const +{ + update(m_impl.m_error); + return m_impl.m_error; +} #if 0 diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index aec98a7f5d5..9176fb47297 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -849,6 +849,10 @@ NdbScanOperation::doSendScan(int aProcessorId) // sending it. This could not be done in openScan because // we created the ATTRINFO signals after the SCAN_TABREQ signal. ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend()); + if (unlikely(theTotalCurrAI_Len > ScanTabReq::MaxTotalAttrInfo)) { + setErrorCode(4257); + return -1; + } req->attrLenKeyLen = (tupKeyLen << 16) | theTotalCurrAI_Len; Uint32 tmp = req->requestInfo; ScanTabReq::setDistributionKeyFlag(tmp, theDistrKeyIndicator_); diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 24ccb1d07c2..56eb2c0f8bd 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -527,7 +527,8 @@ ErrorBundle ErrorCodes[] = { { 4270, IE, "Unknown blob error" }, { 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" }, { 4271, AE, "Invalid index object, not retrieved via getIndex()" }, - { 4275, AE, "The blob method is incompatible with operation type or lock mode" } + { 4275, AE, "The blob method is incompatible with operation type or lock mode" }, + { 4294, AE, "Scan filter is too large, discarded" } }; static diff --git a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc index ea3f8a7683a..c7b185a92f0 100644 --- a/sql/ha_ndbcluster_cond.cc +++ b/sql/ha_ndbcluster_cond.cc @@ -1338,9 +1338,23 @@ ha_ndbcluster_cond::generate_scan_filter(NdbScanOperation *op) if (m_cond_stack) { - NdbScanFilter filter(op); + NdbScanFilter filter(op, false); // don't abort on too large - DBUG_RETURN(generate_scan_filter_from_cond(filter)); + int ret=generate_scan_filter_from_cond(filter); + if (ret != 0) + { + const NdbError& err=filter.getNdbError(); + if (err.code == NdbScanFilter::FilterTooLarge) + { + // err.message has static storage + DBUG_PRINT("info", ("%s", err.message)); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + err.code, err.message); + ret=0; + } + } + if (ret != 0) + DBUG_RETURN(ret); } else { @@ -1391,7 +1405,7 @@ int ha_ndbcluster_cond::generate_scan_filter_from_key(NdbScanOperation *op, { KEY_PART_INFO* key_part= key_info->key_part; KEY_PART_INFO* end= key_part+key_info->key_parts; - NdbScanFilter filter(op); + NdbScanFilter filter(op, true); // abort on too large int res; DBUG_ENTER("generate_scan_filter_from_key"); From c1fbd513c493db8b9824c93799bf1becff5a399d Mon Sep 17 00:00:00 2001 From: "pekka@sama.ndb.mysql.com" <> Date: Thu, 4 Oct 2007 19:46:01 +0200 Subject: [PATCH 19/92] ndb - wl#29390 post-merge 5.0 to 5.1 --- storage/ndb/src/ndbapi/ndberror.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c index a0417e5b118..0ad2faff76a 100644 --- a/storage/ndb/src/ndbapi/ndberror.c +++ b/storage/ndb/src/ndbapi/ndberror.c @@ -624,6 +624,7 @@ ErrorBundle ErrorCodes[] = { { 4273, DMEC, IE, "No blob table in dict cache" }, { 4274, DMEC, IE, "Corrupted main table PK in blob operation" }, { 4275, DMEC, AE, "The blob method is incompatible with operation type or lock mode" }, + { 4294, DMEC, AE, "Scan filter is too large, discarded" }, { NO_CONTACT_WITH_PROCESS, DMEC, AE, "No contact with the process (dead ?)."}, From 2890430e4469a35b8488017bf1ba08d0618e49ec Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 15:07:58 +0200 Subject: [PATCH 20/92] ndb - fix bug in old test prg(s) fix SR1 and SR2 --- storage/ndb/test/ndbapi/testSystemRestart.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/ndb/test/ndbapi/testSystemRestart.cpp b/storage/ndb/test/ndbapi/testSystemRestart.cpp index 2495bf15186..419c1eb1438 100644 --- a/storage/ndb/test/ndbapi/testSystemRestart.cpp +++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp @@ -122,7 +122,7 @@ int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); @@ -143,7 +143,7 @@ int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); @@ -266,7 +266,7 @@ int runSystemRestart2(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); From 2583dae0317bb9bd31865eb8aaff28fd6ef9b10b Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 15:11:47 +0200 Subject: [PATCH 21/92] ndb - Set usable timeout for atrt (problem introduced by stew's timeout handling) --- storage/ndb/src/cw/cpcd/APIService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/src/cw/cpcd/APIService.cpp b/storage/ndb/src/cw/cpcd/APIService.cpp index 5bbf2c86e23..ca4ab733842 100644 --- a/storage/ndb/src/cw/cpcd/APIService.cpp +++ b/storage/ndb/src/cw/cpcd/APIService.cpp @@ -145,7 +145,7 @@ CPCDAPISession::CPCDAPISession(NDB_SOCKET_TYPE sock, : SocketServer::Session(sock) , m_cpcd(cpcd) { - m_input = new SocketInputStream(sock); + m_input = new SocketInputStream(sock, 7*24*60*60000); m_output = new SocketOutputStream(sock); m_parser = new Parser(commands, *m_input, true, true, true); } From edf125a54d968b7b07fd2eb31acc7b7fc1d0bf53 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 15:53:29 +0200 Subject: [PATCH 22/92] ndb - bug#30975 (recommit to 51-telco-gca) - only update extent pages *after* flush of real page has been done - sync both create/drop of table into undolog (for disk tables) --- .../ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 11 +- storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp | 9 +- .../kernel/blocks/dbtup/DbtupDiskAlloc.cpp | 254 +++++++++++++----- .../ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp | 32 ++- storage/ndb/src/kernel/blocks/lgman.cpp | 12 +- storage/ndb/src/kernel/blocks/pgman.cpp | 36 ++- storage/ndb/src/kernel/blocks/tsman.cpp | 62 +++-- storage/ndb/src/kernel/blocks/tsman.hpp | 24 +- 8 files changed, 314 insertions(+), 126 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index bd5e52c1800..6f0d676194f 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -14042,11 +14042,16 @@ void Dblqh::execSTART_FRAGREQ(Signal* signal) fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION; } - c_tup->disk_restart_mark_no_lcp(tabptr.i, fragId); + c_tup->disk_restart_lcp_id(tabptr.i, fragId, RNIL); jamEntry(); - return; - }//if + } + else + { + jam(); + c_tup->disk_restart_lcp_id(tabptr.i, fragId, lcpId); + jamEntry(); + } c_lcpId = (c_lcpId == 0 ? lcpId : c_lcpId); c_lcpId = (c_lcpId < lcpId ? c_lcpId : lcpId); diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 05f993dcece..eaf00138acf 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -624,7 +624,8 @@ struct Fragrecord { DLList::Head m_scanList; - enum { UC_LCP = 1, UC_CREATE = 2 }; + enum { UC_LCP = 1, UC_CREATE = 2, UC_SET_LCP = 3 }; + Uint32 m_restore_lcp_id; Uint32 m_undo_complete; Uint32 m_tablespace_id; Uint32 m_logfile_group_id; @@ -2748,7 +2749,7 @@ private: public: int disk_page_load_hook(Uint32 page_id); - void disk_page_unmap_callback(Uint32 page_id, Uint32 dirty_count); + void disk_page_unmap_callback(Uint32 when, Uint32 page, Uint32 dirty_count); int disk_restart_alloc_extent(Uint32 tableId, Uint32 fragId, const Local_key* key, Uint32 pages); @@ -2769,11 +2770,11 @@ public: Local_key m_key; }; - void disk_restart_mark_no_lcp(Uint32 table, Uint32 frag); + void disk_restart_lcp_id(Uint32 table, Uint32 frag, Uint32 lcpId); private: void disk_restart_undo_next(Signal*); - void disk_restart_undo_lcp(Uint32, Uint32, Uint32 flag); + void disk_restart_undo_lcp(Uint32, Uint32, Uint32 flag, Uint32 lcpId); void disk_restart_undo_callback(Signal* signal, Uint32, Uint32); void disk_restart_undo_alloc(Apply_undo*); void disk_restart_undo_update(Apply_undo*); diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp index db336df6652..4509adb7da0 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp @@ -907,8 +907,10 @@ Dbtup::disk_page_set_dirty(PagePtr pagePtr) } void -Dbtup::disk_page_unmap_callback(Uint32 page_id, Uint32 dirty_count) +Dbtup::disk_page_unmap_callback(Uint32 when, + Uint32 page_id, Uint32 dirty_count) { + jamEntry(); Ptr gpage; m_global_page_pool.getPtr(gpage, page_id); PagePtr pagePtr; @@ -922,17 +924,9 @@ Dbtup::disk_page_unmap_callback(Uint32 page_id, Uint32 dirty_count) { return ; } - - Local_key key; - key.m_page_no = pagePtr.p->m_page_no; - key.m_file_no = pagePtr.p->m_file_no; + Uint32 idx = pagePtr.p->list_index; - ndbassert((idx & 0x8000) == 0); - - if (DBG_DISK) - ndbout << "disk_page_unmap_callback " << key << endl; - Ptr tabPtr; tabPtr.i= pagePtr.p->m_table_id; ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); @@ -942,26 +936,83 @@ Dbtup::disk_page_unmap_callback(Uint32 page_id, Uint32 dirty_count) Disk_alloc_info& alloc= fragPtr.p->m_disk_alloc_info; - if (dirty_count == 0) + if (when == 0) { - Uint32 free = pagePtr.p->free_space; - Uint32 used = pagePtr.p->uncommitted_used_space; - ddassert(free >= used); - ddassert(alloc.calc_page_free_bits(free - used) == idx); + /** + * Before pageout + */ + jam(); + + if (DBG_DISK) + { + Local_key key; + key.m_page_no = pagePtr.p->m_page_no; + key.m_file_no = pagePtr.p->m_file_no; + ndbout << "disk_page_unmap_callback(before) " << key + << " cnt: " << dirty_count << " " << (idx & ~0x8000) << endl; + } + + ndbassert((idx & 0x8000) == 0); + + ArrayPool *pool= (ArrayPool*)&m_global_page_pool; + LocalDLList list(*pool, alloc.m_dirty_pages[idx]); + list.remove(pagePtr); + + if (dirty_count == 0) + { + jam(); + pagePtr.p->list_index = idx | 0x8000; + + Local_key key; + key.m_page_no = pagePtr.p->m_page_no; + key.m_file_no = pagePtr.p->m_file_no; + + Uint32 free = pagePtr.p->free_space; + Uint32 used = pagePtr.p->uncommitted_used_space; + ddassert(free >= used); + ddassert(alloc.calc_page_free_bits(free - used) == idx); + + Tablespace_client tsman(0, c_tsman, + fragPtr.p->fragTableId, + fragPtr.p->fragmentId, + fragPtr.p->m_tablespace_id); + + tsman.unmap_page(&key, idx); + jamEntry(); + } + } + else if (when == 1) + { + /** + * After page out + */ + jam(); + + Local_key key; + key.m_page_no = pagePtr.p->m_page_no; + key.m_file_no = pagePtr.p->m_file_no; + Uint32 real_free = pagePtr.p->free_space; + if (DBG_DISK) + { + ndbout << "disk_page_unmap_callback(after) " << key + << " cnt: " << dirty_count << " " << (idx & ~0x8000) << endl; + } + Tablespace_client tsman(0, c_tsman, fragPtr.p->fragTableId, fragPtr.p->fragmentId, fragPtr.p->m_tablespace_id); - tsman.unmap_page(&key, idx); - jamEntry(); - pagePtr.p->list_index = idx | 0x8000; + if (DBG_DISK && alloc.calc_page_free_bits(real_free) != (idx & ~0x8000)) + { + ndbout << key + << " calc: " << alloc.calc_page_free_bits(real_free) + << " idx: " << (idx & ~0x8000) + << endl; + } + tsman.update_page_free_bits(&key, alloc.calc_page_free_bits(real_free)); } - - ArrayPool *pool= (ArrayPool*)&m_global_page_pool; - LocalDLList list(*pool, alloc.m_dirty_pages[idx]); - list.remove(pagePtr); } void @@ -992,20 +1043,6 @@ Dbtup::disk_page_alloc(Signal* signal, lsn= disk_page_undo_alloc(pagePtr.p, key, sz, gci, logfile_group_id); } - - Uint32 new_free = pagePtr.p->free_space; - Uint32 new_bits= alloc.calc_page_free_bits(new_free); - - if (old_bits != new_bits) - { - Tablespace_client tsman(signal, c_tsman, - fragPtrP->fragTableId, - fragPtrP->fragmentId, - fragPtrP->m_tablespace_id); - - tsman.update_page_free_bits(key, new_bits, lsn); - jamEntry(); - } } void @@ -1049,17 +1086,6 @@ Dbtup::disk_page_free(Signal *signal, Uint32 new_free = pagePtr.p->free_space; Uint32 new_bits = alloc.calc_page_free_bits(new_free); - if (old_bits != new_bits) - { - Tablespace_client tsman(signal, c_tsman, - fragPtrP->fragTableId, - fragPtrP->fragmentId, - fragPtrP->m_tablespace_id); - - tsman.update_page_free_bits(key, new_bits, lsn); - jamEntry(); - } - Uint32 ext = pagePtr.p->m_extent_info_ptr; Uint32 used = pagePtr.p->uncommitted_used_space; Uint32 old_idx = pagePtr.p->list_index; @@ -1345,15 +1371,23 @@ Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn, case File_formats::Undofile::UNDO_LCP_FIRST: case File_formats::Undofile::UNDO_LCP: { + jam(); ndbrequire(len == 3); + Uint32 lcp = ptr[0]; Uint32 tableId = ptr[1] >> 16; Uint32 fragId = ptr[1] & 0xFFFF; - disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_LCP); + disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_LCP, lcp); disk_restart_undo_next(signal); + + if (DBG_UNDO) + { + ndbout_c("UNDO LCP %u (%u, %u)", lcp, tableId, fragId); + } return; } case File_formats::Undofile::UNDO_TUP_ALLOC: { + jam(); Disk_undo::Alloc* rec= (Disk_undo::Alloc*)ptr; preq.m_page.m_page_no = rec->m_page_no; preq.m_page.m_file_no = rec->m_file_no_page_idx >> 16; @@ -1362,6 +1396,7 @@ Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn, } case File_formats::Undofile::UNDO_TUP_UPDATE: { + jam(); Disk_undo::Update* rec= (Disk_undo::Update*)ptr; preq.m_page.m_page_no = rec->m_page_no; preq.m_page.m_file_no = rec->m_file_no_page_idx >> 16; @@ -1370,6 +1405,7 @@ Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn, } case File_formats::Undofile::UNDO_TUP_FREE: { + jam(); Disk_undo::Free* rec= (Disk_undo::Free*)ptr; preq.m_page.m_page_no = rec->m_page_no; preq.m_page.m_file_no = rec->m_file_no_page_idx >> 16; @@ -1381,6 +1417,7 @@ Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn, * */ { + jam(); Disk_undo::Create* rec= (Disk_undo::Create*)ptr; Ptr tabPtr; tabPtr.i= rec->m_table; @@ -1388,12 +1425,34 @@ Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn, for(Uint32 i = 0; ifragrec[i] != RNIL) disk_restart_undo_lcp(tabPtr.i, tabPtr.p->fragid[i], - Fragrecord::UC_CREATE); + Fragrecord::UC_CREATE, 0); disk_restart_undo_next(signal); + + if (DBG_UNDO) + { + ndbout_c("UNDO CREATE (%u)", tabPtr.i); + } return; } case File_formats::Undofile::UNDO_TUP_DROP: + { jam(); + Disk_undo::Drop* rec = (Disk_undo::Drop*)ptr; + Ptr tabPtr; + tabPtr.i= rec->m_table; + ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); + for(Uint32 i = 0; ifragrec[i] != RNIL) + disk_restart_undo_lcp(tabPtr.i, tabPtr.p->fragid[i], + Fragrecord::UC_CREATE, 0); + disk_restart_undo_next(signal); + + if (DBG_UNDO) + { + ndbout_c("UNDO DROP (%u)", tabPtr.i); + } + return; + } case File_formats::Undofile::UNDO_TUP_ALLOC_EXTENT: jam(); case File_formats::Undofile::UNDO_TUP_FREE_EXTENT: @@ -1402,6 +1461,7 @@ Dbtup::disk_restart_undo(Signal* signal, Uint64 lsn, return; case File_formats::Undofile::UNDO_END: + jam(); f_undo_done = true; return; default: @@ -1435,14 +1495,32 @@ Dbtup::disk_restart_undo_next(Signal* signal) } void -Dbtup::disk_restart_mark_no_lcp(Uint32 tableId, Uint32 fragId) +Dbtup::disk_restart_lcp_id(Uint32 tableId, Uint32 fragId, Uint32 lcpId) { jamEntry(); - disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_CREATE); + + if (lcpId == RNIL) + { + disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_CREATE, 0); + if (DBG_UNDO) + { + ndbout_c("mark_no_lcp (%u, %u)", tableId, fragId); + } + } + else + { + disk_restart_undo_lcp(tableId, fragId, Fragrecord::UC_SET_LCP, lcpId); + if (DBG_UNDO) + { + ndbout_c("mark_no_lcp (%u, %u)", tableId, fragId); + } + + } } void -Dbtup::disk_restart_undo_lcp(Uint32 tableId, Uint32 fragId, Uint32 flag) +Dbtup::disk_restart_undo_lcp(Uint32 tableId, Uint32 fragId, Uint32 flag, + Uint32 lcpId) { Ptr tabPtr; tabPtr.i= tableId; @@ -1450,11 +1528,43 @@ Dbtup::disk_restart_undo_lcp(Uint32 tableId, Uint32 fragId, Uint32 flag) if (tabPtr.p->tableStatus == DEFINED) { + jam(); FragrecordPtr fragPtr; getFragmentrec(fragPtr, fragId, tabPtr.p); if (!fragPtr.isNull()) { - fragPtr.p->m_undo_complete |= flag; + jam(); + switch(flag){ + case Fragrecord::UC_CREATE: + jam(); + fragPtr.p->m_undo_complete |= flag; + return; + case Fragrecord::UC_LCP: + jam(); + if (fragPtr.p->m_undo_complete == 0 && + fragPtr.p->m_restore_lcp_id == lcpId) + { + jam(); + fragPtr.p->m_undo_complete |= flag; + if (DBG_UNDO) + ndbout_c("table: %u fragment: %u lcp: %u -> done", + tableId, fragId, lcpId); + } + return; + case Fragrecord::UC_SET_LCP: + { + jam(); + if (DBG_UNDO) + ndbout_c("table: %u fragment: %u restore to lcp: %u", + tableId, fragId, lcpId); + ndbrequire(fragPtr.p->m_undo_complete == 0); + ndbrequire(fragPtr.p->m_restore_lcp_id == RNIL); + fragPtr.p->m_restore_lcp_id = lcpId; + return; + } + } + jamLine(flag); + ndbrequire(false); } } } @@ -1478,6 +1588,7 @@ Dbtup::disk_restart_undo_callback(Signal* signal, pagePtr.p->nextList != RNIL || pagePtr.p->prevList != RNIL) { + jam(); update = true; pagePtr.p->list_index |= 0x8000; pagePtr.p->nextList = pagePtr.p->prevList = RNIL; @@ -1488,6 +1599,9 @@ Dbtup::disk_restart_undo_callback(Signal* signal, if (tableId >= cnoOfTablerec) { + jam(); + if (DBG_UNDO) + ndbout_c("UNDO table> %u", tableId); disk_restart_undo_next(signal); return; } @@ -1496,6 +1610,9 @@ Dbtup::disk_restart_undo_callback(Signal* signal, if (undo->m_table_ptr.p->tableStatus != DEFINED) { + jam(); + if (DBG_UNDO) + ndbout_c("UNDO !defined (%u) ", tableId); disk_restart_undo_next(signal); return; } @@ -1503,19 +1620,25 @@ Dbtup::disk_restart_undo_callback(Signal* signal, getFragmentrec(undo->m_fragment_ptr, fragId, undo->m_table_ptr.p); if(undo->m_fragment_ptr.isNull()) { + jam(); + if (DBG_UNDO) + ndbout_c("UNDO fragment null %u/%u", tableId, fragId); disk_restart_undo_next(signal); return; } if (undo->m_fragment_ptr.p->m_undo_complete) { + jam(); + if (DBG_UNDO) + ndbout_c("UNDO undo complete %u/%u", tableId, fragId); disk_restart_undo_next(signal); return; } - Local_key key; - key.m_page_no = pagePtr.p->m_page_no; - key.m_file_no = pagePtr.p->m_file_no; + Local_key key = undo->m_key; +// key.m_page_no = pagePtr.p->m_page_no; +// key.m_file_no = pagePtr.p->m_file_no; Uint64 lsn = 0; lsn += pagePtr.p->m_page_header.m_page_lsn_hi; lsn <<= 32; @@ -1525,6 +1648,7 @@ Dbtup::disk_restart_undo_callback(Signal* signal, if (undo->m_lsn <= lsn) { + jam(); if (DBG_UNDO) { ndbout << "apply: " << undo->m_lsn << "(" << lsn << " )" @@ -1539,12 +1663,15 @@ Dbtup::disk_restart_undo_callback(Signal* signal, */ switch(undo->m_type){ case File_formats::Undofile::UNDO_TUP_ALLOC: + jam(); disk_restart_undo_alloc(undo); break; case File_formats::Undofile::UNDO_TUP_UPDATE: + jam(); disk_restart_undo_update(undo); break; case File_formats::Undofile::UNDO_TUP_FREE: + jam(); disk_restart_undo_free(undo); break; default: @@ -1559,14 +1686,17 @@ Dbtup::disk_restart_undo_callback(Signal* signal, m_pgman.update_lsn(undo->m_key, lsn); jamEntry(); + + disk_restart_undo_page_bits(signal, undo); } else if (DBG_UNDO) { + jam(); ndbout << "ignore: " << undo->m_lsn << "(" << lsn << " )" - << key << " type: " << undo->m_type << endl; + << key << " type: " << undo->m_type + << " tab: " << tableId << endl; } - disk_restart_undo_page_bits(signal, undo); disk_restart_undo_next(signal); } @@ -1641,16 +1771,12 @@ Dbtup::disk_restart_undo_page_bits(Signal* signal, Apply_undo* undo) Uint32 new_bits = alloc.calc_page_free_bits(free); pageP->list_index = 0x8000 | new_bits; - Uint64 lsn = 0; - lsn += pageP->m_page_header.m_page_lsn_hi; lsn <<= 32; - lsn += pageP->m_page_header.m_page_lsn_lo; - Tablespace_client tsman(signal, c_tsman, fragPtrP->fragTableId, fragPtrP->fragmentId, fragPtrP->m_tablespace_id); - tsman.restart_undo_page_free_bits(&undo->m_key, new_bits, undo->m_lsn, lsn); + tsman.restart_undo_page_free_bits(&undo->m_key, new_bits); jamEntry(); } @@ -1687,6 +1813,7 @@ Dbtup::disk_restart_alloc_extent(Uint32 tableId, Uint32 fragId, if (alloc.m_curr_extent_info_ptr_i != RNIL) { + jam(); Ptr old; c_extent_pool.getPtr(old, alloc.m_curr_extent_info_ptr_i); ndbassert(old.p->m_free_matrix_pos == RNIL); @@ -1713,6 +1840,7 @@ void Dbtup::disk_restart_page_bits(Uint32 tableId, Uint32 fragId, const Local_key*, Uint32 bits) { + jam(); TablerecPtr tabPtr; FragrecordPtr fragPtr; tabPtr.i = tableId; diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp index 3c2d521c1f9..94366905e00 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp @@ -146,6 +146,7 @@ void Dbtup::execTUPFRAGREQ(Signal* signal) regFragPtr.p->m_lcp_scan_op = RNIL; regFragPtr.p->m_lcp_keep_list = RNIL; regFragPtr.p->m_var_page_chunks = RNIL; + regFragPtr.p->m_restore_lcp_id = RNIL; if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId || ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) { @@ -673,11 +674,11 @@ Dbtup::undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused) switch(ret){ case 0: return; + case -1: + warningEvent("Failed to sync log for create of table: %u", regTabPtr.i); default: - ndbout_c("ret: %d", ret); - ndbrequire(false); + execute(signal, req.m_callback, regFragPtr.p->m_logfile_group_id); } - } void @@ -958,8 +959,6 @@ void Dbtup::releaseFragment(Signal* signal, Uint32 tableId, return; } -#if NOT_YET_UNDO_DROP_TABLE -#error "This code is complete, but I prefer not to enable it until I need it" if (logfile_group_id != RNIL) { Callback cb; @@ -968,7 +967,14 @@ void Dbtup::releaseFragment(Signal* signal, Uint32 tableId, safe_cast(&Dbtup::drop_table_log_buffer_callback); Uint32 sz= sizeof(Disk_undo::Drop) >> 2; int r0 = c_lgman->alloc_log_space(logfile_group_id, sz); - + if (r0) + { + jam(); + warningEvent("Failed to alloc log space for drop table: %u", + tabPtr.i); + goto done; + } + Logfile_client lgman(this, c_lgman, logfile_group_id); int res= lgman.get_log_buffer(signal, sz, &cb); switch(res){ @@ -976,15 +982,18 @@ void Dbtup::releaseFragment(Signal* signal, Uint32 tableId, ljam(); return; case -1: - ndbrequire("NOT YET IMPLEMENTED" == 0); + warningEvent("Failed to get log buffer for drop table: %u", + tabPtr.i); + c_lgman->free_log_space(logfile_group_id, sz); + goto done; break; default: execute(signal, cb, logfile_group_id); return; } } -#endif - + +done: drop_table_logsync_callback(signal, tabPtr.i, RNIL); } @@ -1163,9 +1172,10 @@ Dbtup::drop_table_log_buffer_callback(Signal* signal, Uint32 tablePtrI, switch(ret){ case 0: return; + case -1: + warningEvent("Failed to syn log for drop of table: %u", tablePtrI); default: - ndbout_c("ret: %d", ret); - ndbrequire(false); + execute(signal, req.m_callback, logfile_group_id); } } diff --git a/storage/ndb/src/kernel/blocks/lgman.cpp b/storage/ndb/src/kernel/blocks/lgman.cpp index 59b95f4e97f..ce01b31927c 100644 --- a/storage/ndb/src/kernel/blocks/lgman.cpp +++ b/storage/ndb/src/kernel/blocks/lgman.cpp @@ -2684,8 +2684,16 @@ Lgman::execute_undo_record(Signal* signal) Uint32 lcp = * (ptr - len + 1); if(m_latest_lcp && lcp > m_latest_lcp) { - // Just ignore - break; + if (0) + { + const Uint32 * base = ptr - len + 1; + Uint32 lcp = base[0]; + Uint32 tableId = base[1] >> 16; + Uint32 fragId = base[1] & 0xFFFF; + + ndbout_c("NOT! ignoring lcp: %u tab: %u frag: %u", + lcp, tableId, fragId); + } } if(m_latest_lcp == 0 || diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp index a5558aa320d..1f914639d6b 100644 --- a/storage/ndb/src/kernel/blocks/pgman.cpp +++ b/storage/ndb/src/kernel/blocks/pgman.cpp @@ -500,6 +500,11 @@ Pgman::release_page_entry(Ptr& ptr) if (! (state & Page_entry::LOCKED)) ndbrequire(! (state & Page_entry::REQUEST)); + + if (ptr.p->m_copy_page_i != RNIL) + { + m_global_page_pool.release(ptr.p->m_copy_page_i); + } set_page_state(ptr, 0); m_page_hashlist.remove(ptr); @@ -1151,7 +1156,8 @@ Pgman::process_cleanup(Signal* signal) #ifdef VM_TRACE debugOut << "PGMAN: " << ptr << " : process_cleanup" << endl; #endif - c_tup->disk_page_unmap_callback(ptr.p->m_real_page_i, + c_tup->disk_page_unmap_callback(0, + ptr.p->m_real_page_i, ptr.p->m_dirty_count); pageout(signal, ptr); max_count--; @@ -1189,6 +1195,11 @@ Pgman::move_cleanup_ptr(Ptr ptr) void Pgman::execLCP_FRAG_ORD(Signal* signal) { + if (ERROR_INSERTED(11008)) + { + ndbout_c("Ignore LCP_FRAG_ORD"); + return; + } LcpFragOrd* ord = (LcpFragOrd*)signal->getDataPtr(); ndbrequire(ord->lcpId >= m_last_lcp_complete + 1 || m_last_lcp_complete == 0); m_last_lcp = ord->lcpId; @@ -1205,6 +1216,12 @@ Pgman::execLCP_FRAG_ORD(Signal* signal) void Pgman::execEND_LCP_REQ(Signal* signal) { + if (ERROR_INSERTED(11008)) + { + ndbout_c("Ignore END_LCP"); + return; + } + EndLcpReq* req = (EndLcpReq*)signal->getDataPtr(); m_end_lcp_req = *req; @@ -1283,7 +1300,8 @@ Pgman::process_lcp(Signal* signal) { DBG_LCP(" pageout()" << endl); ptr.p->m_state |= Page_entry::LCP; - c_tup->disk_page_unmap_callback(ptr.p->m_real_page_i, + c_tup->disk_page_unmap_callback(0, + ptr.p->m_real_page_i, ptr.p->m_dirty_count); pageout(signal, ptr); } @@ -1505,6 +1523,10 @@ Pgman::fswriteconf(Signal* signal, Ptr ptr) Page_state state = ptr.p->m_state; ndbrequire(state & Page_entry::PAGEOUT); + c_tup->disk_page_unmap_callback(1, + ptr.p->m_real_page_i, + ptr.p->m_dirty_count); + state &= ~ Page_entry::PAGEOUT; state &= ~ Page_entry::EMPTY; state &= ~ Page_entry::DIRTY; @@ -1758,7 +1780,7 @@ Pgman::get_page(Signal* signal, Ptr ptr, Page_request page_req) #endif state |= Page_entry::REQUEST; - if (only_request && req_flags & Page_request::EMPTY_PAGE) + if (only_request && (req_flags & Page_request::EMPTY_PAGE)) { state |= Page_entry::EMPTY; } @@ -2420,7 +2442,8 @@ Pgman::execDUMP_STATE_ORD(Signal* signal) if (pl_hash.find(ptr, key)) { ndbout << "pageout " << ptr << endl; - c_tup->disk_page_unmap_callback(ptr.p->m_real_page_i, + c_tup->disk_page_unmap_callback(0, + ptr.p->m_real_page_i, ptr.p->m_dirty_count); pageout(signal, ptr); } @@ -2476,6 +2499,11 @@ Pgman::execDUMP_STATE_ORD(Signal* signal) { SET_ERROR_INSERT_VALUE(11007); } + + if (signal->theData[0] == 11008) + { + SET_ERROR_INSERT_VALUE(11008); + } } // page cache client diff --git a/storage/ndb/src/kernel/blocks/tsman.cpp b/storage/ndb/src/kernel/blocks/tsman.cpp index 97fc19cc0aa..353bfc6e3c5 100644 --- a/storage/ndb/src/kernel/blocks/tsman.cpp +++ b/storage/ndb/src/kernel/blocks/tsman.cpp @@ -302,7 +302,7 @@ Tsman::execDUMP_STATE_ORD(Signal* signal){ Uint32 new_bits = curr_bits ^ rand(); Local_key key = chunks[chunk].start_page; key.m_page_no += page; - ndbrequire(update_page_free_bits(signal, &key, new_bits, 0) == 0); + ndbrequire(update_page_free_bits(signal, &key, new_bits) == 0); } } } @@ -369,6 +369,20 @@ Tsman::execCREATE_FILEGROUP_REQ(Signal* signal){ CreateFilegroupImplRef::SignalLength, JBB); } +NdbOut& +operator<<(NdbOut& out, const File_formats::Datafile::Extent_header & obj) +{ + out << "table: " << obj.m_table + << " fragment: " << obj.m_fragment_id << " "; + for(Uint32 i = 0; i<32; i++) + { + char t[2]; + BaseString::snprintf(t, sizeof(t), "%x", obj.get_free_bits(i)); + out << t; + } + return out; +} + void Tsman::execDROP_FILEGROUP_REQ(Signal* signal){ jamEntry(); @@ -1582,8 +1596,7 @@ Tsman::execFREE_EXTENT_REQ(Signal* signal) int Tsman::update_page_free_bits(Signal* signal, Local_key *key, - unsigned committed_bits, - Uint64 lsn) + unsigned committed_bits) { jamEntry(); @@ -1618,6 +1631,18 @@ Tsman::update_page_free_bits(Signal* signal, File_formats::Datafile::Extent_header* header = page->get_header(val.m_extent_no, val.m_extent_size); + if (header->m_table == RNIL) + { + ndbout << "update page free bits page: " << *key + << " " << *header << endl; + } + + if (0) + { + ndbout << "update page free bits page(" << committed_bits << ") " + << *key << " " << *header << endl; + } + ndbrequire(header->m_table != RNIL); Uint32 page_no_in_extent = calc_page_no_in_extent(key->m_page_no, &val); @@ -1629,7 +1654,7 @@ Tsman::update_page_free_bits(Signal* signal, Uint32 src = header->get_free_bits(page_no_in_extent) & UNCOMMITTED_MASK; header->update_free_bits(page_no_in_extent, src | committed_bits); - m_page_cache_client.update_lsn(preq.m_page, lsn); + m_page_cache_client.update_lsn(preq.m_page, 0); return 0; } @@ -1717,6 +1742,11 @@ Tsman::unmap_page(Signal* signal, Local_key *key, Uint32 uncommitted_bits) File_formats::Datafile::Extent_header* header = page->get_header(val.m_extent_no, val.m_extent_size); + if (header->m_table == RNIL) + { + ndbout << "trying to unmap page: " << *key + << " " << *header << endl; + } ndbrequire(header->m_table != RNIL); Uint32 page_no_in_extent = calc_page_no_in_extent(key->m_page_no, &val); @@ -1738,9 +1768,7 @@ Tsman::restart_undo_page_free_bits(Signal* signal, Uint32 tableId, Uint32 fragId, Local_key *key, - unsigned bits, - Uint64 undo_lsn, - Uint64 page_lsn) + unsigned bits) { jamEntry(); @@ -1774,21 +1802,7 @@ Tsman::restart_undo_page_free_bits(Signal* signal, (File_formats::Datafile::Extent_page*)ptr_p; File_formats::Datafile::Extent_header* header = page->get_header(val.m_extent_no, val.m_extent_size); - - Uint64 lsn = 0; - lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32; - lsn += page->m_page_header.m_page_lsn_lo; - - if (undo_lsn > lsn && undo_lsn > page_lsn) - { - if (DBG_UNDO) - ndbout << "tsman: ignore " << undo_lsn << "(" << lsn << ", " - << page_lsn << ") " - << *key << " " - << " -> " << bits << endl; - return 0; - } - + if (header->m_table == RNIL) { if (DBG_UNDO) @@ -1807,7 +1821,7 @@ Tsman::restart_undo_page_free_bits(Signal* signal, */ if (DBG_UNDO) { - ndbout << "tsman: apply " << undo_lsn << "(" << lsn << ") " + ndbout << "tsman: apply " << *key << " " << (src & COMMITTED_MASK) << " -> " << bits << endl; } @@ -1855,7 +1869,7 @@ Tsman::execALLOC_PAGE_REQ(Signal* signal) /** * Handling of unmapped extent header pages is not implemented */ - int flags = 0; + int flags = Page_cache_client::DIRTY_REQ; int real_page_id; Uint32 page_no; Uint32 src_bits; diff --git a/storage/ndb/src/kernel/blocks/tsman.hpp b/storage/ndb/src/kernel/blocks/tsman.hpp index 1293cc54141..20019e6d4d1 100644 --- a/storage/ndb/src/kernel/blocks/tsman.hpp +++ b/storage/ndb/src/kernel/blocks/tsman.hpp @@ -209,12 +209,12 @@ private: void load_extent_page_callback(Signal*, Uint32, Uint32); void create_file_ref(Signal*, Ptr, Ptr, Uint32,Uint32,Uint32); - int update_page_free_bits(Signal*, Local_key*, unsigned committed_bits, - Uint64 lsn); + int update_page_free_bits(Signal*, Local_key*, unsigned committed_bits); + int get_page_free_bits(Signal*, Local_key*, unsigned*, unsigned*); int unmap_page(Signal*, Local_key*, unsigned uncommitted_bits); int restart_undo_page_free_bits(Signal*, Uint32, Uint32, Local_key*, - unsigned committed_bits, Uint64, Uint64); + unsigned committed_bits); int alloc_extent(Signal* signal, Uint32 tablespace, Local_key* key); int alloc_page_from_extent(Signal*, Uint32, Local_key*, Uint32 bits); @@ -320,7 +320,7 @@ public: /** * Update page free bits */ - int update_page_free_bits(Local_key*, unsigned bits, Uint64 lsn); + int update_page_free_bits(Local_key*, unsigned bits); /** * Get page free bits @@ -336,8 +336,7 @@ public: /** * Undo handling of page bits */ - int restart_undo_page_free_bits(Local_key*, unsigned bits, - Uint64 lsn, Uint64 page_lsn); + int restart_undo_page_free_bits(Local_key*, unsigned bits); /** * Get tablespace info @@ -417,10 +416,9 @@ Tablespace_client::free_extent(Local_key* key, Uint64 lsn) inline int Tablespace_client::update_page_free_bits(Local_key *key, - unsigned committed_bits, - Uint64 lsn) + unsigned committed_bits) { - return m_tsman->update_page_free_bits(m_signal, key, committed_bits, lsn); + return m_tsman->update_page_free_bits(m_signal, key, committed_bits); } inline @@ -442,17 +440,13 @@ Tablespace_client::unmap_page(Local_key *key, unsigned uncommitted_bits) inline int Tablespace_client::restart_undo_page_free_bits(Local_key* key, - unsigned committed_bits, - Uint64 lsn, - Uint64 page_lsn) + unsigned committed_bits) { return m_tsman->restart_undo_page_free_bits(m_signal, m_table_id, m_fragment_id, key, - committed_bits, - lsn, - page_lsn); + committed_bits); } #endif From 9a5ae909d6af91416f294373b3dfb7d533263519 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 15:57:01 +0200 Subject: [PATCH 23/92] ndb - bug#31257 handle partially complete LCP better in SR --- storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp | 1 + .../ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 35 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index 6321679269d..317983323cc 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -318,6 +318,7 @@ public: Uint8 noOfStartedChkpt; MasterLCPConf::State lcpStateAtTakeOver; + Uint32 m_remove_node_from_table_lcp_id; }; typedef Ptr NodeRecordPtr; /**********************************************************************/ diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index e731bde5917..f4433b9d264 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -4989,6 +4989,18 @@ void Dbdih::startRemoveFailedNode(Signal* signal, NodeRecordPtr failedNodePtr) return; } + /** + * If node has node complete LCP + * we need to remove it as undo might not be complete + * bug#31257 + */ + failedNodePtr.p->m_remove_node_from_table_lcp_id = RNIL; + if (c_lcpState.m_LCP_COMPLETE_REP_Counter_LQH.isWaitingFor(failedNodePtr.i)) + { + jam(); + failedNodePtr.p->m_remove_node_from_table_lcp_id = SYSFILE->latestLCP_ID; + } + jam(); signal->theData[0] = DihContinueB::ZREMOVE_NODE_FROM_TABLE; signal->theData[1] = failedNodePtr.i; @@ -5630,6 +5642,11 @@ void Dbdih::removeNodeFromTable(Signal* signal, return; }//if + NodeRecordPtr nodePtr; + nodePtr.i = nodeId; + ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord); + const Uint32 lcpId = nodePtr.p->m_remove_node_from_table_lcp_id; + /** * For each fragment */ @@ -5637,7 +5654,6 @@ void Dbdih::removeNodeFromTable(Signal* signal, Uint32 noOfRemovedLcpReplicas = 0; // No of replicas in LCP removed Uint32 noOfRemainingLcpReplicas = 0;// No of replicas in LCP remaining - //const Uint32 lcpId = SYSFILE->latestLCP_ID; const bool lcpOngoingFlag = (tabPtr.p->tabLcpStatus== TabRecord::TLS_ACTIVE); const bool unlogged = (tabPtr.p->tabStorage != TabRecord::ST_NORMAL); @@ -5672,6 +5688,23 @@ void Dbdih::removeNodeFromTable(Signal* signal, noOfRemovedLcpReplicas ++; replicaPtr.p->lcpOngoingFlag = false; } + + if (lcpId != RNIL) + { + jam(); + Uint32 lcpNo = prevLcpNo(replicaPtr.p->nextLcp); + if (replicaPtr.p->lcpStatus[lcpNo] == ZVALID && + replicaPtr.p->lcpId[lcpNo] == SYSFILE->latestLCP_ID) + { + jam(); + replicaPtr.p->lcpStatus[lcpNo] = ZINVALID; + replicaPtr.p->lcpId[lcpNo] = 0; + replicaPtr.p->nextLcp = lcpNo; + ndbout_c("REMOVING lcp: %u from table: %u frag: %u node: %u", + SYSFILE->latestLCP_ID, + tabPtr.i, fragNo, nodeId); + } + } } } if (!found) From dac3eb008e8728fda1767c3bc4ec2cb16945f097 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 15:58:08 +0200 Subject: [PATCH 24/92] ndb - remove extra ; (in test framework) --- storage/ndb/test/src/NDBT_Thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/test/src/NDBT_Thread.cpp b/storage/ndb/test/src/NDBT_Thread.cpp index 56cf2f6815b..ff6785724ba 100644 --- a/storage/ndb/test/src/NDBT_Thread.cpp +++ b/storage/ndb/test/src/NDBT_Thread.cpp @@ -131,7 +131,7 @@ NDBT_Thread::exit() m_state = Exit; signal(); unlock(); -}; +} void NDBT_Thread::join() From 48847b3604f4d510ee9af54eb27bcaedbaf223e5 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 16:00:18 +0200 Subject: [PATCH 25/92] ndb - Fix disk scan (backup) (introduced by only updating extent pages after pageout) --- storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp index bb3d8cc0626..eecbee4c058 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp @@ -771,7 +771,7 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) uncommitted = committed = ~(unsigned)0; int ret = tsman.get_page_free_bits(&key, &uncommitted, &committed); ndbrequire(ret == 0); - if (committed == 0) { + if (committed == 0 && uncommitted == 0) { // skip empty page jam(); pos.m_get = ScanPos::Get_next_page_dd; From 67da3a64383e7e258652da2eed166d49ca5e2fa5 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 16:02:21 +0200 Subject: [PATCH 26/92] ndb - fix dd drop table race condition add list of pages being unmaped, so we can wait for it to be empty before dropping extents --- storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp | 2 ++ .../ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp | 6 ++++++ storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp | 13 +++++++++++++ 3 files changed, 21 insertions(+) diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index eaf00138acf..08332a2e1a1 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -563,6 +563,8 @@ typedef Ptr FragoperrecPtr; */ Page_request_list::Head m_page_requests[MAX_FREE_LIST]; + DLList::Head m_unmap_pages; + /** * Current extent */ diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp index 4509adb7da0..a235e02a4b7 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp @@ -956,7 +956,9 @@ Dbtup::disk_page_unmap_callback(Uint32 when, ArrayPool *pool= (ArrayPool*)&m_global_page_pool; LocalDLList list(*pool, alloc.m_dirty_pages[idx]); + LocalDLList list2(*pool, alloc.m_unmap_pages); list.remove(pagePtr); + list2.add(pagePtr); if (dirty_count == 0) { @@ -999,6 +1001,10 @@ Dbtup::disk_page_unmap_callback(Uint32 when, << " cnt: " << dirty_count << " " << (idx & ~0x8000) << endl; } + ArrayPool *pool= (ArrayPool*)&m_global_page_pool; + LocalDLList list(*pool, alloc.m_unmap_pages); + list.remove(pagePtr); + Tablespace_client tsman(0, c_tsman, fragPtr.p->fragTableId, fragPtr.p->fragmentId, diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp index 94366905e00..4df3f91068c 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp @@ -1005,7 +1005,20 @@ Dbtup::drop_fragment_unmap_pages(Signal *signal, { if (tabPtr.p->m_no_of_disk_attributes) { + jam(); Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info; + + if (!alloc_info.m_unmap_pages.isEmpty()) + { + jam(); + ndbout_c("waiting for unmape pages"); + signal->theData[0] = ZUNMAP_PAGES; + signal->theData[1] = tabPtr.i; + signal->theData[2] = fragPtr.i; + signal->theData[3] = pos; + sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB); + return; + } while(alloc_info.m_dirty_pages[pos].isEmpty() && pos < MAX_FREE_LIST) pos++; From 0bf788057dad4c8c0b98d71cff7552eae053f710 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 8 Oct 2007 16:10:41 +0200 Subject: [PATCH 27/92] ndb - post merge fixes --- storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp | 4 ---- storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp index 9115ddf2e67..8420e7f2bde 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp @@ -1026,8 +1026,6 @@ Dbtup::disk_page_alloc(Signal* signal, Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info; Uint64 lsn; - Uint32 old_free = pagePtr.p->free_space; - Uint32 old_bits= alloc.calc_page_free_bits(old_free); if (tabPtrP->m_attributes[DD].m_no_of_varsize == 0) { ddassert(pagePtr.p->uncommitted_used_space > 0); @@ -1059,7 +1057,6 @@ Dbtup::disk_page_free(Signal *signal, Uint32 logfile_group_id= fragPtrP->m_logfile_group_id; Disk_alloc_info& alloc= fragPtrP->m_disk_alloc_info; Uint32 old_free= pagePtr.p->free_space; - Uint32 old_bits= alloc.calc_page_free_bits(old_free); Uint32 sz; Uint64 lsn; @@ -1086,7 +1083,6 @@ Dbtup::disk_page_free(Signal *signal, } Uint32 new_free = pagePtr.p->free_space; - Uint32 new_bits = alloc.calc_page_free_bits(new_free); Uint32 ext = pagePtr.p->m_extent_info_ptr; Uint32 used = pagePtr.p->uncommitted_used_space; diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp index e24927c4cb1..c8df5f5154e 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp @@ -967,7 +967,7 @@ void Dbtup::releaseFragment(Signal* signal, Uint32 tableId, cb.m_callbackFunction = safe_cast(&Dbtup::drop_table_log_buffer_callback); Uint32 sz= sizeof(Disk_undo::Drop) >> 2; - (void) c_lgman->alloc_log_space(logfile_group_id, sz); + int r0 = c_lgman->alloc_log_space(logfile_group_id, sz); if (r0) { jam(); From 7453382acfaa63ffa9adadaf68cad6f760b3e51b Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Tue, 9 Oct 2007 09:39:39 +0200 Subject: [PATCH 28/92] Bug #31470 ndb table with special characters in name are not discovered correctly --- mysql-test/suite/ndb/r/ndb_multi.result | 21 +++++++++++++++++++ mysql-test/suite/ndb/t/ndb_multi.test | 27 +++++++++++++++++++++++++ sql/handler.cc | 3 +-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/ndb/r/ndb_multi.result b/mysql-test/suite/ndb/r/ndb_multi.result index 2bc49bf9b45..98c4265b833 100644 --- a/mysql-test/suite/ndb/r/ndb_multi.result +++ b/mysql-test/suite/ndb/r/ndb_multi.result @@ -121,3 +121,24 @@ show tables; Tables_in_db t2 drop database db; +use test; +create table `test`.`t1$EX` + (server_id int unsigned, +master_server_id int unsigned, +master_epoch bigint unsigned, +count int unsigned, +primary key(server_id, master_server_id, +master_epoch, count)) +engine ndb; +show tables like '%$%'; +Tables_in_test (%$%) +t1$EX +use test; +show tables like '%$%'; +Tables_in_test (%$%) +t1$EX +drop table `test`.`t1$EX`; +show tables like '%$%'; +Tables_in_test (%$%) +show tables like '%$%'; +Tables_in_test (%$%) diff --git a/mysql-test/suite/ndb/t/ndb_multi.test b/mysql-test/suite/ndb/t/ndb_multi.test index b8e052d606b..ce7e22b3b7f 100644 --- a/mysql-test/suite/ndb/t/ndb_multi.test +++ b/mysql-test/suite/ndb/t/ndb_multi.test @@ -122,4 +122,31 @@ connection server2; show tables; drop database db; + +# +# bug#31470, ndb table with special characters in name +# are not discovered correctly connection server1; +use test; +create table `test`.`t1$EX` + (server_id int unsigned, + master_server_id int unsigned, + master_epoch bigint unsigned, + count int unsigned, + primary key(server_id, master_server_id, + master_epoch, count)) + engine ndb; + +# check that table shows up ok on both servers +# before bugfix table would not show up on server2 +show tables like '%$%'; +connection server2; +use test; +show tables like '%$%'; + +# check cleanup +drop table `test`.`t1$EX`; +show tables like '%$%'; + +connection server1; +show tables like '%$%'; diff --git a/sql/handler.cc b/sql/handler.cc index dbe7f6727f7..126882c8e44 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2641,8 +2641,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) frmblob and frmlen are set, write the frm to disk */ - (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,FN_ROOTDIR, - db,FN_ROOTDIR,name,NullS); + build_table_filename(path, FN_REFLEN-1, db, name, "", 0); // Save the frm file error= writefrm(path, frmblob, frmlen); my_free(frmblob, MYF(0)); From 1d1b95f07e303260470ff2b3a6bfd57e0bf46169 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 9 Oct 2007 09:55:30 +0200 Subject: [PATCH 29/92] ndb - testSystemRestart -n SR_UNDO yet another test prg bug --- storage/ndb/test/ndbapi/testSystemRestart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/test/ndbapi/testSystemRestart.cpp b/storage/ndb/test/ndbapi/testSystemRestart.cpp index 419c1eb1438..67429ee0a41 100644 --- a/storage/ndb/test/ndbapi/testSystemRestart.cpp +++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp @@ -330,7 +330,7 @@ int runSystemRestartTestUndoLog(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); CHECK(hugoTrans.loadTable(pNdb, records) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); From c9f7d2243709113afe1bd1ddecba6afbb37c1439 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 9 Oct 2007 10:41:26 +0200 Subject: [PATCH 30/92] ndb - more test prg fixes (due to small change in scanUpdates impl.) (autotest tests) --- storage/ndb/test/ndbapi/testDict.cpp | 4 ++-- storage/ndb/test/ndbapi/testIndex.cpp | 4 ++-- storage/ndb/test/ndbapi/test_event.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp index f7de43aea20..656b074ce8b 100644 --- a/storage/ndb/test/ndbapi/testDict.cpp +++ b/storage/ndb/test/ndbapi/testDict.cpp @@ -679,7 +679,7 @@ int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == records); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == (records/2)); @@ -857,7 +857,7 @@ int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){ CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == records); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); CHECK(count == (records/2)); CHECK(utilTrans.clearTable(pNdb, records) == 0); diff --git a/storage/ndb/test/ndbapi/testIndex.cpp b/storage/ndb/test/ndbapi/testIndex.cpp index 7691f036a46..e52aafa296b 100644 --- a/storage/ndb/test/ndbapi/testIndex.cpp +++ b/storage/ndb/test/ndbapi/testIndex.cpp @@ -809,7 +809,7 @@ int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){ CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0); CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0); @@ -834,7 +834,7 @@ int runSystemRestart1(NDBT_Context* ctx, NDBT_Step* step){ CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0); CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0); CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0); - CHECK(hugoTrans.scanUpdateRecords(pNdb, records) == 0); + CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0); CHECK(utilTrans.verifyIndex(pNdb, idxName, 16, false) == 0); CHECK(utilTrans.clearTable(pNdb, records) == 0); CHECK(hugoTrans.loadTable(pNdb, records, 1) == 0); diff --git a/storage/ndb/test/ndbapi/test_event.cpp b/storage/ndb/test/ndbapi/test_event.cpp index e1e0012d0d8..2083e235a3e 100644 --- a/storage/ndb/test/ndbapi/test_event.cpp +++ b/storage/ndb/test/ndbapi/test_event.cpp @@ -1730,7 +1730,7 @@ runScanUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){ HugoTransactions hugoTrans(*ctx->getTab()); while (ctx->isTestStopped() == false) { - if (hugoTrans.scanUpdateRecords(GETNDB(step), records, abort, + if (hugoTrans.scanUpdateRecords(GETNDB(step), 0, abort, parallelism) == NDBT_FAILED){ return NDBT_FAILED; } From 4bb09aecd4b0750fd8c20fc14407e49a0d4254cf Mon Sep 17 00:00:00 2001 From: "jmiller/ndbdev@mysql.com/ndb15.mysql.com" <> Date: Tue, 9 Oct 2007 19:51:57 +0200 Subject: [PATCH 31/92] Updated NDB test to run for both RBR and MBR testing. In addition added test for Innodb and updated results files for all tests. --- .../extra/rpl_tests/rpl_row_charset.test | 6 +- mysql-test/suite/rpl/r/rpl_row_charset.result | 8 +- .../suite/rpl/r/rpl_row_charset_innodb.result | 215 ++++++++++++++++++ .../rpl/t/rpl_row_charset_innodb-master.opt | 1 + .../rpl/t/rpl_row_charset_innodb-slave.opt | 1 + .../suite/rpl/t/rpl_row_charset_innodb.test | 9 + .../suite/rpl_ndb/r/rpl_ndb_charset.result | 34 +-- .../suite/rpl_ndb/t/rpl_ndb_charset.test | 4 +- 8 files changed, 254 insertions(+), 24 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_row_charset_innodb.result create mode 100644 mysql-test/suite/rpl/t/rpl_row_charset_innodb-master.opt create mode 100644 mysql-test/suite/rpl/t/rpl_row_charset_innodb-slave.opt create mode 100644 mysql-test/suite/rpl/t/rpl_row_charset_innodb.test diff --git a/mysql-test/extra/rpl_tests/rpl_row_charset.test b/mysql-test/extra/rpl_tests/rpl_row_charset.test index a21ed5bb841..c1eccff9bd5 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_charset.test +++ b/mysql-test/extra/rpl_tests/rpl_row_charset.test @@ -38,7 +38,7 @@ show create database mysqltest3; connection master; use mysqltest2; -create table t1 (a int auto_increment primary key, b varchar(100)); +--eval create table t1 (a int auto_increment primary key, b varchar(100))engine=$engine_type; set character_set_client=cp850, collation_connection=latin2_croatian_ci; insert into t1 (b) values(@@character_set_server); insert into t1 (b) values(@@collation_server); @@ -146,13 +146,15 @@ set collation_server=9999998; select "--- --3943--" as ""; use test; -CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255)); +--eval CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))ENGINE=$engine_type; SET CHARACTER_SET_CLIENT=koi8r, CHARACTER_SET_CONNECTION=cp1251, CHARACTER_SET_RESULTS=koi8r; INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ'); +SET SQL_BIG_SELECTS=1; select hex(c1), hex(c2) from t1; sync_slave_with_master; +SET SQL_BIG_SELECTS=1; select hex(c1), hex(c2) from t1; connection master; diff --git a/mysql-test/suite/rpl/r/rpl_row_charset.result b/mysql-test/suite/rpl/r/rpl_row_charset.result index e51f3e57d1f..caaa9d8332b 100644 --- a/mysql-test/suite/rpl/r/rpl_row_charset.result +++ b/mysql-test/suite/rpl/r/rpl_row_charset.result @@ -40,7 +40,7 @@ show create database mysqltest3; Database Create Database mysqltest3 CREATE DATABASE `mysqltest3` /*!40100 DEFAULT CHARACTER SET armscii8 COLLATE armscii8_bin */ use mysqltest2; -create table t1 (a int auto_increment primary key, b varchar(100)); +create table t1 (a int auto_increment primary key, b varchar(100))engine=myisam;; set character_set_client=cp850, collation_connection=latin2_croatian_ci; insert into t1 (b) values(@@character_set_server); insert into t1 (b) values(@@collation_server); @@ -117,7 +117,7 @@ master-bin.000001 # Query # # create database mysqltest2 character set latin2 master-bin.000001 # Query # # create database mysqltest3 master-bin.000001 # Query # # drop database mysqltest3 master-bin.000001 # Query # # create database mysqltest3 -master-bin.000001 # Query # # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100)) +master-bin.000001 # Query # # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))engine=myisam master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) @@ -177,14 +177,16 @@ select "--- --3943--" as ""; --- --3943-- use test; -CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255)); +CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))ENGINE=myisam;; SET CHARACTER_SET_CLIENT=koi8r, CHARACTER_SET_CONNECTION=cp1251, CHARACTER_SET_RESULTS=koi8r; INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ'); +SET SQL_BIG_SELECTS=1; select hex(c1), hex(c2) from t1; hex(c1) hex(c2) CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 +SET SQL_BIG_SELECTS=1; select hex(c1), hex(c2) from t1; hex(c1) hex(c2) CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 diff --git a/mysql-test/suite/rpl/r/rpl_row_charset_innodb.result b/mysql-test/suite/rpl/r/rpl_row_charset_innodb.result new file mode 100644 index 00000000000..eb1dc585457 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_charset_innodb.result @@ -0,0 +1,215 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +set timestamp=1000000000; +drop database if exists mysqltest2; +drop database if exists mysqltest3; +create database mysqltest2 character set latin2; +set @@character_set_server=latin5; +create database mysqltest3; + +--- --master-- +show create database mysqltest2; +Database Create Database +mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET latin2 */ +show create database mysqltest3; +Database Create Database +mysqltest3 CREATE DATABASE `mysqltest3` /*!40100 DEFAULT CHARACTER SET latin5 */ + +--- --slave-- +show create database mysqltest2; +Database Create Database +mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET latin2 */ +show create database mysqltest3; +Database Create Database +mysqltest3 CREATE DATABASE `mysqltest3` /*!40100 DEFAULT CHARACTER SET latin5 */ +set @@collation_server=armscii8_bin; +drop database mysqltest3; +create database mysqltest3; + +--- --master-- +show create database mysqltest3; +Database Create Database +mysqltest3 CREATE DATABASE `mysqltest3` /*!40100 DEFAULT CHARACTER SET armscii8 COLLATE armscii8_bin */ + +--- --slave-- +show create database mysqltest3; +Database Create Database +mysqltest3 CREATE DATABASE `mysqltest3` /*!40100 DEFAULT CHARACTER SET armscii8 COLLATE armscii8_bin */ +use mysqltest2; +create table t1 (a int auto_increment primary key, b varchar(100))engine=innodb;; +set character_set_client=cp850, collation_connection=latin2_croatian_ci; +insert into t1 (b) values(@@character_set_server); +insert into t1 (b) values(@@collation_server); +insert into t1 (b) values(@@character_set_client); +insert into t1 (b) values(@@character_set_connection); +insert into t1 (b) values(@@collation_connection); + +--- --master-- +select * from t1 order by a; +a b +1 armscii8 +2 armscii8_bin +3 cp850 +4 latin2 +5 latin2_croatian_ci + +--- --slave-- +select * from mysqltest2.t1 order by a; +a b +1 armscii8 +2 armscii8_bin +3 cp850 +4 latin2 +5 latin2_croatian_ci +select "--- --muller--" as ""; + +--- --muller-- +set character_set_client=latin1, collation_connection=latin1_german1_ci; +truncate table t1; +insert into t1 (b) values(@@collation_connection); +insert into t1 (b) values(LEAST("Müller","Muffler")); +set collation_connection=latin1_german2_ci; +insert into t1 (b) values(@@collation_connection); +insert into t1 (b) values(LEAST("Müller","Muffler")); + +--- --master-- +select * from t1 order by a; +a b +1 latin1_german1_ci +2 Muffler +3 latin1_german2_ci +4 Müller + +--- --slave-- +select * from mysqltest2.t1 order by a; +a b +1 latin1_german1_ci +2 Muffler +3 latin1_german2_ci +4 Müller +select "--- --INSERT--" as ""; + +--- --INSERT-- +set @a= _cp850 'Müller' collate cp850_general_ci; +truncate table t1; +insert into t1 (b) values(collation(@a)); + +--- --master-- +select * from t1 order by a; +a b +1 cp850_general_ci + +--- --slave-- +select * from mysqltest2.t1 order by a; +a b +1 cp850_general_ci +drop database mysqltest2; +drop database mysqltest3; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # drop database if exists mysqltest2 +master-bin.000001 # Query # # drop database if exists mysqltest3 +master-bin.000001 # Query # # create database mysqltest2 character set latin2 +master-bin.000001 # Query # # create database mysqltest3 +master-bin.000001 # Query # # drop database mysqltest3 +master-bin.000001 # Query # # create database mysqltest3 +master-bin.000001 # Query # # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))engine=innodb +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `mysqltest2`; truncate table t1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `mysqltest2`; truncate table t1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # drop database mysqltest2 +master-bin.000001 # Query # # drop database mysqltest3 +select "--- --global--" as ""; + +--- --global-- +set global character_set_server=latin2; +set global character_set_server=latin1; +set global character_set_server=latin2; +set global character_set_server=latin1; +select "--- --oneshot--" as ""; + +--- --oneshot-- +set one_shot @@character_set_server=latin5; +set @@max_join_size=1000; +select @@character_set_server; +@@character_set_server +latin5 +select @@character_set_server; +@@character_set_server +latin1 +set @@character_set_server=latin5; +select @@character_set_server; +@@character_set_server +latin5 +select @@character_set_server; +@@character_set_server +latin5 +set one_shot max_join_size=10; +ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server +set character_set_client=9999999; +ERROR 42000: Unknown character set: '9999999' +set collation_server=9999998; +ERROR HY000: Unknown collation: '9999998' +select "--- --3943--" as ""; + +--- --3943-- +use test; +CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))ENGINE=innodb;; +SET CHARACTER_SET_CLIENT=koi8r, +CHARACTER_SET_CONNECTION=cp1251, +CHARACTER_SET_RESULTS=koi8r; +INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ'); +SET SQL_BIG_SELECTS=1; +select hex(c1), hex(c2) from t1; +hex(c1) hex(c2) +CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 +SET SQL_BIG_SELECTS=1; +select hex(c1), hex(c2) from t1; +hex(c1) hex(c2) +CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 +drop table t1; +select "--- --6676--" as ""; + +--- --6676-- +create table `t1` ( +`pk` varchar(10) not null default '', +primary key (`pk`) +) engine=innodb default charset=latin1; +set @p=_latin1 'test'; +update t1 set pk='test' where pk=@p; +drop table t1; diff --git a/mysql-test/suite/rpl/t/rpl_row_charset_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_row_charset_innodb-master.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_charset_innodb-master.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/suite/rpl/t/rpl_row_charset_innodb-slave.opt b/mysql-test/suite/rpl/t/rpl_row_charset_innodb-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_charset_innodb-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/suite/rpl/t/rpl_row_charset_innodb.test b/mysql-test/suite/rpl/t/rpl_row_charset_innodb.test new file mode 100644 index 00000000000..1465500d0eb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_charset_innodb.test @@ -0,0 +1,9 @@ +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +# Added to skip if ndb is default # +######################################################## +-- source include/not_ndb_default.inc +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=innodb; +-- source extra/rpl_tests/rpl_row_charset.test diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_charset.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_charset.result index ed9b3cfbfa8..8b1f3093332 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_charset.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_charset.result @@ -40,7 +40,7 @@ show create database mysqltest3; Database Create Database mysqltest3 CREATE DATABASE `mysqltest3` /*!40100 DEFAULT CHARACTER SET armscii8 COLLATE armscii8_bin */ use mysqltest2; -create table t1 (a int auto_increment primary key, b varchar(100)); +create table t1 (a int auto_increment primary key, b varchar(100))engine=NDB;; set character_set_client=cp850, collation_connection=latin2_croatian_ci; insert into t1 (b) values(@@character_set_server); insert into t1 (b) values(@@collation_server); @@ -117,29 +117,27 @@ master-bin.000001 # Query # # create database mysqltest2 character set latin2 master-bin.000001 # Query # # create database mysqltest3 master-bin.000001 # Query # # drop database mysqltest3 master-bin.000001 # Query # # create database mysqltest3 -master-bin.000001 # Query # # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100)) -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))engine=NDB +master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Table_map # # table_id: # (mysql.ndb_apply_status) +master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `mysqltest2`; truncate table t1 +master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Table_map # # table_id: # (mysql.ndb_apply_status) +master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `mysqltest2`; truncate table t1 +master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysqltest2.t1) +master-bin.000001 # Table_map # # table_id: # (mysql.ndb_apply_status) +master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # drop database mysqltest2 master-bin.000001 # Query # # drop database mysqltest3 select "--- --global--" as ""; @@ -177,14 +175,16 @@ select "--- --3943--" as ""; --- --3943-- use test; -CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255)); +CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))ENGINE=NDB;; SET CHARACTER_SET_CLIENT=koi8r, CHARACTER_SET_CONNECTION=cp1251, CHARACTER_SET_RESULTS=koi8r; INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ'); +SET SQL_BIG_SELECTS=1; select hex(c1), hex(c2) from t1; hex(c1) hex(c2) CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 +SET SQL_BIG_SELECTS=1; select hex(c1), hex(c2) from t1; hex(c1) hex(c2) CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_charset.test b/mysql-test/suite/rpl_ndb/t/rpl_ndb_charset.test index 4bac267443e..f14229a52f9 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_charset.test +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_charset.test @@ -1,8 +1,8 @@ ######################################################## # By JBM 2005-02-15 Wrapped to allow reuse of test code# ######################################################## ---source include/have_ndb.inc --- source include/have_binlog_format_row.inc +-- source include/have_ndb.inc +-- source include/have_binlog_format_mixed_or_row.inc -- source include/ndb_master-slave.inc let $engine_type=NDB; -- source extra/rpl_tests/rpl_row_charset.test From ae700296b5e592c087fb56fe94a562d1be195fc7 Mon Sep 17 00:00:00 2001 From: "jmiller/ndbdev@mysql.com/ndb15.mysql.com" <> Date: Wed, 10 Oct 2007 14:18:34 +0200 Subject: [PATCH 32/92] rpl_bug31076.test, rpl_bug31076.result: Correcting test bug --- mysql-test/suite/rpl/r/rpl_bug31076.result | 1 + mysql-test/suite/rpl/t/rpl_bug31076.test | 3 +++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_bug31076.result b/mysql-test/suite/rpl/r/rpl_bug31076.result index c991b2f1946..2d6bed37901 100644 --- a/mysql-test/suite/rpl/r/rpl_bug31076.result +++ b/mysql-test/suite/rpl/r/rpl_bug31076.result @@ -61,3 +61,4 @@ visits_id myid src ip cc org ref time host entry visit_exit user_id visit_start SELECT * FROM visits_events; event_id visit_id timestamp src data visits_events_id 20000 21231038 2007-09-18 03:59:02 Downloads/MySQL-4.1/mysql-4.1.12a-win32.zip 33712207 +DROP DATABASE track; diff --git a/mysql-test/suite/rpl/t/rpl_bug31076.test b/mysql-test/suite/rpl/t/rpl_bug31076.test index 6cb8cc0d902..70584e4e830 100644 --- a/mysql-test/suite/rpl/t/rpl_bug31076.test +++ b/mysql-test/suite/rpl/t/rpl_bug31076.test @@ -111,3 +111,6 @@ VALUES ('3m3l4rhs6do0sf5p1i9lr94g928a272v', '', '', INET_ATON('71.118.124.98'), SELECT * FROM visits; SELECT * FROM visits_events; + +DROP DATABASE track; +# End 5.1 test case From 44352e16adf6510adfab3ef8f0ae7c4d3f34e062 Mon Sep 17 00:00:00 2001 From: "jmiller/ndbdev@mysql.com/ndb15.mysql.com" <> Date: Wed, 10 Oct 2007 16:43:20 +0200 Subject: [PATCH 33/92] .del-rpl_stm_extraColmaster_ndb.test~5ac81fa1ec366ba: Delete: mysql-test/suite/rpl/t/rpl_stm_extraColmaster_ndb.test .del-rpl_row_extraColmaster_ndb.result~a2c64bae75b49d2: Delete: mysql-test/suite/rpl/r/rpl_row_extraColmaster_ndb.result .del-rpl_row_extraColmaster_ndb.test~523b0954869c4423: Delete: mysql-test/suite/rpl/t/rpl_row_extraColmaster_ndb.test Many files: merged and cleanup of test cases --- .../extra/rpl_tests/rpl_extraMaster_Col.test | 842 ++++++++++++++---- .../rpl/r/rpl_extraColmaster_innodb.result | Bin 38226 -> 98074 bytes .../rpl/r/rpl_extraColmaster_myisam.result | Bin 38226 -> 98074 bytes .../rpl/r/rpl_row_extraColmaster_ndb.result | Bin 19129 -> 0 bytes .../rpl/t/rpl_extraColmaster_innodb.test | 3 +- .../rpl/t/rpl_extraColmaster_myisam.test | 2 + .../rpl/t/rpl_row_extraColmaster_ndb.test | 12 - .../rpl/t/rpl_stm_extraColmaster_ndb.test | 13 - 8 files changed, 696 insertions(+), 176 deletions(-) delete mode 100644 mysql-test/suite/rpl/r/rpl_row_extraColmaster_ndb.result delete mode 100644 mysql-test/suite/rpl/t/rpl_row_extraColmaster_ndb.test delete mode 100644 mysql-test/suite/rpl/t/rpl_stm_extraColmaster_ndb.test diff --git a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test index 26b1e6d5ba0..d3959d10306 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test @@ -1,16 +1,22 @@ ############################################################# +# Author: Chuck +############################################################# # Purpose: To test having extra columns on the master WL#3915 # engine inspecific sourced part ############################################################# - +# Change Author: Jeb +# Change: Cleanup and extend testing +############################################################# # TODO: partition specific # -- source include/have_partition.inc +# Note: Will be done in different test due to NDB using this +# test case. +############################################################ ########### Clean up ################ --disable_warnings --disable_query_log -DROP TABLE IF EXISTS t1,t2,t3,t4,t31; - +DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t10,t11,t12,t13,t14,t15,t16,t17,t18,t31; --enable_query_log --enable_warnings @@ -70,154 +76,87 @@ DROP TABLE IF EXISTS t1,t2,t3,t4,t31; #VARCHAR(M) # - +let $binformat = `SHOW VARIABLES LIKE '%binlog_format%'`; +--echo +--echo *********************************************************** +--echo *********************************************************** +--echo ***************** Start of Testing ************************ +--echo *********************************************************** +--echo *********************************************************** +--echo * This test format == $binformat and engine == $engine_type +--echo *********************************************************** +--echo *********************************************************** +--echo +--echo ***** Testing more columns on the Master ***** +--echo connection master; eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), - f5 FLOAT DEFAULT '2.00') - ENGINE=$engine_type; - -sync_slave_with_master; -alter table t1 drop f5; - -connection master; -INSERT into t1 values (1, 1, 1, 'first', 1.0); - - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; - -connection master; -DROP TABLE t1; -eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), - f5 FLOAT DEFAULT '2.00', - f6 CHAR(4) DEFAULT 'TEST') - ENGINE=$engine_type; - -sync_slave_with_master; -alter table t1 drop f5, drop f6; - -connection master; -INSERT into t1 values (1, 1, 1, 'first', 1.0, 'yksi'); - - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; - -connection master; -DROP TABLE t1; -eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), - f5 FLOAT DEFAULT '2.00', - f6 CHAR(4) DEFAULT 'TEST', - f7 INT DEFAULT '0') - ENGINE=$engine_type; - -sync_slave_with_master; -alter table t1 drop f5, drop f6, drop f7; - -connection master; -INSERT into t1 values (1, 1, 1, 'first', 1.0, 'yksi', 1); - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; - -connection master; -DROP TABLE t1; -eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), - f5 FLOAT DEFAULT '2.00', - f6 CHAR(4) DEFAULT 'TEST', - f7 INT DEFAULT '0', - f8 TEXT) - ENGINE=$engine_type; - -sync_slave_with_master; -alter table t1 drop f5, drop f6, drop f7, drop f8; - -connection master; -INSERT into t1 values (1, 1, 1, 'first', 1.0, 'yksi', 1, 'lounge of happiness'); - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; - -connection master; -DROP TABLE t1; -eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), - f5 FLOAT DEFAULT '2.00', - f6 CHAR(4) DEFAULT 'TEST', - f7 INT DEFAULT '0', - f8 TEXT, - f9 LONGBLOB) - ENGINE=$engine_type; - -sync_slave_with_master; -alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9; - -connection master; -INSERT into t1 values (1, 1, 1, 'first', 1.0, 'yksi', 1, 'lounge of happiness', 'very fat blob'); - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; - -connection master; -DROP TABLE t1; -eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), - f5 FLOAT DEFAULT '2.00', - f6 CHAR(4) DEFAULT 'TEST', - f7 INT DEFAULT '0', - f8 TEXT, - f9 LONGBLOB, - f10 BIT(63)) - ENGINE=$engine_type; - -sync_slave_with_master; -alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10; - -connection master; -INSERT into t1 values (1, 1, 1, 'first', 1.0, 'yksi', 1, 'lounge of happiness', 'very fat blob', b'01010101010101'); - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; - -connection master; -DROP TABLE t1; - eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), /* extra */ - f5 FLOAT DEFAULT '2.00', - f6 CHAR(4) DEFAULT 'TEST', - f7 INT DEFAULT '0', - f8 TEXT, - f9 LONGBLOB, - f10 BIT(63), - f11 VARBINARY(64)) - ENGINE=$engine_type; - -#connection slave; - sync_slave_with_master; - alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11; + f5 FLOAT DEFAULT '2.00', + f6 CHAR(4) DEFAULT 'TEST', + f7 INT DEFAULT '0', + f8 TEXT, + f9 LONGBLOB, + f10 BIT(63), + f11 VARBINARY(64))ENGINE=$engine_type; +--echo +--echo * Alter Table on Slave and drop columns f5 through f11 * +--echo +sync_slave_with_master; +alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11; +--echo +--echo * Insert data in Master then update and delete some rows* +--echo connection master; +let $j= 50; +--disable_query_log +while ($j) +{ + eval INSERT INTO t1 VALUES ($j, $j, $j, 'second', 2.0, 'kaks', 2, + 'got stolen from the paradise', + 'very fat blob', b'01010101010101', + 0x123456); + dec $j; +} +let $j= 30; +while ($j) +{ + eval update t1 set f4= 'next' where f1=$j; + dec $j; + dec $j; + eval delete from t1 where f1=$j; + dec $j; +} +--enable_query_log - INSERT into t1 values (1, 1, 1, 'first', 1.0, 'yksi', 1, 'lounge of happiness', 'very fat blob', b'01010101010101', 0x123456); - INSERT into t1 values (2, 2, 2, 'second', 2.0, 'kaks', 2, 'got stolen from the paradise', 'very fat blob', b'01010101010101', 0x123456), (3, 3, 3, 'third', 3.0, 'kolm', 3, 'got stolen from the paradise', 'very fat blob', b'01010101010101', 0x123456); - update t1 set f4= 'next' where f1=1; - delete from t1 where f1=1; - - select * from t1 order by f3; - +--echo * Select count and 20 rows from Master * +--echo +SELECT COUNT(*) FROM t1; +--echo +SELECT f1,f2,f3,f4,f5,f6,f7,f8,f9, + hex(f10),hex(f11) FROM t1 ORDER BY f3 LIMIT 20; #connection slave; - sync_slave_with_master; ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # ---query_vertical show slave status; - select * from t1 order by f3; +sync_slave_with_master; +--echo +--echo * Select count and 20 rows from Slave * +--echo +SELECT COUNT(*) FROM t1; +--echo +SELECT * FROM t1 ORDER BY f3 LIMIT 20; +--echo +--echo * Show Slave Status * +--echo +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # +--query_vertical show slave status; +--echo ### Altering table def scenario +--echo +--echo ***** Testing Altering table def scenario ***** +--echo connection master; @@ -232,7 +171,7 @@ connection master; f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', f12 SET('a', 'b', 'c') default 'b') ENGINE=$engine_type; - +--echo eval CREATE TABLE t3 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), /* extra */ f5 DOUBLE DEFAULT '2.00', @@ -243,7 +182,7 @@ connection master; f12 SET('a', 'b', 'c') default 'b') ENGINE=$engine_type; - +--echo # no ENUM and SET eval CREATE TABLE t4 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), /* extra */ @@ -256,7 +195,7 @@ connection master; f11 CHAR(255)) ENGINE=$engine_type; - +--echo eval CREATE TABLE t31 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), /* extra */ @@ -293,7 +232,9 @@ connection master; f34 VARBINARY(1025), f35 VARCHAR(257) ) ENGINE=$engine_type; - +--echo +--echo ** Alter tables on slave and drop columns ** +--echo #connection slave; sync_slave_with_master; alter table t2 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11, drop @@ -308,8 +249,8 @@ f12; drop f26, drop f27, drop f28, drop f29, drop f30, drop f31, drop f32, drop f33, drop f34, drop f35; - - +--echo +--echo ** Insert Data into Master ** connection master; INSERT into t2 set f1=1, f2=1, f3=1, f4='first', f8='f8: medium size blob', f10='f10: some var char'; @@ -458,7 +399,10 @@ binary data'; /*f34 VARBINARY(1025),*/ '3333 minus 3', /*f35 VARCHAR(257),*/ NULL ); - +--echo +--echo ** Sync slave with master ** +--echo ** Do selects from tables ** +--echo #connection slave; sync_slave_with_master; @@ -469,24 +413,33 @@ binary data'; select * from t31 order by f1; connection master; - +--echo +--echo ** Do updates master ** +--echo update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +--echo +--echo ** Delete from Master ** +--echo + delete from t1; delete from t2; delete from t3; delete from t4; delete from t31; +--echo +--echo ** Check slave status ** +--echo #connection slave; sync_slave_with_master; select * from t31; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # --query_vertical show slave status; #### Clean Up #### @@ -496,11 +449,600 @@ connection master; --disable_query_log DROP TABLE t1,t2,t3,t4,t31; +###################################################### #connection slave; sync_slave_with_master; --enable_query_log --enable_warnings +--echo +--echo **************************************** +--echo * columns in master at middle of table * +--echo * Expect: Proper error message * +--echo **************************************** +--echo +--echo ** Stop and Reset Slave ** +--echo +STOP SLAVE; +RESET SLAVE; +--echo +--echo ** create table slave side ** +eval CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) + ) ENGINE=$engine_type; -# END of the tests +--echo +--echo ** Connect to master and create table ** +--echo +--connection master +eval CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', + c CHAR(5), e INT DEFAULT '1')ENGINE=$engine_type; +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT), + (2,@b1,DEFAULT,'JOE',DEFAULT), + (3,@b1,DEFAULT,'QA',DEFAULT); + +--echo +--echo ******************************************** +--echo *** Expect slave to fail with Error 1523 *** +--echo ******************************************** +--echo +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo +--echo *** Drop t10 *** +connection master; +DROP TABLE t10; +sync_slave_with_master; + +############################################ +############## Continued ################### +############################################ +--echo +--echo ********************************************* +--echo * More columns in master at middle of table * +--echo * Expect: Proper error message * +--echo ********************************************* +--echo +--echo *** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; + +eval CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t11 on Master *** +connection master; +eval CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, + c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT), + (2,@b1,'Testing is cool','JOE',DEFAULT), + (3,@b1,DEFAULT,'QA',DEFAULT); + +--echo +--echo ******************************************** +--echo *** Expect slave to fail with Error 1523 *** +--echo ******************************************** +--echo +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo +--echo *** Drop t11 *** +connection master; +DROP TABLE t11; +sync_slave_with_master; + +############################################ +############## Continued ################### +############################################ +--echo +--echo ********************************************* +--echo * More columns in master at middle of table * +--echo * Expect: This one should pass blob-text * +--echo ********************************************* +--echo +--echo *** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB + ) ENGINE=$engine_type; + +--echo +--echo *** Create t12 on Master *** +connection master; +eval CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, + c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), + (2,@b1,'JOE',DEFAULT,DEFAULT), + (3,@b1,'QA',DEFAULT,DEFAULT); +--echo +SELECT a,hex(b),f,c,e FROM t12 ORDER BY a; + +--echo +--echo *** Select on Slave *** +sync_slave_with_master; +SELECT a,hex(b),c FROM t12 ORDER BY a; + +--echo +--echo *** Drop t12 *** +connection master; +DROP TABLE t12; +sync_slave_with_master; + +############################################ +############## Continued ################### +############################################ +--echo +--echo **************************************************** +--echo * - Alter Master adding columns at middle of table * +--echo * Expect: columns added * +--echo **************************************************** +--echo +--echo +--echo *** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t14 on Master *** +connection master; +eval CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; +--echo +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle',DEFAULT,DEFAULT), + (2,2.00,'This Test Should work',@b1,'JOE',DEFAULT,DEFAULT), + (3,3.00,'If is does not, I will open a bug',@b1,'QA',DEFAULT,DEFAULT); +--echo +--replace_column 7 CURRENT_TIMESTAMP +SELECT c1,c2,c3,hex(c4),c5,c6,c7 FROM t14 ORDER BY c1; + +--echo +--echo *** Select on Slave **** +sync_slave_with_master; +SELECT c1,c2,c3,hex(c4),c5 FROM t14 ORDER BY c1; + +#################################################### +--echo +--echo **************************************************** +--echo * - Alter Master Dropping columns from the middle. * +--echo * Expect: columns dropped * +--echo **************************************************** +--echo +--echo *** connect to master and drop columns *** +connection master; +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c7; +--echo +--echo *** Select from Master *** +SELECT c1,c3,hex(c4),c5,c6 FROM t14 ORDER BY c1; +--echo + +--echo ************ +--echo * Bug30415 * +--echo ************ +# Uncomment below once fixed + +#--echo *** Select from Slave *** +#sync_slave_with_master; +#SELECT c1,c2,c3,hex(c4),c5 FROM t14 ORDER BY c1; + +# Bug30415 +# Remove below once fixed +#*************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # +--query_vertical SHOW SLAVE STATUS +#*************************** + +STOP SLAVE; +RESET SLAVE; + +--echo +--echo *** Drop t14 *** +DROP TABLE t14; + +connection master; +DROP TABLE t14; +RESET MASTER; + +connection slave; +START SLAVE; + +################################################# +--echo +--echo ************************************************* +--echo * - Alter Master adding columns at end of table * +--echo * Expect: Error 1054 * +--echo ************************************************* +--echo +--echo *** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t15 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t15 on Master *** +connection master; +eval CREATE TABLE t15 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT,3.00), + (2,@b1,'JOE',DEFAULT,DEFAULT,3.00), + (3,@b1,'QA',DEFAULT,DEFAULT,3.00); +--replace_column 5 CURRENT_TIMESTAMP +SELECT c1,hex(c4),c5,c6,c7,c2 FROM t15 ORDER BY c1; + +--echo +--echo ******************************************** +--echo *** Expect slave to fail with Error 1054 *** +--echo ******************************************** +--echo +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # +--query_vertical SHOW SLAVE STATUS +STOP SLAVE; +RESET SLAVE; + +--echo +--echo *** Drop t15 *** +DROP TABLE t15; + +connection master; +DROP TABLE t15; +RESET MASTER; + +connection slave; +START SLAVE; + +#################################################### +--echo +--echo ************************************************ +--echo * - Create index on Master column not on slave * +--echo * Expect:Warning * +--echo ************************************************ +--echo +--echo *** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t16 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t16 on Master *** +connection master; +eval CREATE TABLE t16 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Create Index and Data Insert *** +connection master; +CREATE INDEX part_of_c6 ON t16 (c6); +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), + (2,@b1,'JOE',2,DEFAULT), + (3,@b1,'QA',3,DEFAULT); +--replace_column 5 CURRENT_TIMESTAMP +SELECT c1,hex(c4),c5,c6,c7 FROM t16 ORDER BY c1; + +# Uncomment the below when bug 30434 is patched + +#--echo *** Select on Slave **** +#sync_slave_with_master; +#SELECT c1,hex(c4),c5 FROM t16 ORDER BY c1; +# +#--echo *** Drop t16 *** +#connection master; +#DROP TABLE t16; +#sync_slave_with_master; + +# Remove the below when bug 30434 is patched +#******************************************* +--echo +--echo ***************** +--echo *** BUG 30434 *** +--echo ***************** +--echo +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 4 # 7 # 8 # 9 # 22 # 23 # 33 # 35 # 36 # +--query_vertical SHOW SLAVE STATUS +STOP SLAVE; +RESET SLAVE; + +--echo +--echo *** Drop t16 *** +DROP TABLE t16; + +connection master; +DROP TABLE t16; +RESET MASTER; + +connection slave; +START SLAVE; +#******************************************* + +#################################################### +--echo +--echo ***************************************************** +--echo * - Delete rows using column on Master not on slave * +--echo * Expect: Rows Deleted * +--echo ***************************************************** +--echo +--echo *** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t17 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t17 on Master *** +connection master; +eval CREATE TABLE t17 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t17 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), + (2,@b1,'JOE',2,DEFAULT), + (3,@b1,'QA',3,DEFAULT); +--replace_column 5 CURRENT_TIMESTAMP +SELECT c1,hex(c4),c5,c6,c7 FROM t17 ORDER BY c1; + +--echo +--echo ** Select * from Slave ** +sync_slave_with_master; +SELECT c1,hex(c4),c5 FROM t17 ORDER BY c1; + +--echo +--echo ** Delete from master ** +connection master; +DELETE FROM t17 WHERE c6 = 3; +--replace_column 5 CURRENT_TIMESTAMP +SELECT c1,hex(c4),c5,c6,c7 FROM t17 ORDER BY c1; + +--echo +--echo ** Check slave ** +sync_slave_with_master; +SELECT c1,hex(c4),c5 FROM t17 ORDER BY c1; + + +connection master; +DROP TABLE t17; +sync_slave_with_master; +--echo + +#################################################### +--echo +--echo ***************************************************** +--echo * - Update row using column on Master not on slave * +--echo * Expect: Rows updated * +--echo ***************************************************** +--echo +--echo ** Bug30674 ** +--echo +--echo *** Create t18 on slave *** +--echo + +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t18 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t18 on Master *** +connection master; +eval CREATE TABLE t18 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); + +INSERT INTO t18 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), + (2,@b1,'JOE',2,DEFAULT), + (3,@b1,'QA',3,DEFAULT); +--replace_column 5 CURRENT_TIMESTAMP +SELECT c1,hex(c4),c5,c6,c7 FROM t18 ORDER BY c1; + +--echo +--echo ** Select * from Slave ** +sync_slave_with_master; +SELECT c1,hex(c4),c5 FROM t18 ORDER BY c1; + +--echo +--echo ** update from master ** +connection master; +####################################### +# This test should be uncommented +# once bug30674 is patched +####################################### + +#*************************** +#UPDATE t18 SET c5 = 'TEST' WHERE c6 = 3; +#*************************** + +--replace_column 5 CURRENT_TIMESTAMP +SELECT c1,hex(c4),c5,c6,c7 FROM t18 ORDER BY c1; + +--echo +--echo ** Check slave ** +sync_slave_with_master; +SELECT c1,hex(c4),c5 FROM t18 ORDER BY c1; + +connection master; +DROP TABLE t18; +sync_slave_with_master; +--echo + +#################################################### +--echo +--echo ***************************************************** +--echo * - Insert UUID column on Master not on slave * +--echo * Expect: Rows inserted * +--echo ***************************************************** +--echo +--echo *** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t5 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; + +--echo +--echo *** Create t5 on Master *** +connection master; +eval CREATE TABLE t5 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 LONG, + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +RESET MASTER; + +--echo +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +INSERT INTO t5 () VALUES(1,@b1,'Kyle',UUID(),DEFAULT), + (2,@b1,'JOE',UUID(),DEFAULT), + (3,@b1,'QA',UUID(),DEFAULT); +--replace_column 4 UUID 5 TIME +SELECT c1,hex(c4),c5,c6,c7 FROM t5 ORDER BY c1; + +--echo +--echo ** Select * from Slave ** +sync_slave_with_master; +SELECT c1,hex(c4),c5 FROM t5 ORDER BY c1; + +connection master; +DROP TABLE t5; +sync_slave_with_master; +--echo + +# END of 5.1 tests case diff --git a/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result b/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result index 189066179255c33b7d56e0fdfd8a3893dda3535c..28985eb8cbab465b8fb3ac3e824ae37a3f89d32d 100644 GIT binary patch literal 98074 zcmeHwZFAbl()MTRS4{1GAa=1iNaD>&x$1FjcGu7GOAf|oH&u5Pg|QSY9F1eTUpXC*CnxVJ&sJ?&uxZwZ$ut(j$^GNQcqS%eF~5t& zIS)A5;=X^}?Hu(wqIdM}tb@@iUL}Dzz35d%5~}|r`d_^7o}M3dKZt*KKHy$m9RGUM zeHGUBs{X(BG1%wRf!P0-pEShJXO~Akankwu==!WDD&gx|tx^?!(v*+X_tJa4&Q-5c z^^+EtU>-qwKWU3z=l33d9Eh{ai(lTIUB1IfP!sP?d#{=i%1wem{P(E)?(_ondeyA& z?R74GIlbr{>Q0~$FOKdpyF`ztB^uz0<|=m@PgmVEsQ3JCI(htfCn(!}-yiUEayp|~ zICavfsvk}Lqosee^^XJnBdD2Q0axX8Jc}_&ZwK>%7>#v5pi9Q$@iVTfdd2rKe$FNj zvB0#Qp)UL43KxfS^yK4s&b1F~d{ZRT$%D=bDX%(bo#UQ3zP!HZz1rUsKX)(B(W`HL zeZ{ZWOsXWPCSf&+s!6?yS4*1Jq*YDY)#RY+-^G7mB%pickHBOlF1sh4u6XxBB#}5f zJwNS$fLh8hTz6oH9Y#; zQoWiU{cWXQZIAx8RIdY%{o#fw7<#hX+5w7N54s)`Yi*GXrKPB$IO`QFdxcV95=sU#Cmy`+LvKxF! zS@2EG=u66gZ++LE+tr?ug>SvC;V;lvuOS$D z)5&D6FT9^j=XmING9E+j>38G#^qXgrpJ8G1^XNYISyEZ6u+GKx`K!tRYqH7>eGMyn0(BZZ-p>VHrsdd4 z=NPNKvsXc@dSKlRFvWN|N6WMG&dKTZxmuSU2;|!7o*utyR>W_ z7S`1QPOaXskQ5h}J>+tBme%@zYUTc@(m^P$I=#XdyQ%E?3(Ldb22+~Evp2r_1$>$QmD|{s|(thl08~ zmjwn5b*hs$1r%CmlzU5Dfrg!_bVi>P90*kv=uqg_RqyEhJst=HoL+oT^$$ZnlTU{c zpQtjzy7e3?()AQ&ry3myRDJE}WEA30V*EV!Ds#RN@{6I)bjoVR85NQ@n!iq?9 z6qweFLNivGOj8yS(Lk9)9(4!3N20o=H3KE)dPfa2s>4QWPsoqIhbk?o)U-~G*%@mU zrR+zVP)Dh@582RBqlKHQ(WF9+i2YkP=cq7eqnESQaYiwh&8J?NPiaM;^Ty~ee?!$_ zRb>!_rq+@9RX4wkYBDgoNem11IzijyV$_qNQBQ_}P8XUoLQ_U)$_N`em(Y|EnleJu z(xE8><6PAsGG#=e&LuKsM5c_W!TS_K=}J$eu5>;zI?jFn^x~@1?LmWztMgFMW=9en zBL5`h?})$ahm~YBoy{TQById|zY!1d?db7A%trq&W;G(+3Tn6))ZX~4Z~Za=o4*@O zD{r%bRoY$>s<>c2t@ z$)hsA8%=LfT4YL#q-<3~f}+wWN!ilgY9VM7acE6BDs-DWD$}XD=Q7Qh>A8BDtXdcY ztrg<~Ys>*u(4@T2jt)%nRf8~7tNbT0Y!VDxGq93_!|*jO%27Itzd$oS8$3Kt2O}D~ zVf!!)k$@&`5;YDh_=T$F2(?kO>79;;lj)Q;5ioJ$kJuC8A^k?6JUe4o)D3Euz+n0h#980tZaEg|fvXt6+GXGn1r{x2%{@K%x$A+k>iQOSP}lY+|A0!Pksm~^e5 za0G3Y))qB3dxj8o>@qTl=`C*2I-!bn>z0mRh_ZGAt8xn zkn#^X(v$tzvXX2O%YFv$pV)jir2+|~$gytsGc_^XHy-B&C_PSY= zIG2+qeA761(`dgwI5<#=9f{9*g6MKB!XJO+E7$^|lUR;Koo6a2x`{9&cwpMXqno0l zUqVZi?rnNerrKQhE5K^F&Vr>wo$1g78af38otOp^|9PH=8~3uc;(ik=P`aRZyucDVgMK zDynLil_w%=3dYk$JdDOreahYg>2+jhnU#EV*@|L5dWd04K)qD)<(<7;LS07t(6A`- zlh|!ox1L;1%OQ?clF8$Aey19LN6cln(YG1AayVhdZWga*ym9JfBz8y4(+1rUb8FnJ zL(F%yoD|p3M#}|MIj^J;j8!<6oym@FS|eId^c~&QErI`cLa=U(XB2{Wbn~UqP3RLV zv(X zvOD`an%^l;8rakbx_dH#R-UZpXUd$MtZ!hiMh0urnjT7HvYv-^|73a#h4>9D%p=E? zeP;|v#-h2#fKlMdL*EU(h!1@Zt9(B6dEJZn(B};=;zOS|y@(He-trMd`OxPLug-@)Z+dk;^m)sx^P$h%UY!qp ze&E&lQ0I-BCl7U=8H1rU2H~z@xl{Nsvd159X6B7Y-gC(g>8MHJwz zcX|u$^}#O{d9vBAE7lg|AwV1$%Q=OF{P!W%q*SjzOQ^|=6X}DaR~1a z`y;->LJ&4w(P8uLLhA4^Oz*=SAe&oo$Tn#v3%p=9NyJHLN3NxR(RLguhR5+&xlL9{ z3jvAA*`upr^c=IJ7BmP^MGObdm8^l-eGuJ4;}Am-Tm+z^SSAKid*`zvRc?H%^*x43t*wWMld; zy1j)vF^o~A?eIPlcK-Mbq2`Tv4|ih-E%9^;+f?i?%?7Ym)gL4*`Qh1qMQ+Swztv@z zWVUkW`F_>Ad@rufj{e(u>vub3T&7NtzZgzqa$1yClQv+p(QQl*X1q#k;?-c$i}Xg? z3W}jLlWXi1*_$ah00Dy^-8QJJQ#^@vMTN4_I;QY!b&M^u6=F7#5PUJz6qTK);$;h=Oz&F9=-|WAIvz? ztMHP98^J3isp21232N^SriqsjUeUID*nm8{?p#3$O{tXCceV2GZ})LUpOTU~bnpM) z%Z_t9a&Q0VD7`CRvgDY;OChBisfvl9?~=jjUa+JN(|HWqpn(-HwE+H={=j?nSGZks zy9%^%@A~SW?rj36h19p?#W;W|yGVFXI5G#u22-1pE_j-bcL3LQzclTk zgy6vEc2I@w@N4GVPa}k2c&LszR!kUX2$)cE7V&EqvhEC5OUru0gHz^A(;C)F-xo_plV(_QMaMZoNRi}mjLqr--fSlvPA2zAx#Q9t zumrB0-?dNZj!TCPSSl+%9i)6ZXzbYZcgd!g^yfx=I>_PEQY}Rcxa4PTKHa0RPw;6L zP-Z>e-y#IfY{u>)Kh5EqPmFpqJ`GLpT6`K_!Atox`K=W!pe_E)r5E#OQ^?<%KjSU4 z{Mlj0i%VvQ3EQ{jlDT3nmCap9mMR?6fTJkg>{XNMuo~-F6k!^SVgPqG4v%!R=Oy0I zi=p~%hEcHWpGQ^ph@2uYLby6P#0Z@_TAlhoM>?^O38&*vnE+b2w(xSp6)!d{`%)#} z2EjR&wGZ9%{&OUyWVHeab0`Z|4D^am{(!*zq@s(d`82q_B{zQ^Q>;LLCyWNqB)q-F zLbmYpL~^5E#FsB_mIv6|S&QtzL3_v%;oJyt!@5@9HCAZvEaJm;C?-B>QA~Yuim3X- zW>z_eYpv9e*Nq@>eBJGKE_!|A=Ij5ts=T8!=mX8#vM!EJP7sUj?E3sd3`67n+pdOt z;^=2eIs{)^_7MDz5d}{trlFeZ1=rFRqKz%m7a*ELwW5_rh~{B}R&+R`AJi`u)(N`H z6+_}!rAVrv#VUeHeJd&>Kcfc#+;4HoRfe z8@6cQ5%uzxw##bT!}K}u7RMlh-%<9tEw(yaqT_kFVzZrcUD=kaO91W9E5HY3$zueD z6XbM2`KI4uqth<=W(`bnpSISR+hQ-o!#>*##zaY!+eEKPFa;OU8$_DDkpKDTVg|D= zd!f;QtqF?Hl-Zb}0u2{LvIPpq8aP827b&1~za{yz9(nHWw=?!KGk?k0%glL*>4837+&DCkf^*C|Dgmp z%?c&%l&tJDHrvtIn0`$+R$f5gF4^>lU8USispl-EU`)j0L~pL(+}$W&*qQ-%c)|yS zY~_+GhGl?bFOf1twd-7KpzcKu5A=FF6BO6X@uiAQ zFafbbo+{RQJ^nPFd>tzh2@x<`6^h4SnFo!^CQ?!yC6C}cmI|V zpAb+3^u`sJ5c@n zRFueVMs#YfDLOT`C^~T+ibbcisP9E|QaygkJx(^hS^HCEqH}t2()pbLH|G6G(ubb? z@&eYS^uA5loNg#PA)8XNQ&wyWU3D=FU8Dt$%=Kjgl9rC}E*i8%DSork(I%o%S*a+@ zQ3aP1h@zY)eVRYc$H$p?cl`@uM%5AI6K8bA{p>^+!vAqRG+wIc(sHb4mFR-d=Be1y ztni)*>3|q*jD#3A#($a+Q)2$_gqCdyExK11gqG*)*)rk^Vl9A>xZ(+%=^Swd=i3xl zm~gSoav~kv2ne*b zA`I7|ScFN7`d&nsti-aRFoFhnMq#A&_Y_9-{+x2E*M3mB>MJdmEo+Lh5?M*i+ zX$HH*6m8|RWN)^0)x}d7&ax(Wo(^@`QhPJDq#VJouTM{eUfQR6*;VVB5km?W8Fy{K zj#8`LHTSdAJ!S_vI>)GYrPIRl-R!iWrJRRiG$ZQy%dr*CU&J`R{e?TuG+JKm86Bwc z?3a7Zi+8PE=FH6!qU-9t<(ye4y%VS~kBqN#q;!u6OPXMjl)`x5x=%#(%8A=mW{I(^ z?nSjOsB6v&g4_#iT0qz})UCh@xd-;7gpEHWOw9Np9?zvAs%(zBw%3&u5oMz0{GKETRea0r)BmFb9-I zgAUmP1{#7?0zw5bMbgU*NM~@<4$?69i1|d2cfD852pcvDT+iVot|0K5^}R(O3twY~ z$*2Kn06BRVAj5zf1DJ%#Bu@=*~UQ+AGxKN~eq*a-wKtn=Jo|aAD z`ud7rubEUyP))*W5>=CWHEC3nW;JP5lXf*ZsQR=~h1T9<;~zAM$to52lSrJMo}cza zh+qa*G%hbe9JQvGw7jJ4B?s*0Kv}6D!5#=5{mFoI`0;7*X@>tkLYF$5Pwvqi#=;!i zf`i-9EcSquiYSSgiZ}O@8{nZgfQTMO^+uCS=JB@`6lfc2dEWkWr0oLLGL zy>V6fZQWGf>}~=Z6rCd~Bud zGEn22*RJkKwDRrLuIWj%^DXskXhWrM{;mfUTGd2X-8er7s(s_!RbC7`Py<$ zx36!n=3WkSvY3l+GY3BT!Iq z*rcSCxH#&5coo+6*p_+xh%f?X5Ah9@g5Mgny;9v2}LV3lR(I*88 zxYbV_R92h@2C_5X4Sq6#(*D{WAFVfyqBG1q7zfLEGeF)RQ3)+GQ>w zFa*^vQ$}dY2u&GbL+28jGD1^EXj(cnWkjZo$dnOk2%;IXRSgM>N@En~ zlBMOMLzDpqw#A_*VfmyFhHj@uWjZyep;s51(S#}IQ8TZX$*P5%S}Vo}_SObaL6h=6 zJ32G~NN|Wjo`n1z@pl~=kERH4kf~Mv6BsrLo{(#PBGm_n;cHyPmIU5)7Jq?ed^UJ^ zoDN19A>b#6VTc4FJx9PF_=SRUFg~JY(>omxCsRbPo@47_9)Cmx|1X34M~cAUW=vaN z+8%(~*ODBZiHBF<3}!+>kkT;JgA}U~EJCzc02}9j*$!Mb44nOY2d^gq-t9KAkn$|C z$ZgSONO_L*WIwj-AzQ?%QYXu5Z%tCBM{-Q3 z`do8Yy~B=fF3P|b-Gn}|!g#AI=_a9~%Es1v4cVqxar)?@Z)82f?BB6ON#* z(%O3$Zu%e6v_HuDn4JwbAqGI&`HJ+_>U`+)$gA_A&+A^D4}IS7>U`+)rdQ`fpSQd^ANsuQ0ZAQ)K0om4 ze5mtA&69^Z&x}FfBTa9yDRToahYYwm!PEyprpG=~-gx9am+X*^%4L_S1aMNyR3h^f zc7jShMsK0LKHvj~@#D$5)9<<`^^JT3{v))8=HE?^TfyLcL7kL(bkg0iW@!!W%Mvx4mX;E;%OngpGbO%ibu+L3GNU$h-Z%7k(J zRT9BUngd8o&K_M2LkF-Yj}Hh4nnV>b9E`~c_a+u(Oe9}ldImWzKY0IJ>+&4cbI$Qb z&N&Kq&JilxIggM5QO{$J=su&UWpK)omcEOWlTzE{a%Ty=vjiT`NB8|RxS{?$0#2BJ zZO-3MW?s#gUT^)YtF!*m{r%)?eCr_+o^|#3NImIZdq0@pc}}_*u$<0?(Pzwa=MsXO zdHz)lxRBdf|6P2C@S}a1t@oq-=$~Z?T-t4uAWdlQ&&V7(*Ib80;v;Argc-?pteh+`-wPwYAb&Ab5Wozutw_b_ zHYO1(<5dc*_@x+v>>1i9g82m+cOKk}Q#>((qC(j}|3=}4C5yJvy!~J>fWJ4;U$ku| z0F3gl&4h_3C3VQ4TIRluk43koyS}+?!Cql)f*vpbp~S0$pf_MwiG-B6^ao>d7XtUJRdVgJ9BH){tHOs66S zovnowvA7mRg=KiMw5&HgICWg2X$@n?*o_boR2E}BxG`Y4ZQ!CfO{JNANHa&>p13+Y z`fo>eyS6H3Gh-DIiTXG{MoxMa0_AWpe??)z@ej<=37>P!K34{G^JfD681hE`!>54=0l%HU)OUBW)S^!VXffoBY87)M9 z#MS%3xAZalf}LP>_AD*;PcQr3$MG0`eja&$%8NuU_0<;|@7s`ej`Z#QnPhzlZu_Uv z=l(GTH^Bm~=6C*xhiaXc+hJFq2g4X$DA$%45VtH*U?DklZ2|gMv*{)Mxe=cZ za`?1VOMy0*{jANWdv~DG7)S!jtjGIXAXCg{9ChZWIXrBMQE$elq3KFY$(6oD(B18!%Hwx+D1rOfX!Hu1sO?RO-c;cMF*#2A)dn zW5((DQy96-*rb3dV@;Wt8?Jb^aPFD~t(6Wc%cij2CrxVjq zO&1}Rn?U}-=_|duVrhalwn!hr%~vZrQVA(#^g5-(!6cx5sj$j$8GWSK64eT`O?p~f zNxu1YGX10;w)KpLJhHx#(9WxsmFUwdpXF3`7yy{EI?SMPS1~$N@cep8a1|WWF!Y8Q zOm1)3qJ2lyYdhH7IS@)4!^C61^!U2lMfk}+1v$mC_WV7CDxylSY|GW00<=G`0HTt4 zi~#Fu0~MO>fbvbh#YU%Ha%zg)A-VeXF76#KS(PC^Xuv1ra?Zn|V!wDHw*{ zAkyrGT)RIPGZ;Ly#z%4&5SuZ%l)^t-F1vXXiG9g+>BxJ5!m$R<(8Wax=-emx1!ST} zp1b?)jJ?dvUo!SGa~@-FDGgjbW@Mmq47~Nn9Hh8tTeFv2%=9Wo#kj1=@Q zRH+{zWGk0kG4>K+e>&&gMo>G8A<9`p0KT-W%Ky0Zv0SZuBun>U*2FCUZQkBOYdLa( zRn*^Op;Zb1+g>ECwR9>(MaZaysw9V7J34u*ACtyHNXX4*8BPM0J6gtBhBqMLTD)Oc zR{xSG{qy3Yq++J{`ErVUOry;AS!@bjbur%{EpTM6FB6cobcA>5o^+@@VOQ2X;9%jo9vp zF3*S7z7txuBDCmUO$}+KR-*EJJzGXxL97K35?4HdGo2%@;C!3n3KK4tSx%&b8{=KA z385^rSO%e-(TuxfbIDmoglVlQ!T=k7Ya$HSp;&}Ti~3$fn5@LIp)i65ct&Al8TkBn zER5*=IYfRXZ+mSfWbF+Tq#R_f>ad~ZvSm$CR#{b2Csp29NGNi{uc3A|iS%KQyVpr; z{@bseZbv{&J{0h&O?SZ4w{!uOm%Z!rcDqkYFw5N+FPrx|>8lqD)7$PehriH9FzUL- zhq=i0XT)xf2{loy$wZ{z_cA7uBXO6hF1?oAqHVTFaL@3Rc7~@Edu3+4Er1QbHKxLq zC}t{YQU6e;f(Cd-rm_sH{CTNMIhB8uW6(sC;>wBCQi`c8Yl>~tr&2G+vs=ZC$S{>W zI_t8HWpDF6ckB}w&ax(Wo(^@`QhPJDq`b}ukX-1v`>B;Ig#gJ{$ciqofe|fW2K9N7 zan}ayDAmfYxu3no?d;{d*=a#bIS&C00fzeJ*b3(_VjM@p!X0NCEwA>B4%B$|OJBjo zyVfpq=4J`eb@kqI&McJP2~?OzCaO77x(5ZXmnK*wr9ip2?ytuUmeswe)&+IVSwWzN zjtYdZYp7e{dw7okC=xvW@L}{vd@GF@%Ls#cY4GxEe-@t=(k~WPGTPd^DD%ZaO>y8Nt2;9H9krN2myA_dF=@RlwT+Ai zMJh*HjcGY_NG__J3c=@DAL*DQV|PVb!k0rOPJ(I@R+Ffj)T_V;OPbZBRZZH}W z4NszEZ>M%GPoivZX&N{X-5bAa2I713{1AGPkFB&_24Z~k+SNUYQofzqxe(`@*RJJB zl=SV??tnt78i@6cYv(|;Z=BmoR;N@jPvms_<++!`oX8JLF&E!v4t`49eVaJ@DRK2P z#L<_OO%XRgL!5j`S@2Dr>`TgkZxyW7ncRM6a{6*+;hUe$Ob%a;Y<$bR?%?$0$ilb0 z>kf`g$X)83JE*T^A3%to1Gog@$u8<<)~16ZuxO92xPLO~pS<&|3#T8)kjpa{k&30% zoP-P4e;eK3QnvXwRQBp7+c8R`MuinGEjo6w$+i-kOtoohPvK|RV7vk$zsb3dKqqFy z7-*iO2^lpkF2WEVVpBxylgn#zfiWvBYZcbHxIQn0sb`Sqmhlt^g71L^0UaQm5qt~e z^6b2Ga(aEP(5eqsCq5hQ*mdslmHS7#ePPw}`2 zZDc3h%OW`8(t(NwjJy_L>jZ(xrK5;RGh)oMevQ(HW~}n?rb`wYoy6#Nvj9LH64foO z8HR9!RA~qmuSa#*XzeM3`hsvyN~gx`j6zkZ*r^LjHR5az8hyB_8cpK0qc;(W#K}1- z%-QJWY;~N*eP76@UYJj5MW0)*K=>Sv0QxnR^;1=c8m&G6%(l!b0MxbmWpL{QlYd|e zz_8Hi+9nsHo(zHGE^`S19H@SoGD1^EXvzp1I+xIt5t=eW)6$_SBQj+~ri>`mxkRRn z$dnP$9>%`Wm9pg>BdHtH4;|}L;;V;c@YUM@LujwSS7&|emjSTH?*`K>UV3P-#?e6X zNMX_;TLC=`a|?=4mXB&kQB)u$p}UK~@l_w7aA8z$G+W4ufg~v+wvY#)lSb29%wGbi zl%)|W9i*`u5)_rjz;z`{TbsGq;?R>Ye9{L)w^O4sol2PWIn8Kdp~~@5FOyXZIki@d z5A3N8rr!i9@3W&r1AhdE801OF-w}V;kul+>lzRfhCczVO%}=EI;4plRi`bIDyUyY- z*eI9{9v-KI5k?63$zd2GK}gRL;0J!8pd6t#YBs&o@o+Ll)ap659_H~!MDAyBq&L95 zb24_(l7gBgIV{I)reUZD=?=2lbyVBI>RIgpG(v?g*b-Ne&d(Onj&%Yhw88lQUseYA zxr5cS+GHJAJt5&tZ3)%N5e+QS;$=rINUkR74tsPzD?69NY<_OAz2&qV;#fuEVSx?p zh`CF9cEsFjj~y}BjZu*h?vTrrdcY7#odS-r5dL>K(vViQ8e^f2XnDgew4mNFNhO-G zN@Zz0XbHy4CKeX(i<0E2JG3yt7{&-*IL0=X?7a18xrHN*RX8MmUa$s-^j zJ}Pg$Gm-Ngv~#VWa0G3Ywk>xtc<;hZ|3jMg2U#Dpv*9L0eI&;s@~23j-1t~Xhm`uW zqmkTfsu^~Q0yQ3YvZWyV1;GXkTHv$gz3)@DB%S;g#Xl*9TKo{V^p=<3^esP-Pej^=kd1UPn&Xa@;k-4ZBV2P!A)8`!In z!J6aMIk)k{;Y)7=O52v|J7Yjk8hf&-U{^P$h{UY!qp-tg*t z=<}vm=R=>jygDEHyzK!&9fv+Y@alZ1^G3~+hdR%ULEs`yZ?P$J^9{Q_?ieI^`T&UZ z*hk7UPUSt9?2wMiWtXW0@KMTCBJ&i4(o&DnTWGHj_`YHAc(U&FyY5MSBj14k2(6*{ zchh6JkS9E*wDe=1rE}f)m22}{Z^JbX8}3JZ1ul0C&TxnjLD|&dVVK^BSwZ%Ga7e^C zO@hwJCW$x+?Z~zCFWQbHWx_cADv4kv%>g7PXOFIip>r(JX7OZ23xZ09^e21Gq=|LB>r^j)N!l-eejJ4@i5CGdDY zx=&#(EjUC%wXA8l%&V)j{?YyYQAV1DO0=_qcib7Axu z^W3?Fpk|(b6$2*ZcGiCv-y!U%!gWMIS1bQN%MuvIy`?@r!0dVMlSjR#ZSXnG!|&4Y zD(?ZS0)`P!r<198h-b3_1TOvA_e+(FL_FKC=9ACtR@jZnf7ryiD30`k{Kaq@Q$!nS z);y!YhGI6ljY-7Hc$ESpekpb!n>;p(;C+F@od@&c6i+WwR4Du9-v~DB6N$38vuvYT zGhncPzc;X7v~4Eviw@-OhB!?l!khbcWO%wQ-So|E3+@VQlhPxKMjj+4Bz>Bgex*)TaYnQ> zgRp|Vqi#=JogMwRBfDMKl+BD)cm_PUX|!>?WrihJbU+SZJ1380Y*Z6sTO}ugj+JmY zA^1xfQ%5o79hdf%Fxc~+aFx>gI|csbBwe=eLm zKlUS%-4DJkBv_q2k1s-w=su3e@bmM?`%_;04&r?OgxS5 zfCbBQC3gj>+!ZwZtBv?{ki(~?TBXYiQ8tYgTVH!$l0CzSHk94!=CEn1Bb7I3SV9PV+D@{Kz z!EiN1EQPyMsTX72Eo6?^cPg=zq~wknMy@4I$yih7<%TO>Y*_ZCO1@1_K)jsSkW%sq zlx0AZ33Dh5fto*ou9&1CFe||z^YnL%0Lg>f+oA}XYmggNL0`VOLf-)v=9**&4%%Cb z;mma?CO&CVOnruRrLsf7cBLS!`UrUL#EJ`G81ZsqYGzSuk4{d6!I?Hu724HsPaOT+ z10oRNz%P3Ue#f2Pdpa=<)%>uX=~d{uhlBYmLMp;P=PCwAS$T?5!#FZ>uSjfayp=V({HiS zX_uUuB6moxetnGAtv2Si*bDKn&onpnRuOLmQ$$b6W?qwE3WlLKh;%Y??fzWMVDQiy zAIV)nY{ukLI-l5!3ic(}r6cbJ3db5aLl+k*pmU#K7m$e_dG7AFGxjnwf63U(%z2Ex zr8IE$m|9AT#0mB{y#@$STF_E*mf^%0Zzo39O zG^*4O5VDm^t{4cTus@YX37~csLzFE`z`eAr%Ky0Zv0SZuBun>U*2F6SZQkBOYdK

CCiwg68rPCCD1w{tr0Pm(_L z?3WkNnbP|NDx?LD%=Kjgl9rC}F5MGo+uwa)g*z0#3MJJW zHojvJJDNe($H#B+?)n#m8L1=4C(h`K``L*u-;4EZO(V5CqRaE4wC{wLtq3i;R~Lkq z=j+)r;tFCdfRMQ237qL1aRukw6jzvVvCMKJ9o!i2YE9^5nZ+{bxTeQs<3GNx5($4UdVz11MH779Px5iYs62(jFPMyKPlR0ITS=?S>Rwdqg1Y9cAW%a`1wz<0{~vncCPe@M delta 3124 zcmbRBkM+_jrU`2&A7XNvEWj)-q{-##=kDp}YOC&v%C;zclnrydOYx0||JbW%e{s9Uhj!r(VK=Z68A7pX{I=~pa0~9PsbAXP5dS!NT zraJi!amVfuO>6QT0t^=N-4cM^Ek;3Py9F3NIr*h|>8T3&X$l#M1qGRTsl~+<1XnC} zCt4>{+lfGzm!%d}Dx@WrC?w_NCsE+$EbMM}t*5!0brh1+4GfVX&>LLE8TsW3#W{(a z#VxOpns?3$V#~LI^`zulSf&BzXsqc2Bk-|!L`T7(!qCXr#MBJvB|cR9Cl}0=7E&+H%*hKmWWs=Kw3x+jxQ>E`v5o=+sh4DA7Nr19FoqbNpOXvXK#i^^ z)o5$3(t?!4l2lMRSDad+kY-}5pq`gnQKGI;o{?IVs*q-AYiP}tlA4nWRFqbfp9@ln zEL9AYN-j~*0!vQz-YheDPKyA0nxO$_nxWz3y)90P3}7G{$|+1?3$ zIgKYT;LzbgR)x1nwPgkC-h8fqH{)g|Ap^$EyC*d;Znl|X$Fx~d+=OZKpBb!Dz@pc7 zGWRyo&7Nk8jFWk`Kb_38BXIKvi{Cg>n^1%7XuW_|L51`5 Oh0%HeRJjeJdI10o&!Tz& diff --git a/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result b/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result index 5bc1a13b1078a054d99dfef348ad74e85295e302..966f97e05789010f7d19e3e0c2a11a35dbf9291f 100644 GIT binary patch literal 98074 zcmeHwZFAbl()MTRS4{1GAa=1iNaD>&x$1FjcGu7GOAf|oH&u5Pg|QSY9F1eTUpfDFdUbSOdA4fHf=#nNOs26IPVOHc#xpS)i}_tF z&UwJe7We(*Zs(}i5xt{#XB~`I@hS<#=|!(9l2H90(f{Io_w@Xz`$7D>^8xqj;`rC2 z?yIo2SM~q3kHJ2l4#fVy{G=g%KD#{XiIdLHN7rXPQ3+qyYL%++lcs#6zL(zXb*_4q zs-LvD1oH^e`$=2$I=}bu<3OBUUi|Xz?D8E>f|_`D+I!WEP;L?g;=f1Tcc&Mq*Q;iI zZ?ALl%jreuP)hoV_@pCqL zhy|wY40YKTSGYKwqbDE7bFO_@m2vQ@#XbJ@74aE__=#|j$VE1 z>nnb}W>O_VH3_RpR88ttyjs$%Car4Ht|kXn|1SOmBLUqje*`8gaoIiTbj7<5B8kM= z>G^3-gtfQm3@-`2B=VBFmo&Vj=_M^MX?w|mr?XN&f;~U<=x-JeC*xcE_%!%5!+#$q zAYk*!J(`2xipJ{a!E|stn#JCic=}Bw1JJem$&D8@8VxT9qk5z1M;`r+F$6cxs^QV! zmg?2?=x;0aYJ2pzrFtEB^tY9I1%W4zEmbWD(W!K7r*?HO;A300!;s@+JGELmYuDyQ4mjBqvga+s6FTzs23_$hJsZQ|^w#MRFbN8cfCzNAd}mfhe> z%7SldMqg3}eCxaR(7} ztCFE0!p|RPBr475A}?IPzv<%Jw?6k%|Map?$ztzEUrL?*UnjFUD17U64S#{YdJVzI zn@%Qkec}CNI>$rDlkpgGPrn<_r{6r2{0s}5pGWtxC)Z9tVXXrx6Q98E#)I3wDvOf6 zpUjX?H@+Wy>zl{y3w8qQxq|G?Yjq#TW2{@e5AjUB>(zhG`u5ds{P}(~#LM?jCjFCl z9x92y5tYQ8?1Og;bV)97>m zm?TOxe$DUv5f7KO+|}p7kUH{uJRjZTx$*62KAMcZi^(`v7fl0O=hVJ6-K|$wXZ@r5 z`^ne%7SGvNkB?-JX0E*-%Tjp{cl-@+$I|7j|1Q28jrEX7$060^ zzwvaGeCuDuQ%INnW6Bwo;wHktl}+}eeU4UB=hWFwo2m=cu4p*8ND7a_NC zB4)#QJeZCq`HQe{^F`Rn^2j&tFvrSd&$5=xbQn6R6YR@qRAoGA+kW zI>%V;oxKWL)dTBpfGNhyIa;2bcTP^P&(*r@Kp@vn_w@Kxvx*g-$uCTwz|sw?HC{Fb zwXm)haBB62g`~K+>>-!4v$WR#Q!DpJl@3C2)#(+!*iB{6UsxXgHki^Rp1twaFHojt z-Mf683#cZhgYm~$d>Pz7#-ssI%V<$a4k`i*5v4f||I`Ls zJ&s%MIBu^V#|MkUn3NK%grH$O#xi#Ncz>Txf^viSe^~7S<%86$G#Y!`8?o&rBX$ca zAG|&kFQlw#3ZW=MONbLFmT;{tfAvn!>FhvA4G~S*8f%zXkz?z4Le}^w^-mDFJrvZ{ zxhybfs8gN1DWK3gqug8K3N-9Yr8D}Z;6SLVK!-xVu6jr3@9{tw;Pm2ys(%>rnS45o z_(YWv*2Ra;QI{TRn4U*}(S@eePceB5TWMd?y|$sNQLWnI`Z- zqrkLY6q>QhWSX*whz80W@~AuLJrdO|tr;jW*E?#MQ5`l~dqRHvJydByrKWXi%+6S= zC}ls=ggQ#KeaME68ZF#ZjV2XpMC{+XIY)@-&Zjx&n6Y(DkEd`c_&oHs^)`5USZ zt15#aG_{V*ue$kVRFi?xO=4K6*9qDt7o(mGje0T+bh^-#5t=eWQ%2a(xrC;S(3BCH zmJUrB80V@6ktrhzbuN)9BQj+~4c?~^N>_R!b*1x((Q)qkrx#b9ZVwt%T%Cu4Han8w z5cww|e@FaXKddC9>1+-WCu!q%`;B;rZ%2<0VmA7JF{=^jR#3yep!UXRee0J2*!RsR)Q zNFJ5>-DrA?(jrq@BxS1_5)_q2Ny?V?RtrI!h(l}2QK8%1QJGHFJ(p?5OwZNJWYxkL zXss9@SYr;Lf+ppCc64BpuNs7zTID~1VUu9knt_!Z9EPuPQI67C`~{lv+2G-EIvCN= z4cmudhy*lglc;f6!7o%TN2raOP49F(oJ^;*iGYa{f5e^$59v1o<=Gj#qHa*LBnM~W z;T80pz|_M*!%z=WYzbjUMT-RjJ41@2@PARkhqsc92$6kCh)Vu*m=si=7C3UA!=!8d zgd=FHw6;j%rvD*L`-9Ba2rOBk)G_wmX&0SSoSk`5A_0$)MY0@o2Vp85VLQ}L69b~Bs4df&O-@p?oG-Cwb#v} z#JQX_;hV<6n@0Qf!NGw_>_~jh6GWG55&rliU%?g#oy2k^>O50H(M^OI!2{D49^Dib z{SsQDbZ^s(G6k2}xU!~|6w_`R$9*1Sx>BheY9*u$Z@^^&kPn%sEulIIWu7{>tmJBv z@)S_7X=GV*m&(H@ohN!4SpUn17ldC@OEA^I50ylVzS-=Ne@!LHio_QnX}NUtM1%dF&^%T^Tg(L)SV0_vrTFYoN-66!MAhlWLw zpTus%y7lC8S`Klnl1v__^E=h}J7O-ojlRv`mBR@ucC&aj`Zoa(;CrwqVMRYZVCLq6M}VPJfjf2qnj^x4CH`*k&1#Hjrs%Nb8tT8Q>wDM#%KU3!9WPJmBH8NO}*7Q&sll45T`zO;|D8z4IVIDcA z>^oyXG8WA>28;qv9{O(RMSSRUSmpDf&+A^qhdyt35g+=z=|z0#^OhI!q0if1#D_jV z@FG6cdA;VzL!Sp;oezB;dUZbZdF0jk(C2lp&WAp4cy&JXdDE-&q0d`hoezE9_Ue4- z^8>HWhdOW6Jb9?|%oq%GICO6Sj# zy3<=|uMd8y$dh%a8}J%oeIwt1{|K$2`8O<8NiO6Gk0~u3WoGGI_kHC%GuNAHjYD{c z*dOr~7J{(hiVmA^7gC3ZVR|3t0NLDvL$*mXS>Oe;Ng_@{J8~`ki?-uPF+7gH%5Abr zS_nu?&K_M2qvx0%wV*+WDq=VolO@qj%*I6W^`&Q!dm8^l-eGuJ4;}Am-Tm+z^SSAKid*`zvRc?H%^*x43t*wWMld; zy1j)vF^o~A?eIPlcK-Mbq2`Tv4|ih-E%9^;+f?i?%?7Ym)gL4*`Qh1qMQ+Swztv@z zWVUkW`F_>Ad@rufj{e(u>vub3T&7NtzZgzqa$1yClQv+p(QQl*X1q#k;?-c$i}Xg? z3W}jLlWXi1*_$ah00Dy^-8QJJQ#^@vMTN4_I;QY!b&M^u6=F7#5PUJz6qTK);$;h=Oz&F9=-|WAIvz? ztMHP98^J3isp21232N^SriqsjUeUID*nm8{?p#3$O{tXCceV2GZ})LUpOTU~bnpM) z%Z_t9a&Q0VD7`CRvgDY;OChBisfvl9?~=jjUa+JN(|HWqpn(-HwE+H={=j?nSGZks zy9%^%@A~SW?rj36h19p?#W;W|yGVFXI5G#u22-1pE_j-bcL3LQzclTk zgy6vEc2I@w@N4GVPa}k2c&LszR!kUX2$)cE7V&EqvhEC5OUru0gHz^A(;C)F-xo_plV(_QMaMZoNRi}mjLqr--fSlvPA2zAx#Q9t zumrB0-?dNZj!TCPSSl+%9i)6ZXzbYZcgd!g^yfx=I>_PEQY}Rcxa4PTKHa0RPw;6L zP-Z>e-y#IfY{u>)Kh5EqPmFpqJ`GLpT6`K_!Atox`K=W!pe_E)r5E#OQ^?<%KjSU4 z{Mlj0i%VvQ3EQ{jlDT3nmCap9mMR?6fTJkg>{XNMuo~-F6k!^SVgPqG4v%!R=Oy0I zi=p~%hEcHWpGQ^ph@2uYLby6P#0Z@_TAlhoM>?^O38&*vnE+b2w(xSp6)!d{`%)#} z2EjR&wGZ9%{&OUyWVHeab0`Z|4D^am{(!*zq@s(d`82q_B{zQ^Q>;LLCyWNqB)q-F zLbmYpL~^5E#FsB_mIv6|S&QtzL3_v%;oJyt!@5@9HCAZvEaJm;C?-B>QA~Yuim3X- zW>z_eYpv9e*Nq@>eBJGKE_!|A=Ij5ts=T8!=mX8#vM!EJP7sUj?E3sd3`67n+pdOt z;^=2eIs{)^_7MDz5d}{trlFeZ1=rFRqKz%m7a*ELwW5_rh~{B}R&+R`AJi`u)(N`H z6+_}!rAVrv#VUeHeJd&>Kcfc#+;4HoRfe z8@6cQ5%uzxw##bT!}K}u7RMlh-%<9tEw(yaqT_kFVzZrcUD=kaO91W9E5HY3$zueD z6XbM2`KI4uqth<=W(`bnpSISR+hQ-o!#>*##zaY!+eEKPFa;OU8$_DDkpKDTVg|D= zd!f;QtqF?Hl-Zb}0u2{LvIPpq8aP827b&1~za{yz9(nHWw=?!KGk?k0%glL*>4837+&DCkf^*C|Dgmp z%?c&%l&tJDHrvtIn0`$+R$f5gF4^>lU8USispl-EU`)j0L~pL(+}$W&*qQ-%c)|yS zY~_+GhGl?bFOf1twd-7KpzcKu5A=FF6BO6X@uiAQ zFafbbo+{RQJ^nPFd>tzh2@x<`6^h4SnFo!^CQ?!yC6C}cmI|V zpAb+3^u`sJ5c@n zRFueVMs#YfDLOT`C^~T+ibbcisP9E|QaygkJx(^hS^HCEqH}t2()pbLH|G6G(ubb? z@&eYS^uA5loNg#PA)8XNQ&wyWU3D=FU8Dt$%=Kjgl9rC}E*i8%DSork(I%o%S*a+@ zQ3aP1h@zY)eVRYc$H$p?cl`@uM%5AI6K8bA{p>^+!vAqRG+wIc(sHb4mFR-d=Be1y ztni)*>3|q*jD#3A#($a+Q)2$_gqCdyExK11gqG*)*)rk^Vl9A>xZ(+%=^Swd=i3xl zm~gSoav~kv2ne*b zA`I7|ScFN7`d&nsti-aRFoFhnMq#A&_Y_9-{+x2E*M3mB>MJdmEo+Lh5?M*i+ zX$HH*6m8|RWN)^0)x}d7&ax(Wo(^@`QhPJDq#VJouTM{eUfQR6*;VVB5km?W8Fy{K zj#8`LHTSdAJ!S_vI>)GYrPIRl-R!iWrJRRiG$ZQy%dr*CU&J`R{e?TuG+JKm86Bwc z?3a7Zi+8PE=FH6!qU-9t<(ye4y%VS~kBqN#q;!u6OPXMjl)`x5x=%#(%8A=mW{I(^ z?nSjOsB6v&g4_#iT0qz})UCh@xd-;7gpEHWOw9Np9?zvAs%(zBw%3&u5oMz0{GKETRea0r)BmFb9-I zgAUmP1{#7?0zw5bMbgU*NM~@<4$?69i1|d2cfD852pcvDT+iVot|0K5^}R(O3twY~ z$*2Kn06BRVAj5zf1DJ%#Bu@=*~UQ+AGxKN~eq*a-wKtn=Jo|aAD z`ud7rubEUyP))*W5>=CWHEC3nW;JP5lXf*ZsQR=~h1T9<;~zAM$to52lSrJMo}cza zh+qa*G%hbe9JQvGw7jJ4B?s*0Kv}6D!5#=5{mFoI`0;7*X@>tkLYF$5Pwvqi#=;!i zf`i-9EcSquiYSSgiZ}O@8{nZgfQTMO^+uCS=JB@`6lfc2dEWkWr0oLLGL zy>V6fZQWGf>}~=Z6rCd~Bud zGEn22*RJkKwDRrLuIWj%^DXskXhWrM{;mfUTGd2X-8er7s(s_!RbC7`Py<$ zx36!n=3WkSvY3l+GY3BT!Iq z*rcSCxH#&5coo+6*p_+xh%f?X5Ah9@g5Mgny;9v2}LV3lR(I*88 zxYbV_R92h@2C_5X4Sq6#(*D{WAFVfyqBG1q7zfLEGeF)RQ3)+GQ>w zFa*^vQ$}dY2u&GbL+28jGD1^EXj(cnWkjZo$dnOk2%;IXRSgM>N@En~ zlBMOMLzDpqw#A_*VfmyFhHj@uWjZyep;s51(S#}IQ8TZX$*P5%S}Vo}_SObaL6h=6 zJ32G~NN|Wjo`n1z@pl~=kERH4kf~Mv6BsrLo{(#PBGm_n;cHyPmIU5)7Jq?ed^UJ^ zoDN19A>b#6VTc4FJx9PF_=SRUFg~JY(>omxCsRbPo@47_9)Cmx|1X34M~cAUW=vaN z+8%(~*ODBZiHBF<3}!+>kkT;JgA}U~EJCzc02}9j*$!Mb44nOY2d^gq-t9KAkn$|C z$ZgSONO_L*WIwj-AzQ?%QYXu5Z%tCBM{-Q3 z`do8Yy~B=fF3P|b-Gn}|!g#AI=_a9~%Es1v4cVqxar)?@Z)82f?BB6ON#* z(%O3$Zu%e6v_HuDn4JwbAqGI&`HJ+_>U`+)$gA_A&+A^D4}IS7>U`+)rdQ`fpSQd^ANsuQ0ZAQ)K0om4 ze5mtA&69^Z&x}FfBTa9yDRToahYYwm!PEyprpG=~-gx9am+X*^%4L_S1aMNyR3h^f zc7jShMsK0LKHvj~@#D$5)9<<`^^JT3{v))8=HE?^TfyLcL7kL(bkg0iW@!!W%Mvx4mX;E;%OngpGbO%ibu+L3GNU$h-Z%7k(J zRT9BUngd8o&K_M2LkF-Yj}Hh4nnV>b9E`~c_a+u(Oe9}ldImWzKY0IJ>+&4cbI$Qb z&N&Kq&JilxIggM5QO{$J=su&UWpK)omcEOWlTzE{a%Ty=vjiT`NB8|RxS{?$0#2BJ zZO-3MW?s#gUT^)YtF!*m{r%)?eCr_+o^|#3NImIZdq0@pc}}_*u$<0?(Pzwa=MsXO zdHz)lxRBdf|6P2C@S}a1t@oq-=$~Z?T-t4uAWdlQ&&V7(*Ib80;v;Argc-?pteh+`-wPwYAb&Ab5Wozutw_b_ zHYO1(<5dc*_@x+v>>1i9g82m+cOKk}Q#>((qC(j}|3=}4C5yJvy!~J>fWJ4;U$ku| z0F3gl&4h_3C3VQ4TIRluk43koyS}+?!Cql)f*vpbp~S0$pf_MwiG-B6^ao>d7XtUJRdVgJ9BH){tHOs66S zovnowvA7mRg=KiMw5&HgICWg2X$@n?*o_boR2E}BxG`Y4ZQ!CfO{JNANHa&>p13+Y z`fo>eyS6H3Gh-DIiTXG{MoxMa0_AWpe??)z@ej<=37>P!K34{G^JfD681hE`!>54=0l%HU)OUBW)S^!VXffoBY87)M9 z#MS%3xAZalf}LP>_AD*;PcQr3$MG0`eja&$%8NuU_0<;|@7s`ej`Z#QnPhzlZu_Uv z=l(GTH^Bm~=6C*xhiaXc+hJFq2g4X$DA$%45VtH*U?DklZ2|gMv*{)Mxe=cZ za`?1VOMy0*{jANWdv~DG7)S!jtjGIXAXCg{9ChZWIXrBMQE$elq3KFY$(6oD(B18!%Hwx+D1rOfX!Hu1sO?RO-c;cMF*#2A)dn zW5((DQy96-*rb3dV@;Wt8?Jb^aPFD~t(6Wc%cij2CrxVjq zO&1}Rn?U}-=_|duVrhalwn!hr%~vZrQVA(#^g5-(!6cx5sj$j$8GWSK64eT`O?p~f zNxu1YGX10;w)KpLJhHx#(9WxsmFUwdpXF3`7yy{EI?SMPS1~$N@cep8a1|WWF!Y8Q zOm1)3qJ2lyYdhH7IS@)4!^C61^!U2lMfk}+1v$mC_WV7CDxylSY|GW00<=G`0HTt4 zi~#Fu0~MO>fbvbh#YU%Ha%zg)A-VeXF76#KS(PC^Xuv1ra?Zn|V!wDHw*{ zAkyrGT)RIPGZ;Ly#z%4&5SuZ%l)^t-F1vXXiG9g+>BxJ5!m$R<(8Wax=-emx1!ST} zp1b?)jJ?dvUo!SGa~@-FDGgjbW@Mmq47~Nn9Hh8tTeFv2%=9Wo#kj1=@Q zRH+{zWGk0kG4>K+e>&&gMo>G8A<9`p0KT-W%Ky0Zv0SZuBun>U*2FCUZQkBOYdLa( zRn*^Op;Zb1+g>ECwR9>(MaZaysw9V7J34u*ACtyHNXX4*8BPM0J6gtBhBqMLTD)Oc zR{xSG{qy3Yq++J{`ErVUOry;AS!@bjbur%{EpTM6FB6cobcA>5o^+@@VOQ2X;9%jo9vp zF3*S7z7txuBDCmUO$}+KR-*EJJzGXxL97K35?4HdGo2%@;C!3n3KK4tSx%&b8{=KA z385^rSO%e-(TuxfbIDmoglVlQ!T=k7Ya$HSp;&}Ti~3$fn5@LIp)i65ct&Al8TkBn zER5*=IYfRXZ+mSfWbF+Tq#R_f>ad~ZvSm$CR#{b2Csp29NGNi{uc3A|iS%KQyVpr; z{@bseZbv{&J{0h&O?SZ4w{!uOm%Z!rcDqkYFw5N+FPrx|>8lqD)7$PehriH9FzUL- zhq=i0XT)xf2{loy$wZ{z_cA7uBXO6hF1?oAqHVTFaL@3Rc7~@Edu3+4Er1QbHKxLq zC}t{YQU6e;f(Cd-rm_sH{CTNMIhB8uW6(sC;>wBCQi`c8Yl>~tr&2G+vs=ZC$S{>W zI_t8HWpDF6ckB}w&ax(Wo(^@`QhPJDq`b}ukX-1v`>B;Ig#gJ{$ciqofe|fW2K9N7 zan}ayDAmfYxu3no?d;{d*=a#bIS&C00fzeJ*b3(_VjM@p!X0NCEwA>B4%B$|OJBjo zyVfpq=4J`eb@kqI&McJP2~?OzCaO77x(5ZXmnK*wr9ip2?ytuUmeswe)&+IVSwWzN zjtYdZYp7e{dw7okC=xvW@L}{vd@GF@%Ls#cY4GxEe-@t=(k~WPGTPd^DD%Z2TL8OE#yazvI2BQWoRNQJ(!Nee*#!-j!#96 zt{J?v0|%RppzeCFni1?QrpOQ zP^5CC)tHt;hvcHlsStdg^^uM_GIm#_C44zl;v}dhVKs@WNxceuu%uZ{TGgaoO%AF) zsS$v_v&WueXp%j>{7$#BfC+kbdVbmi?35FQ%S#YHt?4B#FKK(p0q=EDR_aHv2LeZb zG7#Oykj?Nrz~5Govu%jwjq8;{G;f@h4e`8jW+_DU##v<`rZ>+oL<~kdv|jx2o3 zyYAq~gxsahxr6#z_5peMfx^Vh&47ogW5vf>8 z%}Ka${kPHmEoGa3LuIdSvK^x|YE)S9(xPJ*n`|qw$yA%B_7r}04aO@F@|&FN2y|jL zjDhAknvhY$;vx*;AvQ(CKDoRm7Z|hBvQ}Z8i|g}3n0f|zZW&K;Aow0w5YPd_8Ns(e zF3-+8C#Tov3a$EJHE#I}#DdQWgIp$re2NgL@8wEY59kSe!Og2g(S32@Hn2og*Oh zBsQ=W&Wt`uWBmDv1K@|#fU);fEy5Iu54R8pwoVY3Tsn%FG$Y15>(?lKXvQiJZ@Ofm(MgPMHwysNAyM7Z znqdexNR@_A@p@E;jn&Q`~1-1mii>V^4~R`j{`3WU$$2%uk6SwB^EsL|>Jz--H`0zh4>Uk0~6F!=|j z01OMAu5EHL>d6o|?lPAUz=7(QDI+vxgrqjM8KEg7G%X#PG9pt(WXgy_ol9iO zh)fv~?P2U2T`61MF_OA5{m`*4CBAxC24B4mFogCBe0A2hei;CJ{BAJK;-!ZMYa9(E zj}#^yvK7$7Ft?xxW%;Ov6h#G661uwx9AEVT3KvH8Mze*i7)X*LVhecyI%zb$#r!3J zN?97A(m@)lAwf}T3|v>Tw6&RwEe<^i!zX<(bUQUF)2W0>pVN#c7OET{^)gwtkW*{L z_`sgpVERpv@;*B{H1J1oh(Vr&{2lRk9T^jDO1UR6Y!W;n*Zf4P4-UiExQHzYyz4Cf zf{lXN;NfvP7-58fpB#oE5`^>|0e;{Y3d#{`qh`}P9StP;$MC5)3M|uO? zJ11ioEh(s3lEZS$W*UZiknSLxT}QPYte({#KqFM>f-P|c>HKUF?N}#JLK}?#|7B%> zpF3DRt4-E{)e{oV)Rs`K9MQlMEnarig5+wF?yyJqv$AtJ%;x6?+gnb{A&ylf9v0Zp zj+nc&XGhGf_Sg|~-53=K;SRY>sRs;^)G6Q?3*moO^C&M@3<*1gL| zc#I`tIv4{EmQ~EIMmel+;mL^ih_1ekhidQf>u7$bLx5xVh<1r$qwnLTy~jC03W4HB{EMzC@u9Ey@mGrfbSayk0Xjr3wgq0N=rZHSvuE!U%58V^)_7Nu;G5hSKxBT;0%Wd5tL0G9){_Cm=$F22ZuzQ z((i}iya`xzI7&^xiZ5B^f#BeYs=i8fDkTH>b zed!tGxcq>c-CCFDsGf6AOfdDYZ>5cb33AOW^T* zbf3anT5yPjYFX28nO9e5{iFN)$=CRng0D*Jjy_#IKI%*0MEBbJ!Tip1(ox)2=fdbS z=DBkTLCrk>Dh5o*?X3SUzC+kih3klbu2%kkmL)KZdrN(MfZ6lhCy#nf+u(DWhu@{) zRo(+u1q>sePA60G5YJ`<2weKJ@0ThUiFmeO%_pDPt*{%D|FDU3Q5@+7`HSH+rieDu zta(O(4aID98dHhF9m!TSP*I}hf?DV|=Ws8IIHzY%QMClY0GXW2%x zX24+oes5sEXxmKS7ahpm4RM-Agg5u?$nbPqy6KzS7TguqCZ$IdjXX-cI{0}5c9kkI z{ww#{MG*a7B8dKl$iCQiAy@s^bC?w04Q68g?Q<*u7{2py*$QX-tATxsyK^I4-x?II zAWcs69JsFga;(C%B{sk2RZ(2k44Z`g|5DzZ z+J)DP7<3w}2b+4Rg|XFL5ClwN8J;XH>kSW1nKMmm7(2#pgovQB80*1}{Yssx;*4l% z24MwzN8O&dIy?GrM|QieDVrIq@C1aHf6TmJGIYW58Cs%E^6DY<>+k`kr!@DVq-iWAWP|}z$lsbj<1MrN*&*C02lg1&rlg}wtU%r(gl9JIF< z!qCrih-B&AcYT6bwUe5b0#(+Wonh!Qi1a zK9akD*o?`gbUv{c73@o{OGn-d6pl4;hAu8rK<7TeE+7*<^4#5TXY6HW{*tkmne!NX zOKIThF~hPLiDB!HIY@EQwq`H4nCVrFig%A6fy#zp8E$XyfMm1#_1KHnL*WGl?h0xe zr(MSG;%`xTPK@@Q#%3ED8`H0;#^wd|ZPCsF(_yug0){;ZjJufvVfO~0KmH%<+W4T)SNS5xytch0u+PuAm)^fxG ztEj)nLaQNGFSH;=q>H4rFk}nS5HgCND#_ugwS}{Pqn9lvO|kw+CRv7$faQ*sahBl> zNSGF^b;{~r@}z%WT$EJI6hB{1@szXpkj2wPEB*12a-~E9o7_hf zAZfkpD|8c^WndSG;-bc>dD*WMQqYC1*ND~g+U!-+dhMW^PPI%)!m4_Gh! zzKeLD-4CKju35c7#&syxQKv-}74gz^)T+l%xyLC+W7gP3Z2_KMoOFK2Zs&B~pCosdOO!3~+pnE&M?g$I6!57{cfgfoSsga2!=`0?uFV?s?7Ycdh(_q~jXlW@f z(`b3MXLO)&-4CUiE?e3z-nDj_GdD|!uB-Q!b7rB(7I9RVM<%K{Qo2VD32A~wQVMi? p>pqD{SJDe%UoaWfo(Q?Zw~|(u)xD_J1$E6?L7;|?3WTt0{y(eK8g&2w delta 3124 zcmbRBkM+_jrU`2&A7XNvEWj)-q{-##=kDp}YOC&B=^5v%C;zclnrydOYx0||JbW%e{s9Uhj!r(VK=Z68A7pX{I=~pa0~9PsbAXP5dS!NT zraJi!amVfuO>6QT0t^=N-4cM^Ek;3Py9F3NIr*h|>8T3&X$l#M1qGRTsl~+<1XnC} zCt4>{+lfGzm!%d}Dx@WrC?w_NCsE+$EbMM}t*5!0brh1+4GfVX&>LLE8TsW3#W{(a z#VxOpns?3$V#~LI^`zulSf&BzXsqc2Bk-|!L`T7(!qCXr#MBJvB|cR9Cl}0=7E&+H%*hKmWWs=Kw3x+jxQ>E`v5o=+sh4DA7Nr19FoqbNpOXvXK#i^^ z)o5$3(t?!4l2lMRSDad+kY-}5pq`gnQKGI;o{?IVs*q-AYiP}tlA4nWRFqbfp9@ln zEL9AYN-j~*0!vQz-YheDPKyA0nxO$_nxWz3y)90P3}7G{$|+1?3$ zIgKYT;LzbgR)x1nwPgkC-h8fqH{)g|Ap^$EyC*d;Znl|X$Fx~d+=OZKpBb!Dz@pc7 zGWRyo&7Nk8jFWk`Kb_38BXIKvi{Cg>n^1%7XuW_|L51`5 Oh0%HeRJjeJdI118P@paV diff --git a/mysql-test/suite/rpl/r/rpl_row_extraColmaster_ndb.result b/mysql-test/suite/rpl/r/rpl_row_extraColmaster_ndb.result deleted file mode 100644 index 0b1f2e6c8bf9514ef53ef326dde109d3a78bdea8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19129 zcmeHP-EZ4Q62DjSvB14AdJnV%)+LwJmjyk@w$cifWuGLc7odPZTT7d;Od2GW#P`>C zX1_$zk|V3lCCHI-B<}9)?APp%vojNBdGbiIW$=M@%|#0Ld2qdCBnk=p6lHlva@WqO zoqKlf+j+yzn|9u^^R}ILx@O8UmXn7d%UP;Y`|`^2Ak9@zPA7x@Y(QrHlhFWrKn_Be z497E@gjD`|_)9J)!}I>+J^5|$9?E=j`fGo3K%GO|3>)O_=%PO(XM?x>tI>>D^vH3n zLvt|xWjG%6tnt~2)ir}9bX|@a+Tk-0HoE3;JRMACB#QF{+y4+OS1cn3u1&h9(~+xAV8rk{M$1f4Yuh7#>`%Ibp$KF55z~%OnFn z6SfSV=DJ!jqexJww}rhP)?^jOQG9E>XPF%9^xva-F?Yfqm(dLjetwqB&rS^JgvuD+ z#z_kKrA(ljq4aGae3t)vv|J$D%>|OZEF8ha&j)E5Cx&CHM3Nfj^geo=pC+pqgaC>L zpV-YyGdFzn9R=T{CozkQ$+9 zgudw-_~CoWJeyox>K)%TzZeAA#0;APDg47VJj@2u*^cmFOPpxF4kv74J>6%KRpUjC z7d2jd7kB}BMvE&VTFcl~#n2d{Zd&_+31}cSp450!i6Cx9_+G8_D7w%gf7;Ym~7 zwA4*|Z-fEOWeHmHEh9-t?t;h1C}vq!D>C)Lr#|@1zklEX1nQ8{#rT(#(Z$JMMj-`9 zU_W||l|`MNxCLe-903KKV&RY(u$dWU}>SSi$U zoi7esHo3MOxA>`%tVXgL$-Y4(`}qyH$?`NHZ+_n9aeB$zyvcl|k9#GptAuKpaLK#= zU zJubk5hF%o(wT6C=STV?)MLvSlhmp|j!SXD?;{rs=-%>2v*%@Pm4I^wCVao{HM%Xdn zF$(`&lN$ID6AU*vwea)Ov>GKf-1rB-{&{8m;J-6H13!H3;P)P84Sx1zR=Zu%#f%5g z+U+Wxr@}X@{NA!Y;>)h4Nf7zV|3uQ>`tN7g+K?4<^Y;DIUk%2ug=jl0m%*lu7k<& z^q^^jcUSYH>l$!6fJY~f6mcEuW2^`~P35B$Vn@jMVg_7Bqjj(UaCZA(hg?dggW1-B zfmNasg7SNiVjM+wY|1+b4r%(v#VSW@YZ{>0mB*iuFiFWxvRpmH#0onW0Xs(uaVKtN z*}Sj3Y?USX*5Y5f+?@OI<7C%qCvMIlZw1aAZ~4h6hXkZgZkwCpg+MX4ZZ5HR+!O*3^03eNTaRwI$~K{ zW2xuZEl%Dc0-d4Qa|psQ;jpz0jy+e;o=3Hua%e^t9^#(hunExt>ZwD@26vY#>ZltRjs_ya&xI&Hyu$^r1Oa+mIk$D~XM8{n zuk!J?@>x6N6vK@@toF+#rVLM1)m}Yj$-sqkk(>uOugE)J-!=4|ZU7cp(Y0;GMfaNO z`Ji%MNl0}YRJTEO8?>RgP~8UAZBRYaRJQ?AD|_JSHax1hc)ATwx8YU8IH@>6!GQ_m zNcp$Nzx|#L=M39$-##V}Y!R&>6GeV zQE@cIGpIV9n&Nbd>W)-M94y|_Ad+AyG)c-$+9ntX`PsN7H7DDAelj)1$rM}jg!<#) z@pMaTNV02dU8So06{TfQZHJbp+uLPP)yh?-v9fahF05K01Fg@<2L$5=;D>^9dr*}Q zz)*gSe?bT$%OqGBBw zha5mjNh*@SoJbO>Hx&zo5UfcG3RRg*@sK)Jxe&QP@71(O?P~)KJ#KW48||Y`rz43= z3Rcalnd}7cor4P5~1L!xK$NRP0F``9Hv%1bt$$7*Lt6*ZBY0X zm7nRVXgS~;18yXV(p0PLxv`cH=a~kpNktbVqk>Y4YB4rt7u(vT(W*_#w+(rS;#Ee( z>H+kYR9(SJj9knj$)gAOk0yMTEK`(#{d)sY?_wip6cG7Uk6Y>&YQBu+pl?}WvP$zi zIr%l1i)F)aExbaU;Bc+anp)mC^-B<2IFjyOsRr{J%oPxE36o%6V>#NEzZ#Yku)N6s zMF_`iICh3LZk9of3u}#=d>X`8tpuyd_=-w!jho*JZi2zk%A!v@;3hipgyK~j3N)gM z8>y?;h5`jG@LL-S3QyvF36PBnfbVN) z8vOao^HpRZPxywg1nHnf<-BP08s$qxFM2(AiGm7oRMfOb*X7_>t(Lnz9-bqk9Knb8 zoW$cK==o@=J9K-X0WM}Ag*!rrPz^&F}UKI@%V~L&}AhE n6S`dr%7hk5X}^;8U=WoB#;l@f)zOZ1v?G7>O#PA>c*)G4sd{H} diff --git a/mysql-test/suite/rpl/t/rpl_extraColmaster_innodb.test b/mysql-test/suite/rpl/t/rpl_extraColmaster_innodb.test index 082c22329fa..5255a9cfbad 100644 --- a/mysql-test/suite/rpl/t/rpl_extraColmaster_innodb.test +++ b/mysql-test/suite/rpl/t/rpl_extraColmaster_innodb.test @@ -12,4 +12,5 @@ set binlog_format=row; set binlog_format=statement; -- source extra/rpl_tests/rpl_extraMaster_Col.test - +set binlog_format=mixed; +-- source extra/rpl_tests/rpl_extraMaster_Col.test diff --git a/mysql-test/suite/rpl/t/rpl_extraColmaster_myisam.test b/mysql-test/suite/rpl/t/rpl_extraColmaster_myisam.test index 5bbd7953294..e6b41eabd0d 100644 --- a/mysql-test/suite/rpl/t/rpl_extraColmaster_myisam.test +++ b/mysql-test/suite/rpl/t/rpl_extraColmaster_myisam.test @@ -11,3 +11,5 @@ set binlog_format=row; set binlog_format=statement; -- source extra/rpl_tests/rpl_extraMaster_Col.test +set binlog_format=mixed; +-- source extra/rpl_tests/rpl_extraMaster_Col.test diff --git a/mysql-test/suite/rpl/t/rpl_row_extraColmaster_ndb.test b/mysql-test/suite/rpl/t/rpl_row_extraColmaster_ndb.test deleted file mode 100644 index b91947e52e2..00000000000 --- a/mysql-test/suite/rpl/t/rpl_row_extraColmaster_ndb.test +++ /dev/null @@ -1,12 +0,0 @@ -########################################### -# Purpose: Wrapper for rpl_extraMaster_Col.test -# Using NDB -########################################### --- source include/have_ndb.inc --- source include/ndb_master-slave.inc --- source include/have_binlog_format_row.inc - -let $engine_type = 'NDB'; - --- source extra/rpl_tests/rpl_extraMaster_Col.test - diff --git a/mysql-test/suite/rpl/t/rpl_stm_extraColmaster_ndb.test b/mysql-test/suite/rpl/t/rpl_stm_extraColmaster_ndb.test deleted file mode 100644 index 84734204439..00000000000 --- a/mysql-test/suite/rpl/t/rpl_stm_extraColmaster_ndb.test +++ /dev/null @@ -1,13 +0,0 @@ -########################################### -# Purpose: Wrapper for rpl_extraMaster_Col.test -# Using NDB -########################################### --- source include/have_ndb.inc --- source include/ndb_master-slave.inc --- source include/have_binlog_format_statement.inc - -let $engine_type = 'NDB'; - --- source extra/rpl_tests/rpl_extraMaster_Col.test - - From cc62b3406159c795ea8dd13212fbaacbab5aa4c3 Mon Sep 17 00:00:00 2001 From: "jmiller/ndbdev@mysql.com/ndb15.mysql.com" <> Date: Wed, 10 Oct 2007 17:22:21 +0200 Subject: [PATCH 34/92] rpl_ndb_extraColMaster.test, rpl_ndb_extraColMaster.result: Back porting NDB test case --- .../rpl_ndb/r/rpl_ndb_extraColMaster.result | 2286 +++++++++++++++++ .../rpl_ndb/t/rpl_ndb_extraColMaster.test | 14 + 2 files changed, 2300 insertions(+) create mode 100644 mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result create mode 100644 mysql-test/suite/rpl_ndb/t/rpl_ndb_extraColMaster.test diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result new file mode 100644 index 00000000000..38c8ab2afc5 --- /dev/null +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result @@ -0,0 +1,2286 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +set binlog_format=row; + +*********************************************************** +*********************************************************** +***************** Start of Testing ************************ +*********************************************************** +*********************************************************** +* This test format == binlog_format ROW and engine == 'NDB' +*********************************************************** +*********************************************************** + +***** Testing more columns on the Master ***** + +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 FLOAT DEFAULT '2.00', +f6 CHAR(4) DEFAULT 'TEST', +f7 INT DEFAULT '0', +f8 TEXT, +f9 LONGBLOB, +f10 BIT(63), +f11 VARBINARY(64))ENGINE='NDB'; + +* Alter Table on Slave and drop columns f5 through f11 * + +alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11; + +* Insert data in Master then update and delete some rows* + +* Select count and 20 rows from Master * + +SELECT COUNT(*) FROM t1; +COUNT(*) +40 + +SELECT f1,f2,f3,f4,f5,f6,f7,f8,f9, +hex(f10),hex(f11) FROM t1 ORDER BY f3 LIMIT 20; +f1 f2 f3 f4 f5 f6 f7 f8 f9 hex(f10) hex(f11) +2 2 2 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +3 3 3 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +5 5 5 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +6 6 6 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +8 8 8 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +9 9 9 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +11 11 11 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +12 12 12 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +14 14 14 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +15 15 15 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +17 17 17 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +18 18 18 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +20 20 20 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +21 21 21 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +23 23 23 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +24 24 24 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +26 26 26 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +27 27 27 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +29 29 29 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +30 30 30 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 + +* Select count and 20 rows from Slave * + +SELECT COUNT(*) FROM t1; +COUNT(*) +40 + +SELECT * FROM t1 ORDER BY f3 LIMIT 20; +f1 f2 f3 f4 +2 2 2 second +3 3 3 next +5 5 5 second +6 6 6 next +8 8 8 second +9 9 9 next +11 11 11 second +12 12 12 next +14 14 14 second +15 15 15 next +17 17 17 second +18 18 18 next +20 20 20 second +21 21 21 next +23 23 23 second +24 24 24 next +26 26 26 second +27 27 27 next +29 29 29 second +30 30 30 next + +* Show Slave Status * + +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 0 +Last_SQL_Error + + +***** Testing Altering table def scenario ***** + +CREATE TABLE t2 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 DOUBLE DEFAULT '2.00', +f6 ENUM('a', 'b', 'c') default 'a', +f7 DECIMAL(17,9) default '1000.00', +f8 MEDIUMBLOB, +f9 NUMERIC(6,4) default '2000.00', +f10 VARCHAR(1024), +f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +f12 SET('a', 'b', 'c') default 'b') +ENGINE='NDB'; +Warnings: +Warning 1264 Out of range value for column 'f9' at row 1 + +CREATE TABLE t3 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 DOUBLE DEFAULT '2.00', +f6 ENUM('a', 'b', 'c') default 'a', +f8 MEDIUMBLOB, +f10 VARCHAR(1024), +f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +f12 SET('a', 'b', 'c') default 'b') +ENGINE='NDB'; + +CREATE TABLE t4 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 DOUBLE DEFAULT '2.00', +f6 DECIMAL(17,9) default '1000.00', +f7 MEDIUMBLOB, +f8 NUMERIC(6,4) default '2000.00', +f9 VARCHAR(1024), +f10 BINARY(20) not null default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +f11 CHAR(255)) +ENGINE='NDB'; +Warnings: +Warning 1264 Out of range value for column 'f8' at row 1 + +CREATE TABLE t31 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 BIGINT, +f6 BLOB, +f7 DATE, +f8 DATETIME, +f9 FLOAT, +f10 INT, +f11 LONGBLOB, +f12 LONGTEXT, +f13 MEDIUMBLOB, +f14 MEDIUMINT, +f15 MEDIUMTEXT, +f16 REAL, +f17 SMALLINT, +f18 TEXT, +f19 TIME, +f20 TIMESTAMP, +f21 TINYBLOB, +f22 TINYINT, +f23 TINYTEXT, +f24 YEAR, +f25 BINARY(255), +f26 BIT(64), +f27 CHAR(255), +f28 DECIMAL(30,7), +f29 DOUBLE, +f30 ENUM ('a','b', 'c') default 'a', +f31 FLOAT, +f32 NUMERIC(17,9), +f33 SET ('a', 'b', 'c') default 'b', +f34 VARBINARY(1025), +f35 VARCHAR(257) +) ENGINE='NDB'; + +** Alter tables on slave and drop columns ** + +alter table t2 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11, drop +f12; +alter table t3 drop f5, drop f6, drop f8, drop f10, drop f11, drop f12; +alter table t4 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11; +alter table t31 +drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11, +drop f12, drop f13, drop f14, drop f15, drop f16, drop f17, drop f18, +drop f19, drop f20, drop f21, drop f22, drop f23, drop f24, drop f25, +drop f26, drop f27, drop f28, drop f29, drop f30, drop f31, drop f32, +drop f33, drop f34, drop f35; + +** Insert Data into Master ** +INSERT into t2 set f1=1, f2=1, f3=1, f4='first', f8='f8: medium size blob', f10='f10: +some var char'; +INSERT into t2 values (2, 2, 2, 'second', +2.0, 'b', 2000.0002, 'f8: medium size blob', 2000, 'f10: some var char', +'01234567', 'c'), +(3, 3, 3, 'third', +3.0, 'b', 3000.0003, 'f8: medium size blob', 3000, 'f10: some var char', +'01234567', 'c'); +Warnings: +Warning 1264 Out of range value for column 'f9' at row 1 +Warning 1264 Out of range value for column 'f9' at row 2 +INSERT into t3 set f1=1, f2=1, f3=1, f4='first', f10='f10: some var char'; +INSERT into t4 set f1=1, f2=1, f3=1, f4='first', f7='f7: medium size blob', f10='f10: +binary data'; +INSERT into t31 set f1=1, f2=1, f3=1, f4='first'; +INSERT into t31 set f1=1, f2=1, f3=2, f4='second', +f9=2.2, f10='seven samurai', f28=222.222, f35='222'; +Warnings: +Warning 1366 Incorrect integer value: 'seven samurai' for column 'f10' at row 1 +INSERT into t31 values (1, 1, 3, 'third', +/* f5 BIGINT, */ 333333333333333333333333, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ 'three times three' + ); +Warnings: +Warning 1264 Out of range value for column 'f5' at row 1 +Warning 1264 Out of range value for column 'f24' at row 1 +INSERT into t31 values (1, 1, 4, 'fourth', +/* f5 BIGINT, */ 333333333333333333333333, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ 'three times three' + ), +(1, 1, 5, 'fifth', +/* f5 BIGINT, */ 333333333333333333333333, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ 'three times three' + ), +(1, 1, 6, 'sixth', +/* f5 BIGINT, */ NULL, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ NULL +); +Warnings: +Warning 1264 Out of range value for column 'f5' at row 1 +Warning 1264 Out of range value for column 'f24' at row 1 +Warning 1264 Out of range value for column 'f5' at row 2 +Warning 1264 Out of range value for column 'f24' at row 2 +Warning 1264 Out of range value for column 'f24' at row 3 + +** Sync slave with master ** +** Do selects from tables ** + +select * from t1 order by f3; +f1 f2 f3 f4 +2 2 2 second +3 3 3 next +5 5 5 second +6 6 6 next +8 8 8 second +9 9 9 next +11 11 11 second +12 12 12 next +14 14 14 second +15 15 15 next +17 17 17 second +18 18 18 next +20 20 20 second +21 21 21 next +23 23 23 second +24 24 24 next +26 26 26 second +27 27 27 next +29 29 29 second +30 30 30 next +31 31 31 second +32 32 32 second +33 33 33 second +34 34 34 second +35 35 35 second +36 36 36 second +37 37 37 second +38 38 38 second +39 39 39 second +40 40 40 second +41 41 41 second +42 42 42 second +43 43 43 second +44 44 44 second +45 45 45 second +46 46 46 second +47 47 47 second +48 48 48 second +49 49 49 second +50 50 50 second +select * from t2 order by f1; +f1 f2 f3 f4 +1 1 1 first +2 2 2 second +3 3 3 third +select * from t3 order by f1; +f1 f2 f3 f4 +1 1 1 first +select * from t4 order by f1; +f1 f2 f3 f4 +1 1 1 first +select * from t31 order by f1; +f1 f2 f3 f4 +1 1 5 fifth +1 1 3 third +1 1 1 first +1 1 6 sixth +1 1 2 second +1 1 4 fourth + +** Do updates master ** + +update t31 set f5=555555555555555 where f3=6; +update t31 set f2=2 where f3=2; +update t31 set f1=NULL where f3=1; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null + +** Delete from Master ** + +delete from t1; +delete from t2; +delete from t3; +delete from t4; +delete from t31; + +** Check slave status ** + +select * from t31; +f1 f2 f3 f4 +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 0 +Last_SQL_Error + +**************************************** +* columns in master at middle of table * +* Expect: Proper error message * +**************************************** + +** Stop and Reset Slave ** + +STOP SLAVE; +RESET SLAVE; + +** create table slave side ** +CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='NDB'; + +** Connect to master and create table ** + +CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', +c CHAR(5), e INT DEFAULT '1')ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT), +(2,@b1,DEFAULT,'JOE',DEFAULT), +(3,@b1,DEFAULT,'QA',DEFAULT); + +******************************************** +*** Expect slave to fail with Error 1523 *** +******************************************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1532 +Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1532 +Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +*** Drop t10 *** +DROP TABLE t10; + +********************************************* +* More columns in master at middle of table * +* Expect: Proper error message * +********************************************* + +*** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) +) ENGINE='NDB'; + +*** Create t11 on Master *** +CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT), +(2,@b1,'Testing is cool','JOE',DEFAULT), +(3,@b1,DEFAULT,'QA',DEFAULT); + +******************************************** +*** Expect slave to fail with Error 1523 *** +******************************************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1532 +Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1532 +Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +*** Drop t11 *** +DROP TABLE t11; + +********************************************* +* More columns in master at middle of table * +* Expect: This one should pass blob-text * +********************************************* + +*** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB +) ENGINE='NDB'; + +*** Create t12 on Master *** +CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',DEFAULT,DEFAULT), +(3,@b1,'QA',DEFAULT,DEFAULT); + +SELECT a,hex(b),f,c,e FROM t12 ORDER BY a; +a hex(b) f c e +1 62316231623162316231623162316231 Kyle test 1 +2 62316231623162316231623162316231 JOE test 1 +3 62316231623162316231623162316231 QA test 1 + +*** Select on Slave *** +SELECT a,hex(b),c FROM t12 ORDER BY a; +a hex(b) c +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA + +*** Drop t12 *** +DROP TABLE t12; + +**************************************************** +* - Alter Master adding columns at middle of table * +* Expect: columns added * +**************************************************** + + +*** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t14 on Master *** +CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; + +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle',DEFAULT,DEFAULT), +(2,2.00,'This Test Should work',@b1,'JOE',DEFAULT,DEFAULT), +(3,3.00,'If is does not, I will open a bug',@b1,'QA',DEFAULT,DEFAULT); + +SELECT c1,c2,c3,hex(c4),c5,c6,c7 FROM t14 ORDER BY c1; +c1 c2 c3 hex(c4) c5 c6 c7 +1 1.00 Replication Testing Extra Col 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work 62316231623162316231623162316231 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug 62316231623162316231623162316231 QA 1 CURRENT_TIMESTAMP + +*** Select on Slave **** +SELECT c1,c2,c3,hex(c4),c5 FROM t14 ORDER BY c1; +c1 c2 c3 hex(c4) c5 +1 1.00 Replication Testing Extra Col 62316231623162316231623162316231 Kyle +2 2.00 This Test Should work 62316231623162316231623162316231 JOE +3 3.00 If is does not, I will open a bug 62316231623162316231623162316231 QA + +**************************************************** +* - Alter Master Dropping columns from the middle. * +* Expect: columns dropped * +**************************************************** + +*** connect to master and drop columns *** +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c7; + +*** Select from Master *** +SELECT c1,c3,hex(c4),c5,c6 FROM t14 ORDER BY c1; +c1 c3 hex(c4) c5 c6 +1 Replication Testing Extra Col 62316231623162316231623162316231 Kyle 1 +2 This Test Should work 62316231623162316231623162316231 JOE 1 +3 If is does not, I will open a bug 62316231623162316231623162316231 QA 1 + +************ +* Bug30415 * +************ +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1091 +Last_Error Error 'Can't DROP 'c7'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t14 DROP COLUMN c7' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1091 +Last_SQL_Error Error 'Can't DROP 'c7'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t14 DROP COLUMN c7' +STOP SLAVE; +RESET SLAVE; + +*** Drop t14 *** +DROP TABLE t14; +DROP TABLE t14; +RESET MASTER; +START SLAVE; + +************************************************* +* - Alter Master adding columns at end of table * +* Expect: Error 1054 * +************************************************* + +*** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t15 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t15 on Master *** +CREATE TABLE t15 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT,3.00), +(2,@b1,'JOE',DEFAULT,DEFAULT,3.00), +(3,@b1,'QA',DEFAULT,DEFAULT,3.00); +SELECT c1,hex(c4),c5,c6,c7,c2 FROM t15 ORDER BY c1; +c1 hex(c4) c5 c6 c7 c2 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP 3.00 +2 62316231623162316231623162316231 JOE 1 CURRENT_TIMESTAMP 3.00 +3 62316231623162316231623162316231 QA 1 CURRENT_TIMESTAMP 3.00 + +******************************************** +*** Expect slave to fail with Error 1054 *** +******************************************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1054 +Last_Error Error 'Unknown column 'c7' in 't15'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1054 +Last_SQL_Error Error 'Unknown column 'c7' in 't15'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7' +STOP SLAVE; +RESET SLAVE; + +*** Drop t15 *** +DROP TABLE t15; +DROP TABLE t15; +RESET MASTER; +START SLAVE; + +************************************************ +* - Create index on Master column not on slave * +* Expect:Warning * +************************************************ + +*** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t16 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t16 on Master *** +CREATE TABLE t16 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Create Index and Data Insert *** +CREATE INDEX part_of_c6 ON t16 (c6); +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',2,DEFAULT), +(3,@b1,'QA',3,DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t16 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +***************** +*** BUG 30434 *** +***************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1072 +Last_Error Error 'Key column 'c6' doesn't exist in table' on query. Default database: 'test'. Query: 'CREATE INDEX part_of_c6 ON t16 (c6)' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1072 +Last_SQL_Error Error 'Key column 'c6' doesn't exist in table' on query. Default database: 'test'. Query: 'CREATE INDEX part_of_c6 ON t16 (c6)' +STOP SLAVE; +RESET SLAVE; + +*** Drop t16 *** +DROP TABLE t16; +DROP TABLE t16; +RESET MASTER; +START SLAVE; + +***************************************************** +* - Delete rows using column on Master not on slave * +* Expect: Rows Deleted * +***************************************************** + +*** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t17 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t17 on Master *** +CREATE TABLE t17 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t17 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',2,DEFAULT), +(3,@b1,'QA',3,DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t17 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +** Select * from Slave ** +SELECT c1,hex(c4),c5 FROM t17 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA + +** Delete from master ** +DELETE FROM t17 WHERE c6 = 3; +SELECT c1,hex(c4),c5,c6,c7 FROM t17 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP + +** Check slave ** +SELECT c1,hex(c4),c5 FROM t17 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +DROP TABLE t17; + + +***************************************************** +* - Update row using column on Master not on slave * +* Expect: Rows updated * +***************************************************** + +** Bug30674 ** + +*** Create t18 on slave *** + +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t18 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t18 on Master *** +CREATE TABLE t18 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t18 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',2,DEFAULT), +(3,@b1,'QA',3,DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t18 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +** Select * from Slave ** +SELECT c1,hex(c4),c5 FROM t18 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA + +** update from master ** +SELECT c1,hex(c4),c5,c6,c7 FROM t18 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +** Check slave ** +SELECT c1,hex(c4),c5 FROM t18 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA +DROP TABLE t18; + + +***************************************************** +* - Insert UUID column on Master not on slave * +* Expect: Rows inserted * +***************************************************** + +*** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t5 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t5 on Master *** +CREATE TABLE t5 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 LONG, +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +INSERT INTO t5 () VALUES(1,@b1,'Kyle',UUID(),DEFAULT), +(2,@b1,'JOE',UUID(),DEFAULT), +(3,@b1,'QA',UUID(),DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t5 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 6231623162316231 Kyle UUID TIME +2 6231623162316231 JOE UUID TIME +3 6231623162316231 QA UUID TIME + +** Select * from Slave ** +SELECT c1,hex(c4),c5 FROM t5 ORDER BY c1; +c1 hex(c4) c5 +1 6231623162316231 Kyle +2 6231623162316231 JOE +3 6231623162316231 QA +DROP TABLE t5; + +set binlog_format=mixed; + +*********************************************************** +*********************************************************** +***************** Start of Testing ************************ +*********************************************************** +*********************************************************** +* This test format == binlog_format MIXED and engine == 'NDB' +*********************************************************** +*********************************************************** + +***** Testing more columns on the Master ***** + +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 FLOAT DEFAULT '2.00', +f6 CHAR(4) DEFAULT 'TEST', +f7 INT DEFAULT '0', +f8 TEXT, +f9 LONGBLOB, +f10 BIT(63), +f11 VARBINARY(64))ENGINE='NDB'; + +* Alter Table on Slave and drop columns f5 through f11 * + +alter table t1 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11; + +* Insert data in Master then update and delete some rows* + +* Select count and 20 rows from Master * + +SELECT COUNT(*) FROM t1; +COUNT(*) +40 + +SELECT f1,f2,f3,f4,f5,f6,f7,f8,f9, +hex(f10),hex(f11) FROM t1 ORDER BY f3 LIMIT 20; +f1 f2 f3 f4 f5 f6 f7 f8 f9 hex(f10) hex(f11) +2 2 2 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +3 3 3 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +5 5 5 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +6 6 6 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +8 8 8 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +9 9 9 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +11 11 11 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +12 12 12 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +14 14 14 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +15 15 15 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +17 17 17 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +18 18 18 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +20 20 20 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +21 21 21 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +23 23 23 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +24 24 24 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +26 26 26 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +27 27 27 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +29 29 29 second 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 +30 30 30 next 2 kaks 2 got stolen from the paradise very fat blob 1555 123456 + +* Select count and 20 rows from Slave * + +SELECT COUNT(*) FROM t1; +COUNT(*) +40 + +SELECT * FROM t1 ORDER BY f3 LIMIT 20; +f1 f2 f3 f4 +2 2 2 second +3 3 3 next +5 5 5 second +6 6 6 next +8 8 8 second +9 9 9 next +11 11 11 second +12 12 12 next +14 14 14 second +15 15 15 next +17 17 17 second +18 18 18 next +20 20 20 second +21 21 21 next +23 23 23 second +24 24 24 next +26 26 26 second +27 27 27 next +29 29 29 second +30 30 30 next + +* Show Slave Status * + +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 0 +Last_SQL_Error + + +***** Testing Altering table def scenario ***** + +CREATE TABLE t2 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 DOUBLE DEFAULT '2.00', +f6 ENUM('a', 'b', 'c') default 'a', +f7 DECIMAL(17,9) default '1000.00', +f8 MEDIUMBLOB, +f9 NUMERIC(6,4) default '2000.00', +f10 VARCHAR(1024), +f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +f12 SET('a', 'b', 'c') default 'b') +ENGINE='NDB'; +Warnings: +Warning 1264 Out of range value for column 'f9' at row 1 + +CREATE TABLE t3 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 DOUBLE DEFAULT '2.00', +f6 ENUM('a', 'b', 'c') default 'a', +f8 MEDIUMBLOB, +f10 VARCHAR(1024), +f11 BINARY(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +f12 SET('a', 'b', 'c') default 'b') +ENGINE='NDB'; + +CREATE TABLE t4 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 DOUBLE DEFAULT '2.00', +f6 DECIMAL(17,9) default '1000.00', +f7 MEDIUMBLOB, +f8 NUMERIC(6,4) default '2000.00', +f9 VARCHAR(1024), +f10 BINARY(20) not null default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', +f11 CHAR(255)) +ENGINE='NDB'; +Warnings: +Warning 1264 Out of range value for column 'f8' at row 1 + +CREATE TABLE t31 (f1 INT, f2 INT, f3 INT PRIMARY KEY, f4 CHAR(20), +/* extra */ +f5 BIGINT, +f6 BLOB, +f7 DATE, +f8 DATETIME, +f9 FLOAT, +f10 INT, +f11 LONGBLOB, +f12 LONGTEXT, +f13 MEDIUMBLOB, +f14 MEDIUMINT, +f15 MEDIUMTEXT, +f16 REAL, +f17 SMALLINT, +f18 TEXT, +f19 TIME, +f20 TIMESTAMP, +f21 TINYBLOB, +f22 TINYINT, +f23 TINYTEXT, +f24 YEAR, +f25 BINARY(255), +f26 BIT(64), +f27 CHAR(255), +f28 DECIMAL(30,7), +f29 DOUBLE, +f30 ENUM ('a','b', 'c') default 'a', +f31 FLOAT, +f32 NUMERIC(17,9), +f33 SET ('a', 'b', 'c') default 'b', +f34 VARBINARY(1025), +f35 VARCHAR(257) +) ENGINE='NDB'; + +** Alter tables on slave and drop columns ** + +alter table t2 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11, drop +f12; +alter table t3 drop f5, drop f6, drop f8, drop f10, drop f11, drop f12; +alter table t4 drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11; +alter table t31 +drop f5, drop f6, drop f7, drop f8, drop f9, drop f10, drop f11, +drop f12, drop f13, drop f14, drop f15, drop f16, drop f17, drop f18, +drop f19, drop f20, drop f21, drop f22, drop f23, drop f24, drop f25, +drop f26, drop f27, drop f28, drop f29, drop f30, drop f31, drop f32, +drop f33, drop f34, drop f35; + +** Insert Data into Master ** +INSERT into t2 set f1=1, f2=1, f3=1, f4='first', f8='f8: medium size blob', f10='f10: +some var char'; +INSERT into t2 values (2, 2, 2, 'second', +2.0, 'b', 2000.0002, 'f8: medium size blob', 2000, 'f10: some var char', +'01234567', 'c'), +(3, 3, 3, 'third', +3.0, 'b', 3000.0003, 'f8: medium size blob', 3000, 'f10: some var char', +'01234567', 'c'); +Warnings: +Warning 1264 Out of range value for column 'f9' at row 1 +Warning 1264 Out of range value for column 'f9' at row 2 +INSERT into t3 set f1=1, f2=1, f3=1, f4='first', f10='f10: some var char'; +INSERT into t4 set f1=1, f2=1, f3=1, f4='first', f7='f7: medium size blob', f10='f10: +binary data'; +INSERT into t31 set f1=1, f2=1, f3=1, f4='first'; +INSERT into t31 set f1=1, f2=1, f3=2, f4='second', +f9=2.2, f10='seven samurai', f28=222.222, f35='222'; +Warnings: +Warning 1366 Incorrect integer value: 'seven samurai' for column 'f10' at row 1 +INSERT into t31 values (1, 1, 3, 'third', +/* f5 BIGINT, */ 333333333333333333333333, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ 'three times three' + ); +Warnings: +Warning 1264 Out of range value for column 'f5' at row 1 +Warning 1264 Out of range value for column 'f24' at row 1 +INSERT into t31 values (1, 1, 4, 'fourth', +/* f5 BIGINT, */ 333333333333333333333333, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ 'three times three' + ), +(1, 1, 5, 'fifth', +/* f5 BIGINT, */ 333333333333333333333333, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ 'three times three' + ), +(1, 1, 6, 'sixth', +/* f5 BIGINT, */ NULL, +/* f6 BLOB, */ '3333333333333333333333', +/* f7 DATE, */ '2007-07-18', +/* f8 DATETIME, */ "2007-07-18", +/* f9 FLOAT, */ 3.33333333, +/* f10 INT, */ 333333333, +/* f11 LONGBLOB, */ '3333333333333333333', +/* f12 LONGTEXT, */ '3333333333333333333', +/* f13 MEDIUMBLOB, */ '3333333333333333333', +/* f14 MEDIUMINT, */ 33, +/* f15 MEDIUMTEXT, */ 3.3, +/* f16 REAL, */ 3.3, +/* f17 SMALLINT, */ 3, +/* f18 TEXT, */ '33', +/* f19 TIME, */ '2:59:58.999', +/* f20 TIMESTAMP, */ 20000303000000, +/* f21 TINYBLOB, */ '3333', +/* f22 TINYINT, */ 3, +/* f23 TINYTEXT, */ '3', +/* f24 YEAR, */ 3000, +/* f25 BINARY(255), */ 'three_33333', +/* f26 BIT(64), */ b'011', +/* f27 CHAR(255), */ 'three', +/* f28 DECIMAL(30,7), */ 3.333, +/* f29 DOUBLE, */ 3.333333333333333333333333333, +/* f30 ENUM ('a','b','c')*/ 'c', +/* f31 FLOAT, */ 3.0, +/* f32 NUMERIC(17,9), */ 3.3333, +/* f33 SET ('a','b','c'),*/ 'c', +/*f34 VARBINARY(1025),*/ '3333 minus 3', +/*f35 VARCHAR(257),*/ NULL +); +Warnings: +Warning 1264 Out of range value for column 'f5' at row 1 +Warning 1264 Out of range value for column 'f24' at row 1 +Warning 1264 Out of range value for column 'f5' at row 2 +Warning 1264 Out of range value for column 'f24' at row 2 +Warning 1264 Out of range value for column 'f24' at row 3 + +** Sync slave with master ** +** Do selects from tables ** + +select * from t1 order by f3; +f1 f2 f3 f4 +2 2 2 second +3 3 3 next +5 5 5 second +6 6 6 next +8 8 8 second +9 9 9 next +11 11 11 second +12 12 12 next +14 14 14 second +15 15 15 next +17 17 17 second +18 18 18 next +20 20 20 second +21 21 21 next +23 23 23 second +24 24 24 next +26 26 26 second +27 27 27 next +29 29 29 second +30 30 30 next +31 31 31 second +32 32 32 second +33 33 33 second +34 34 34 second +35 35 35 second +36 36 36 second +37 37 37 second +38 38 38 second +39 39 39 second +40 40 40 second +41 41 41 second +42 42 42 second +43 43 43 second +44 44 44 second +45 45 45 second +46 46 46 second +47 47 47 second +48 48 48 second +49 49 49 second +50 50 50 second +select * from t2 order by f1; +f1 f2 f3 f4 +1 1 1 first +2 2 2 second +3 3 3 third +select * from t3 order by f1; +f1 f2 f3 f4 +1 1 1 first +select * from t4 order by f1; +f1 f2 f3 f4 +1 1 1 first +select * from t31 order by f1; +f1 f2 f3 f4 +1 1 5 fifth +1 1 3 third +1 1 1 first +1 1 6 sixth +1 1 2 second +1 1 4 fourth + +** Do updates master ** + +update t31 set f5=555555555555555 where f3=6; +update t31 set f2=2 where f3=2; +update t31 set f1=NULL where f3=1; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null + +** Delete from Master ** + +delete from t1; +delete from t2; +delete from t3; +delete from t4; +delete from t31; + +** Check slave status ** + +select * from t31; +f1 f2 f3 f4 +show slave status;; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 0 +Last_SQL_Error + +**************************************** +* columns in master at middle of table * +* Expect: Proper error message * +**************************************** + +** Stop and Reset Slave ** + +STOP SLAVE; +RESET SLAVE; + +** create table slave side ** +CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='NDB'; + +** Connect to master and create table ** + +CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', +c CHAR(5), e INT DEFAULT '1')ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT), +(2,@b1,DEFAULT,'JOE',DEFAULT), +(3,@b1,DEFAULT,'QA',DEFAULT); + +******************************************** +*** Expect slave to fail with Error 1523 *** +******************************************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1532 +Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1532 +Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +*** Drop t10 *** +DROP TABLE t10; + +********************************************* +* More columns in master at middle of table * +* Expect: Proper error message * +********************************************* + +*** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) +) ENGINE='NDB'; + +*** Create t11 on Master *** +CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT), +(2,@b1,'Testing is cool','JOE',DEFAULT), +(3,@b1,DEFAULT,'QA',DEFAULT); + +******************************************** +*** Expect slave to fail with Error 1523 *** +******************************************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1532 +Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1532 +Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +*** Drop t11 *** +DROP TABLE t11; + +********************************************* +* More columns in master at middle of table * +* Expect: This one should pass blob-text * +********************************************* + +*** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB +) ENGINE='NDB'; + +*** Create t12 on Master *** +CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',DEFAULT,DEFAULT), +(3,@b1,'QA',DEFAULT,DEFAULT); + +SELECT a,hex(b),f,c,e FROM t12 ORDER BY a; +a hex(b) f c e +1 62316231623162316231623162316231 Kyle test 1 +2 62316231623162316231623162316231 JOE test 1 +3 62316231623162316231623162316231 QA test 1 + +*** Select on Slave *** +SELECT a,hex(b),c FROM t12 ORDER BY a; +a hex(b) c +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA + +*** Drop t12 *** +DROP TABLE t12; + +**************************************************** +* - Alter Master adding columns at middle of table * +* Expect: columns added * +**************************************************** + + +*** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t14 on Master *** +CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; + +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle',DEFAULT,DEFAULT), +(2,2.00,'This Test Should work',@b1,'JOE',DEFAULT,DEFAULT), +(3,3.00,'If is does not, I will open a bug',@b1,'QA',DEFAULT,DEFAULT); + +SELECT c1,c2,c3,hex(c4),c5,c6,c7 FROM t14 ORDER BY c1; +c1 c2 c3 hex(c4) c5 c6 c7 +1 1.00 Replication Testing Extra Col 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work 62316231623162316231623162316231 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug 62316231623162316231623162316231 QA 1 CURRENT_TIMESTAMP + +*** Select on Slave **** +SELECT c1,c2,c3,hex(c4),c5 FROM t14 ORDER BY c1; +c1 c2 c3 hex(c4) c5 +1 1.00 Replication Testing Extra Col 62316231623162316231623162316231 Kyle +2 2.00 This Test Should work 62316231623162316231623162316231 JOE +3 3.00 If is does not, I will open a bug 62316231623162316231623162316231 QA + +**************************************************** +* - Alter Master Dropping columns from the middle. * +* Expect: columns dropped * +**************************************************** + +*** connect to master and drop columns *** +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c7; + +*** Select from Master *** +SELECT c1,c3,hex(c4),c5,c6 FROM t14 ORDER BY c1; +c1 c3 hex(c4) c5 c6 +1 Replication Testing Extra Col 62316231623162316231623162316231 Kyle 1 +2 This Test Should work 62316231623162316231623162316231 JOE 1 +3 If is does not, I will open a bug 62316231623162316231623162316231 QA 1 + +************ +* Bug30415 * +************ +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1091 +Last_Error Error 'Can't DROP 'c7'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t14 DROP COLUMN c7' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1091 +Last_SQL_Error Error 'Can't DROP 'c7'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t14 DROP COLUMN c7' +STOP SLAVE; +RESET SLAVE; + +*** Drop t14 *** +DROP TABLE t14; +DROP TABLE t14; +RESET MASTER; +START SLAVE; + +************************************************* +* - Alter Master adding columns at end of table * +* Expect: Error 1054 * +************************************************* + +*** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t15 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t15 on Master *** +CREATE TABLE t15 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT,3.00), +(2,@b1,'JOE',DEFAULT,DEFAULT,3.00), +(3,@b1,'QA',DEFAULT,DEFAULT,3.00); +SELECT c1,hex(c4),c5,c6,c7,c2 FROM t15 ORDER BY c1; +c1 hex(c4) c5 c6 c7 c2 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP 3.00 +2 62316231623162316231623162316231 JOE 1 CURRENT_TIMESTAMP 3.00 +3 62316231623162316231623162316231 QA 1 CURRENT_TIMESTAMP 3.00 + +******************************************** +*** Expect slave to fail with Error 1054 *** +******************************************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1054 +Last_Error Error 'Unknown column 'c7' in 't15'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1054 +Last_SQL_Error Error 'Unknown column 'c7' in 't15'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c2 DECIMAL(8,2) AFTER c7' +STOP SLAVE; +RESET SLAVE; + +*** Drop t15 *** +DROP TABLE t15; +DROP TABLE t15; +RESET MASTER; +START SLAVE; + +************************************************ +* - Create index on Master column not on slave * +* Expect:Warning * +************************************************ + +*** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t16 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t16 on Master *** +CREATE TABLE t16 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Create Index and Data Insert *** +CREATE INDEX part_of_c6 ON t16 (c6); +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',2,DEFAULT), +(3,@b1,'QA',3,DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t16 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +***************** +*** BUG 30434 *** +***************** + +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1072 +Last_Error Error 'Key column 'c6' doesn't exist in table' on query. Default database: 'test'. Query: 'CREATE INDEX part_of_c6 ON t16 (c6)' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 1072 +Last_SQL_Error Error 'Key column 'c6' doesn't exist in table' on query. Default database: 'test'. Query: 'CREATE INDEX part_of_c6 ON t16 (c6)' +STOP SLAVE; +RESET SLAVE; + +*** Drop t16 *** +DROP TABLE t16; +DROP TABLE t16; +RESET MASTER; +START SLAVE; + +***************************************************** +* - Delete rows using column on Master not on slave * +* Expect: Rows Deleted * +***************************************************** + +*** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t17 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t17 on Master *** +CREATE TABLE t17 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t17 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',2,DEFAULT), +(3,@b1,'QA',3,DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t17 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +** Select * from Slave ** +SELECT c1,hex(c4),c5 FROM t17 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA + +** Delete from master ** +DELETE FROM t17 WHERE c6 = 3; +SELECT c1,hex(c4),c5,c6,c7 FROM t17 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP + +** Check slave ** +SELECT c1,hex(c4),c5 FROM t17 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +DROP TABLE t17; + + +***************************************************** +* - Update row using column on Master not on slave * +* Expect: Rows updated * +***************************************************** + +** Bug30674 ** + +*** Create t18 on slave *** + +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t18 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t18 on Master *** +CREATE TABLE t18 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t18 () VALUES(1,@b1,'Kyle',DEFAULT,DEFAULT), +(2,@b1,'JOE',2,DEFAULT), +(3,@b1,'QA',3,DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t18 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +** Select * from Slave ** +SELECT c1,hex(c4),c5 FROM t18 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA + +** update from master ** +SELECT c1,hex(c4),c5,c6,c7 FROM t18 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 62316231623162316231623162316231 Kyle 1 CURRENT_TIMESTAMP +2 62316231623162316231623162316231 JOE 2 CURRENT_TIMESTAMP +3 62316231623162316231623162316231 QA 3 CURRENT_TIMESTAMP + +** Check slave ** +SELECT c1,hex(c4),c5 FROM t18 ORDER BY c1; +c1 hex(c4) c5 +1 62316231623162316231623162316231 Kyle +2 62316231623162316231623162316231 JOE +3 62316231623162316231623162316231 QA +DROP TABLE t18; + + +***************************************************** +* - Insert UUID column on Master not on slave * +* Expect: Rows inserted * +***************************************************** + +*** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t5 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; + +*** Create t5 on Master *** +CREATE TABLE t5 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 LONG, +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +RESET MASTER; + +*** Start Slave *** +START SLAVE; + +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +INSERT INTO t5 () VALUES(1,@b1,'Kyle',UUID(),DEFAULT), +(2,@b1,'JOE',UUID(),DEFAULT), +(3,@b1,'QA',UUID(),DEFAULT); +SELECT c1,hex(c4),c5,c6,c7 FROM t5 ORDER BY c1; +c1 hex(c4) c5 c6 c7 +1 6231623162316231 Kyle UUID TIME +2 6231623162316231 JOE UUID TIME +3 6231623162316231 QA UUID TIME + +** Select * from Slave ** +SELECT c1,hex(c4),c5 FROM t5 ORDER BY c1; +c1 hex(c4) c5 +1 6231623162316231 Kyle +2 6231623162316231 JOE +3 6231623162316231 QA +DROP TABLE t5; + diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_extraColMaster.test b/mysql-test/suite/rpl_ndb/t/rpl_ndb_extraColMaster.test new file mode 100644 index 00000000000..d78eda7eef1 --- /dev/null +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_extraColMaster.test @@ -0,0 +1,14 @@ +############################################################# +# Purpose: To test having extra columns on the master WL#3915 +############################################################# +-- source include/have_ndb.inc +-- source include/ndb_master-slave.inc +-- source include/have_binlog_format_mixed_or_row.inc + +let $engine_type = 'NDB'; + +set binlog_format=row; +-- source extra/rpl_tests/rpl_extraMaster_Col.test + +set binlog_format=mixed; +-- source extra/rpl_tests/rpl_extraMaster_Col.test From 3465c5bc586f3f3b37c7e7ec76b94d531b9c192e Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Thu, 11 Oct 2007 14:54:05 +0200 Subject: [PATCH 35/92] ndb - bug#31525 Fix bug regarding node that missed 2 LCP's (that was not included in next LCP after SR) --- storage/ndb/src/kernel/blocks/ERROR_codes.txt | 5 +- .../ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 4 + storage/ndb/test/ndbapi/testNodeRestart.cpp | 77 +++++++++++++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 4 + 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index abb1d858082..deea98fc3a6 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -5,7 +5,7 @@ Next DBACC 3002 Next DBTUP 4029 Next DBLQH 5045 Next DBDICT 6007 -Next DBDIH 7186 +Next DBDIH 7193 Next DBTC 8054 Next CMVMI 9000 Next BACKUP 10038 @@ -155,6 +155,9 @@ And crash when all have "not" been sent 7027: Crash in master when changing state to LCP_TAB_SAVED 7018: Crash in master when changing state to LCP_TAB_SAVED +7191: Crash when receiving LCP_COMPLETE_REP +7192: Crash in setLcpActiveStatusStart - when dead node missed to LCP's + ERROR CODES FOR TESTING NODE FAILURE, FAILURE IN COPY FRAGMENT PROCESS: ----------------------------------------------------------------------- diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index f4433b9d264..217c6f38ade 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -10853,6 +10853,8 @@ void Dbdih::execLCP_COMPLETE_REP(Signal* signal) { jamEntry(); + CRASH_INSERTION(7191); + #if 0 g_eventLogger.info("LCP_COMPLETE_REP"); printLCP_COMPLETE_REP(stdout, @@ -13603,6 +13605,7 @@ void Dbdih::setLcpActiveStatusStart(Signal* signal) // It must be taken over with the copy fragment process after a system // crash. We indicate this by setting the active status to TAKE_OVER. /*-------------------------------------------------------------------*/ + c_lcpState.m_participatingLQH.set(nodePtr.i); nodePtr.p->activeStatus = Sysfile::NS_TakeOver; //break; // Fall through case Sysfile::NS_TakeOver:{ @@ -13645,6 +13648,7 @@ void Dbdih::setLcpActiveStatusStart(Signal* signal) break; case Sysfile::NS_ActiveMissed_2: jam(); + CRASH_INSERTION(7192); if ((nodePtr.p->nodeStatus == NodeRecord::ALIVE) && (!nodePtr.p->copyCompleted)) { jam(); diff --git a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp index 66b9c6086da..4b80dd7aaef 100644 --- a/storage/ndb/test/ndbapi/testNodeRestart.cpp +++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp @@ -1668,6 +1668,80 @@ runBug28717(NDBT_Context* ctx, NDBT_Step* step) return NDBT_OK; } +int +runBug31525(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + Ndb* pNdb = GETNDB(step); + NdbRestarter res; + + if (res.getNumDbNodes() < 2) + { + return NDBT_OK; + } + + int nodes[2]; + nodes[0] = res.getMasterNodeId(); + nodes[1] = res.getNextMasterNodeId(nodes[0]); + + while (res.getNodeGroup(nodes[0]) != res.getNodeGroup(nodes[1])) + { + ndbout_c("Restarting %u as it not in same node group as %u", + nodes[1], nodes[0]); + if (res.restartOneDbNode(nodes[1], false, true, true)) + return NDBT_FAILED; + + if (res.waitNodesNoStart(nodes+1, 1)) + return NDBT_FAILED; + + if (res.startNodes(nodes+1, 1)) + return NDBT_FAILED; + + if (res.waitClusterStarted()) + return NDBT_FAILED; + + nodes[1] = res.getNextMasterNodeId(nodes[0]); + } + + ndbout_c("nodes[0]: %u nodes[1]: %u", nodes[0], nodes[1]); + + int val = DumpStateOrd::DihMinTimeBetweenLCP; + if (res.dumpStateAllNodes(&val, 1)) + return NDBT_FAILED; + + int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + if (res.dumpStateAllNodes(val2, 2)) + return NDBT_FAILED; + + if (res.insertErrorInAllNodes(932)) + return NDBT_FAILED; + + if (res.insertErrorInNode(nodes[1], 7192)) + return NDBT_FAILED; + + if (res.insertErrorInNode(nodes[0], 7191)) + return NDBT_FAILED; + + if (res.waitClusterNoStart()) + return NDBT_FAILED; + + if (res.startAll()) + return NDBT_FAILED; + + if (res.waitClusterStarted()) + return NDBT_FAILED; + + if (res.restartOneDbNode(nodes[1], false, false, true)) + return NDBT_FAILED; + + if (res.waitClusterStarted()) + return NDBT_FAILED; + + return NDBT_OK; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", "Test that one node at a time can be stopped and then restarted "\ @@ -1991,6 +2065,9 @@ TESTCASE("Bug21271", STEP(runPkUpdateUntilStopped); FINALIZER(runClearTable); } +TESTCASE("Bug31525", ""){ + INITIALIZER(runBug31525); +} TESTCASE("Bug24717", ""){ INITIALIZER(runBug24717); } diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 2c654a13bcf..da588430e80 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -934,3 +934,7 @@ max-time: 1500 cmd: testSystemRestart args: -n SR_DD_2b_LCP D2 +max-time: 600 +cmd: testNodeRestart +args: -n Bug31525 T1 + From 9326e82027aea558afb679df7969804073e90d05 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Thu, 11 Oct 2007 15:28:10 +0200 Subject: [PATCH 36/92] ndb - decrease test time --- storage/ndb/test/run-test/daily-basic-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 4e937ee8933..fd8faf959ae 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -555,7 +555,7 @@ args: -n Bug25554 T1 max-time: 3000 cmd: testNodeRestart -args: -n Bug25984 +args: -n Bug25984 T1 max-time: 1000 cmd: testNodeRestart From f178f7258d34ad138b854ab37eb4cf21eeff8ad4 Mon Sep 17 00:00:00 2001 From: "mtaylor@solace.(none)" <> Date: Thu, 11 Oct 2007 23:46:25 -0700 Subject: [PATCH 37/92] Fixed header to reflect the implementation. Added accessor method to help out the NDB/Connectors. --- storage/ndb/include/ndbapi/NdbOperation.hpp | 3 +++ storage/ndb/include/ndbapi/NdbPool.hpp | 3 ++- storage/ndb/include/ndbapi/NdbScanFilter.hpp | 1 + storage/ndb/include/ndbapi/NdbTransaction.hpp | 7 +++++++ storage/ndb/src/ndbapi/NdbOperation.cpp | 6 ++++++ storage/ndb/src/ndbapi/NdbScanFilter.cpp | 4 ++++ 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 06111941df4..063b414e520 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -842,6 +842,9 @@ protected: virtual ~NdbOperation(); void next(NdbOperation*); // Set next pointer NdbOperation* next(); // Get next pointer + + NdbTransation* getNdbTransaction(); + public: #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL const NdbOperation* next() const; diff --git a/storage/ndb/include/ndbapi/NdbPool.hpp b/storage/ndb/include/ndbapi/NdbPool.hpp index 1963bf26448..44b6d7488f0 100644 --- a/storage/ndb/include/ndbapi/NdbPool.hpp +++ b/storage/ndb/include/ndbapi/NdbPool.hpp @@ -17,7 +17,8 @@ class Ndb; class NdbPool; bool -create_instance(Uint32 max_ndb_objects, +create_instance(Ndb_cluster_connection* cc, + Uint32 max_ndb_objects, Uint32 no_conn_obj, Uint32 init_no_ndb_objects); diff --git a/storage/ndb/include/ndbapi/NdbScanFilter.hpp b/storage/ndb/include/ndbapi/NdbScanFilter.hpp index 02fcb6215ba..35cbccedfe5 100644 --- a/storage/ndb/include/ndbapi/NdbScanFilter.hpp +++ b/storage/ndb/include/ndbapi/NdbScanFilter.hpp @@ -191,6 +191,7 @@ public: */ const class NdbError & getNdbError() const; + NdbOperation * getNdbOperation(); private: #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL friend class NdbScanFilterImpl; diff --git a/storage/ndb/include/ndbapi/NdbTransaction.hpp b/storage/ndb/include/ndbapi/NdbTransaction.hpp index 20c9c709e51..7a06b182647 100644 --- a/storage/ndb/include/ndbapi/NdbTransaction.hpp +++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp @@ -170,6 +170,13 @@ public: #endif }; + /** + * Convenience method to fetch this transactions Ndb* object + */ + Ndb * getNdb() { + return theNdb; + } + #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED /** * Get an NdbOperation for a table. diff --git a/storage/ndb/src/ndbapi/NdbOperation.cpp b/storage/ndb/src/ndbapi/NdbOperation.cpp index 50531292e40..ddaf5d0b233 100644 --- a/storage/ndb/src/ndbapi/NdbOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbOperation.cpp @@ -429,3 +429,9 @@ NdbOperation::getTable() const { return m_currentTable; } + +NdbTransaction* +NdbOperation::getNdbTransaction() +{ + return theNdbCon; +} diff --git a/storage/ndb/src/ndbapi/NdbScanFilter.cpp b/storage/ndb/src/ndbapi/NdbScanFilter.cpp index 624122b5c55..4c052110040 100644 --- a/storage/ndb/src/ndbapi/NdbScanFilter.cpp +++ b/storage/ndb/src/ndbapi/NdbScanFilter.cpp @@ -348,6 +348,10 @@ NdbScanFilter::isfalse(){ return 0; } +NdbOperation * +NdbScanFilter::getNdbOperation(){ + return m_impl.m_operation; +} #define action(x, y, z) From 04342a487b6a9f2a0a00b98a6526b45240dadd11 Mon Sep 17 00:00:00 2001 From: "mtaylor@solace.(none)" <> Date: Fri, 12 Oct 2007 00:10:07 -0700 Subject: [PATCH 38/92] Added SKIP_INTERNAL wrappers to mark new methods as not part of the public API. --- storage/ndb/include/ndbapi/NdbOperation.hpp | 3 +-- storage/ndb/include/ndbapi/NdbScanFilter.hpp | 3 ++- storage/ndb/include/ndbapi/NdbTransaction.hpp | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 063b414e520..9b528ef4949 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -843,10 +843,9 @@ protected: void next(NdbOperation*); // Set next pointer NdbOperation* next(); // Get next pointer - NdbTransation* getNdbTransaction(); - public: #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + NdbTransation* getNdbTransaction(); const NdbOperation* next() const; const NdbRecAttr* getFirstRecAttr() const; #endif diff --git a/storage/ndb/include/ndbapi/NdbScanFilter.hpp b/storage/ndb/include/ndbapi/NdbScanFilter.hpp index 35cbccedfe5..4527012a6c4 100644 --- a/storage/ndb/include/ndbapi/NdbScanFilter.hpp +++ b/storage/ndb/include/ndbapi/NdbScanFilter.hpp @@ -190,8 +190,9 @@ public: * immediately. */ const class NdbError & getNdbError() const; - +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL NdbOperation * getNdbOperation(); +#endif private: #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL friend class NdbScanFilterImpl; diff --git a/storage/ndb/include/ndbapi/NdbTransaction.hpp b/storage/ndb/include/ndbapi/NdbTransaction.hpp index 7a06b182647..6a057655398 100644 --- a/storage/ndb/include/ndbapi/NdbTransaction.hpp +++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp @@ -170,12 +170,14 @@ public: #endif }; +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL /** - * Convenience method to fetch this transactions Ndb* object + * Convenience method to fetch this transaction's Ndb* object */ Ndb * getNdb() { return theNdb; } +#endif #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED /** From 2a595c1bc1d55fe2adec6c47f89f00ab6df47fa8 Mon Sep 17 00:00:00 2001 From: "mtaylor@solace.(none)" <> Date: Fri, 12 Oct 2007 01:16:55 -0700 Subject: [PATCH 39/92] Fixed a typo. We have NdbTransactions not NdbTransations. --- storage/ndb/include/ndbapi/NdbOperation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 9b528ef4949..2f899d5b4bd 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -845,7 +845,7 @@ protected: public: #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - NdbTransation* getNdbTransaction(); + NdbTransaction* getNdbTransaction(); const NdbOperation* next() const; const NdbRecAttr* getFirstRecAttr() const; #endif From 596166688651a04fd0849687b22b65acfbe68ba6 Mon Sep 17 00:00:00 2001 From: "pekka@sama.ndb.mysql.com" <> Date: Sun, 14 Oct 2007 16:17:39 +0200 Subject: [PATCH 40/92] ndb - bug#29390: fix mem leak introduced in previous cset --- ndb/src/ndbapi/NdbScanFilter.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp index 624122b5c55..58e9f180119 100644 --- a/ndb/src/ndbapi/NdbScanFilter.cpp +++ b/ndb/src/ndbapi/NdbScanFilter.cpp @@ -22,6 +22,7 @@ #include #include #include "NdbApiSignal.hpp" +#include "NdbUtil.hpp" #ifdef VM_TRACE #include @@ -621,12 +622,43 @@ NdbScanFilterImpl::handle_filter_too_large() op->theStatus = m_initial_op_status; // reset interpreter state to initial + + NdbBranch* tBranch = op->theFirstBranch; + while (tBranch != NULL) { + NdbBranch* tmp = tBranch; + tBranch = tBranch->theNext; + op->theNdb->releaseNdbBranch(tmp); + } op->theFirstBranch = NULL; op->theLastBranch = NULL; + + NdbLabel* tLabel = op->theFirstLabel; + while (tLabel != NULL) { + NdbLabel* tmp = tLabel; + tLabel = tLabel->theNext; + op->theNdb->releaseNdbLabel(tmp); + } + op->theFirstLabel = NULL; + op->theLastLabel = NULL; + + NdbCall* tCall = op->theFirstCall; + while (tCall != NULL) { + NdbCall* tmp = tCall; + tCall = tCall->theNext; + op->theNdb->releaseNdbCall(tmp); + } op->theFirstCall = NULL; op->theLastCall = NULL; + + NdbSubroutine* tSubroutine = op->theFirstSubroutine; + while (tSubroutine != NULL) { + NdbSubroutine* tmp = tSubroutine; + tSubroutine = tSubroutine->theNext; + op->theNdb->releaseNdbSubroutine(tmp); + } op->theFirstSubroutine = NULL; op->theLastSubroutine = NULL; + op->theNoOfLabels = 0; op->theNoOfSubroutines = 0; From f28e73ae4c32accb0996bed72801bb993b120701 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Sun, 14 Oct 2007 18:42:49 +0200 Subject: [PATCH 41/92] ndb - testScan -n InsertDelete fix testcase --- storage/ndb/test/ndbapi/testScan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ndb/test/ndbapi/testScan.cpp b/storage/ndb/test/ndbapi/testScan.cpp index 2561869fa5f..df6dbe2e550 100644 --- a/storage/ndb/test/ndbapi/testScan.cpp +++ b/storage/ndb/test/ndbapi/testScan.cpp @@ -579,7 +579,7 @@ int runScanUpdateUntilStopped(NDBT_Context* ctx, NDBT_Step* step){ para = myRandom48(239)+1; g_info << i << ": "; - if (hugoTrans.scanUpdateRecords(GETNDB(step), records, 0, para) == NDBT_FAILED){ + if (hugoTrans.scanUpdateRecords(GETNDB(step), 0, 0, para) == NDBT_FAILED){ return NDBT_FAILED; } i++; From 5aacf8b775adb8ec85313099a14e3a3371740285 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 15 Oct 2007 09:10:14 +0200 Subject: [PATCH 42/92] ndb - bug#31482 (re)impl. simple-read (read that releases lock just before LQHKEYCONF) use simple-read for blobs --- .../include/kernel/signaldata/TcKeyConf.hpp | 2 +- storage/ndb/include/ndbapi/NdbOperation.hpp | 3 +- .../common/debugger/signaldata/TcKeyConf.cpp | 4 +- storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp | 1 - .../ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 76 ++++--- storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp | 12 +- .../ndb/src/kernel/blocks/dbtc/DbtcMain.cpp | 199 ++++++++++-------- storage/ndb/src/ndbapi/NdbBlob.cpp | 2 +- storage/ndb/src/ndbapi/NdbIndexOperation.cpp | 3 + storage/ndb/src/ndbapi/NdbOperationDefine.cpp | 62 +++--- storage/ndb/src/ndbapi/NdbOperationExec.cpp | 17 +- storage/ndb/src/ndbapi/NdbReceiver.cpp | 2 +- storage/ndb/src/ndbapi/NdbScanOperation.cpp | 1 + storage/ndb/src/ndbapi/NdbTransaction.cpp | 6 +- storage/ndb/test/ndbapi/testBasic.cpp | 35 ++- .../ndb/test/run-test/daily-basic-tests.txt | 8 + storage/ndb/test/src/HugoOperations.cpp | 1 + 17 files changed, 236 insertions(+), 198 deletions(-) diff --git a/storage/ndb/include/kernel/signaldata/TcKeyConf.hpp b/storage/ndb/include/kernel/signaldata/TcKeyConf.hpp index b8562875ef5..fd8932c3c87 100644 --- a/storage/ndb/include/kernel/signaldata/TcKeyConf.hpp +++ b/storage/ndb/include/kernel/signaldata/TcKeyConf.hpp @@ -46,7 +46,7 @@ public: */ STATIC_CONST( StaticLength = 5 ); STATIC_CONST( OperationLength = 2 ); - STATIC_CONST( SimpleReadBit = (((Uint32)1) << 31) ); + STATIC_CONST( DirtyReadBit = (((Uint32)1) << 31) ); private: diff --git a/storage/ndb/include/ndbapi/NdbOperation.hpp b/storage/ndb/include/ndbapi/NdbOperation.hpp index 06111941df4..a927df521a9 100644 --- a/storage/ndb/include/ndbapi/NdbOperation.hpp +++ b/storage/ndb/include/ndbapi/NdbOperation.hpp @@ -93,8 +93,9 @@ public: ,LM_CommittedRead ///< Ignore locks, read last committed value #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL = 2, - LM_Dirty = 2 + LM_Dirty = 2, #endif + LM_SimpleRead = 3 ///< Read with shared lock, but release lock directly }; /** diff --git a/storage/ndb/src/common/debugger/signaldata/TcKeyConf.cpp b/storage/ndb/src/common/debugger/signaldata/TcKeyConf.cpp index 65589f8cd6e..377863f9446 100644 --- a/storage/ndb/src/common/debugger/signaldata/TcKeyConf.cpp +++ b/storage/ndb/src/common/debugger/signaldata/TcKeyConf.cpp @@ -51,11 +51,11 @@ printTCKEYCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receive (TcKeyConf::getMarkerFlag(confInfo) == 0)?"false":"true"); fprintf(output, "Operations:\n"); for(i = 0; i < noOfOp; i++) { - if(sig->operations[i].attrInfoLen > TcKeyConf::SimpleReadBit) + if(sig->operations[i].attrInfoLen > TcKeyConf::DirtyReadBit) fprintf(output, " apiOperationPtr: H'%.8x, simplereadnode: %u\n", sig->operations[i].apiOperationPtr, - sig->operations[i].attrInfoLen & (~TcKeyConf::SimpleReadBit)); + sig->operations[i].attrInfoLen & (~TcKeyConf::DirtyReadBit)); else fprintf(output, " apiOperationPtr: H'%.8x, attrInfoLen: %u\n", diff --git a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 6f8e5569831..1bed25fb5a8 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -2025,7 +2025,6 @@ public: Uint8 reclenAiLqhkey; Uint8 m_offset_current_keybuf; Uint8 replicaType; - Uint8 simpleRead; Uint8 seqNoReplica; Uint8 tcNodeFailrec; Uint8 m_disk_table; diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 43d49e791be..f511e00afaa 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3496,7 +3496,6 @@ void Dblqh::execLQHKEYREQ(Signal* signal) regTcPtr->dirtyOp = LqhKeyReq::getDirtyFlag(Treqinfo); regTcPtr->opExec = LqhKeyReq::getInterpretedFlag(Treqinfo); regTcPtr->opSimple = LqhKeyReq::getSimpleFlag(Treqinfo); - regTcPtr->simpleRead = op == ZREAD && regTcPtr->opSimple; regTcPtr->seqNoReplica = LqhKeyReq::getSeqNoReplica(Treqinfo); UintR TreclenAiLqhkey = LqhKeyReq::getAIInLqhKeyReq(Treqinfo); regTcPtr->apiVersionNo = 0; @@ -3513,9 +3512,15 @@ void Dblqh::execLQHKEYREQ(Signal* signal) regTcPtr->lockType = op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op; } + + if (regTcPtr->dirtyOp) + { + ndbrequire(regTcPtr->opSimple); + } - CRASH_INSERTION2(5041, regTcPtr->simpleRead && - refToNode(signal->senderBlockRef()) != cownNodeid); + CRASH_INSERTION2(5041, (op == ZREAD && + (regTcPtr->opSimple || regTcPtr->dirtyOp) && + refToNode(signal->senderBlockRef()) != cownNodeid)); regTcPtr->reclenAiLqhkey = TreclenAiLqhkey; regTcPtr->currReclenAi = TreclenAiLqhkey; @@ -3687,8 +3692,8 @@ void Dblqh::execLQHKEYREQ(Signal* signal) Uint8 TdistKey = LqhKeyReq::getDistributionKey(TtotReclenAi); if ((tfragDistKey != TdistKey) && (regTcPtr->seqNoReplica == 0) && - (regTcPtr->dirtyOp == ZFALSE) && - (regTcPtr->simpleRead == ZFALSE)) { + (regTcPtr->dirtyOp == ZFALSE)) + { /* ---------------------------------------------------------------------- * WE HAVE DIFFERENT OPINION THAN THE DIH THAT STARTED THE TRANSACTION. * THE REASON COULD BE THAT THIS IS AN OLD DISTRIBUTION WHICH IS NO LONGER @@ -4778,7 +4783,18 @@ void Dblqh::tupkeyConfLab(Signal* signal) TRACE_OP(regTcPtr, "TUPKEYCONF"); - if (regTcPtr->simpleRead) { + if (readLen != 0) + { + jam(); + + /* SET BIT 15 IN REQINFO */ + LqhKeyReq::setApplicationAddressFlag(regTcPtr->reqinfo, 1); + regTcPtr->readlenAi = readLen; + }//if + + if (regTcPtr->operation == ZREAD && + (regTcPtr->opSimple || regTcPtr->dirtyOp)) + { jam(); /* ---------------------------------------------------------------------- * THE OPERATION IS A SIMPLE READ. @@ -4792,14 +4808,6 @@ void Dblqh::tupkeyConfLab(Signal* signal) commitContinueAfterBlockedLab(signal); return; }//if - if (readLen != 0) - { - jam(); - - /* SET BIT 15 IN REQINFO */ - LqhKeyReq::setApplicationAddressFlag(regTcPtr->reqinfo, 1); - regTcPtr->readlenAi = readLen; - }//if regTcPtr->totSendlenAi = writeLen; ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen); @@ -5178,12 +5186,15 @@ void Dblqh::packLqhkeyreqLab(Signal* signal) /* */ /* ------------------------------------------------------------------------- */ sendLqhkeyconfTc(signal, regTcPtr->tcBlockref); - if (regTcPtr->dirtyOp != ZTRUE) { + if (! (regTcPtr->dirtyOp || + (regTcPtr->operation == ZREAD && regTcPtr->opSimple))) + { jam(); regTcPtr->transactionState = TcConnectionrec::PREPARED; releaseOprec(signal); } else { jam(); + /*************************************************************>*/ /* DIRTY WRITES ARE USED IN TWO SITUATIONS. THE FIRST */ /* SITUATION IS WHEN THEY ARE USED TO UPDATE COUNTERS AND*/ @@ -6406,8 +6417,8 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal) Ptr regTcPtr = tcConnectptr; Ptr regFragptr = fragptr; Uint32 operation = regTcPtr.p->operation; - Uint32 simpleRead = regTcPtr.p->simpleRead; Uint32 dirtyOp = regTcPtr.p->dirtyOp; + Uint32 opSimple = regTcPtr.p->opSimple; if (regTcPtr.p->activeCreat != Fragrecord::AC_IGNORED) { if (operation != ZREAD) { TupCommitReq * const tupCommitReq = @@ -6465,20 +6476,29 @@ void Dblqh::commitContinueAfterBlockedLab(Signal* signal) EXECUTE_DIRECT(acc, GSN_ACC_COMMITREQ, signal, 1); } - if (simpleRead) { + if (dirtyOp) + { jam(); -/* ------------------------------------------------------------------------- */ -/*THE OPERATION WAS A SIMPLE READ THUS THE COMMIT PHASE IS ONLY NEEDED TO */ -/*RELEASE THE LOCKS. AT THIS POINT IN THE CODE THE LOCKS ARE RELEASED AND WE */ -/*ARE IN A POSITION TO SEND LQHKEYCONF TO TC. WE WILL ALSO RELEASE ALL */ -/*RESOURCES BELONGING TO THIS OPERATION SINCE NO MORE WORK WILL BE */ -/*PERFORMED. */ -/* ------------------------------------------------------------------------- */ + /** + * The dirtyRead does not send anything but TRANSID_AI from LDM + */ fragptr = regFragptr; tcConnectptr = regTcPtr; cleanUp(signal); return; - }//if + } + + /** + * The simpleRead will send a LQHKEYCONF + * but have already released the locks + */ + if (opSimple) + { + fragptr = regFragptr; + tcConnectptr = regTcPtr; + packLqhkeyreqLab(signal); + return; + } } }//if jamEntry(); @@ -7088,7 +7108,7 @@ void Dblqh::abortStateHandlerLab(Signal* signal) /* ------------------------------------------------------------------------- */ return; }//if - if (regTcPtr->simpleRead) { + if (regTcPtr->opSimple) { jam(); /* ------------------------------------------------------------------------- */ /*A SIMPLE READ IS CURRENTLY RELEASING THE LOCKS OR WAITING FOR ACCESS TO */ @@ -7356,7 +7376,8 @@ void Dblqh::continueAbortLab(Signal* signal) void Dblqh::continueAfterLogAbortWriteLab(Signal* signal) { TcConnectionrec * const regTcPtr = tcConnectptr.p; - if (regTcPtr->simpleRead) { + if (regTcPtr->operation == ZREAD && regTcPtr->dirtyOp) + { jam(); TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend(); @@ -19027,7 +19048,6 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal) ndbout << " operation = " << tcRec.p->operation<getProperty("LockMode", NdbOperation::LM_Read); int i = 0; HugoTransactions hugoTrans(*ctx->getTab()); while (igetNumLoops(); - int records = ctx->getNumRecords(); - int batchSize = ctx->getProperty("BatchSize", 1); - int i = 0; - bool dirty = true; - HugoTransactions hugoTrans(*ctx->getTab()); - while (igetType() == NdbDictionary::Index::OrderedIndex && pIndexScanOp == 0) { From 69cce99bb62cc65f593a2cbf83704e662d365b02 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Mon, 15 Oct 2007 09:17:15 +0200 Subject: [PATCH 43/92] ndb - reenable disabled testcases ndb_load ndb_dd_sql_features --- mysql-test/suite/ndb/t/disabled.def | 3 --- 1 file changed, 3 deletions(-) diff --git a/mysql-test/suite/ndb/t/disabled.def b/mysql-test/suite/ndb/t/disabled.def index 9c2dc80d5ee..f876039a042 100644 --- a/mysql-test/suite/ndb/t/disabled.def +++ b/mysql-test/suite/ndb/t/disabled.def @@ -9,9 +9,6 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -ndb_dd_sql_features : Bug#29102 ndb_dd_sql_features fails in pushbuild -ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed - partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table ndb_partition_error2 : HF is not sure if the test can work as internded on all the platforms From 5cf8e94bf86bb35e803c303a1ac543ad0992b607 Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Thu, 18 Oct 2007 23:21:18 +0200 Subject: [PATCH 44/92] ndb - bug#31701 Node failure with repl. wo/ load, can lead to endless out of order buckets Correct check for buffer/no buffer --- storage/ndb/src/kernel/blocks/ERROR_codes.txt | 2 +- storage/ndb/src/kernel/blocks/suma/Suma.cpp | 6 +- storage/ndb/test/ndbapi/test_event.cpp | 88 +++++++++++++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 4 + 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index deea98fc3a6..b58eeb730f3 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -11,7 +11,7 @@ Next CMVMI 9000 Next BACKUP 10038 Next DBUTIL 11002 Next DBTUX 12008 -Next SUMA 13001 +Next SUMA 13034 TESTING NODE FAILURE, ARBITRATION --------------------------------- diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp index 717448ca03b..94df9a2b32e 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp @@ -3650,6 +3650,8 @@ Suma::execSUB_GCP_COMPLETE_REP(Signal* signal) if(m_gcp_complete_rep_count && !c_subscriber_nodes.isclear()) { + CRASH_INSERTION(13033); + NodeReceiverGroup rg(API_CLUSTERMGR, c_subscriber_nodes); sendSignal(rg, GSN_SUB_GCP_COMPLETE_REP, signal, SubGcpCompleteRep::SignalLength, JBB); @@ -3669,8 +3671,8 @@ Suma::execSUB_GCP_COMPLETE_REP(Signal* signal) { if(m_active_buckets.get(i)) continue; - - if(c_buckets[i].m_buffer_tail != RNIL) + + if (!c_subscriber_nodes.isclear()) { //Uint32* dst; get_buffer_ptr(signal, i, gci, 0); diff --git a/storage/ndb/test/ndbapi/test_event.cpp b/storage/ndb/test/ndbapi/test_event.cpp index 2083e235a3e..18825d734a4 100644 --- a/storage/ndb/test/ndbapi/test_event.cpp +++ b/storage/ndb/test/ndbapi/test_event.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb() @@ -1758,6 +1759,85 @@ runInsertDeleteUntilStopped(NDBT_Context* ctx, NDBT_Step* step) return NDBT_OK; } +int +runBug31701(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + + NdbRestarter restarter; + + if (restarter.getNumDbNodes() < 2){ + ctx->stopTest(); + return NDBT_OK; + } + // This should really wait for applier to start...10s is likely enough + NdbSleep_SecSleep(10); + + int nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes()); + + int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 }; + if (restarter.dumpStateOneNode(nodeId, val2, 2)) + return NDBT_FAILED; + + restarter.insertErrorInNode(nodeId, 13033); + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitClusterStarted()) + return NDBT_FAILED; + + + int records = ctx->getNumRecords(); + HugoTransactions hugoTrans(*ctx->getTab()); + + if(ctx->getPropertyWait("LastGCI", ~(Uint32)0)) + { + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + + hugoTrans.clearTable(GETNDB(step), 0); + + if (hugoTrans.loadTable(GETNDB(step), 3*records, 1, true, 1) != 0){ + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + + if (hugoTrans.pkDelRecords(GETNDB(step), 3*records, 1, true, 1) != 0){ + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + if (hugoTrans.loadTable(GETNDB(step), records, 1, true, 1) != 0){ + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){ + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){ + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + if (hugoTrans.pkUpdateRecords(GETNDB(step), records, 1, 1) != 0){ + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + + ctx->setProperty("LastGCI", hugoTrans.m_latest_gci); + if(ctx->getPropertyWait("LastGCI", ~(Uint32)0)) + { + g_err << "FAIL " << __LINE__ << endl; + return NDBT_FAILED; + } + + ctx->stopTest(); + return NDBT_OK; +} + NDBT_TESTSUITE(test_event); TESTCASE("BasicEventOperation", "Verify that we can listen to Events" @@ -1887,6 +1967,14 @@ TESTCASE("Bug27169", ""){ STEP(runRestarterLoop); FINALIZER(runDropEvent); } +TESTCASE("Bug31701", ""){ + INITIALIZER(runCreateEvent); + INITIALIZER(runCreateShadowTable); + STEP(runEventApplier); + STEP(runBug31701); + FINALIZER(runDropEvent); + FINALIZER(runDropShadowTable); +} NDBT_TESTSUITE_END(test_event); int main(int argc, const char** argv){ diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index da588430e80..ef5082ca30c 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -938,3 +938,7 @@ max-time: 600 cmd: testNodeRestart args: -n Bug31525 T1 +max-time: 300 +cmd: test_event +args: -n Bug31701 T1 + From c60397ef1988ed1286a4d99dc2b9f9216c5dd98b Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Fri, 19 Oct 2007 19:57:08 +0400 Subject: [PATCH 45/92] Patch for BUG#31111: --read-only crashes MySQL (events fail to load). There actually were several problems here: - WRITE-lock is required to load events from the mysql.event table, but in the read-only mode an ordinary user can not acquire it; - Security_context::master_access attribute was not properly initialized in Security_context::init(), which led to differences in behavior with and without debug configure options. - if the server failed to load events from mysql.event, it forgot to close the mysql.event table, that led to the coredump, described in the bug report. The patch is to fix all these problems: - Use the super-user to acquire WRITE-lock on the mysql.even table; - The WRITE-lock is acquired by the event scheduler in two cases: - on initial loading of events from the database; - when an event has been executed, so its attributes should be updated. Other cases when WRITE-lock is needed for the mysql.event table happen under the user account. So, nothing should be changed there for the read-only mode. The user is able to create/update/drop an event only if he is a super-user. - Initialize Security_context::master_access; - Close the mysql.event table in case something went wrong. --- mysql-test/r/events_bugs.result | 103 ++++++++++++++- mysql-test/t/events_bugs.test | 224 ++++++++++++++++++++++++++++++-- sql/event_data_objects.cc | 16 ++- sql/event_db_repository.cc | 9 ++ sql/event_scheduler.cc | 7 + sql/events.cc | 16 ++- sql/sql_class.cc | 1 + 7 files changed, 360 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index 3c9e6384c64..b6b77101874 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -610,7 +610,6 @@ id ev_nm ev_cnt 6 ev_sched_1823 6 DROP TABLE event_log; SET GLOBAL event_scheduler = OFF; -DROP DATABASE events_test; SET GLOBAL event_scheduler= ON; CREATE EVENT bug28641 ON SCHEDULE AT '2038.01.18 03:00:00' DO BEGIN @@ -618,3 +617,105 @@ SELECT 1; END;| SET GLOBAL event_scheduler= OFF; DROP EVENT bug28641; + +##################################################################### +# +# BUG#31111: --read-only crashes MySQL (events fail to load). +# +##################################################################### + +DROP USER mysqltest_u1@localhost; +DROP EVENT IF EXISTS e1; +DROP EVENT IF EXISTS e2; + +GRANT EVENT ON *.* TO mysqltest_u1@localhost; + +SET GLOBAL READ_ONLY = 1; + +# +# Connection: u1_con (mysqltest_u1@localhost/events_test). +# + +CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement + +ALTER EVENT e1 COMMENT 'comment'; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement + +DROP EVENT e1; +ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement + +# +# Connection: root_con (root@localhost/events_test). +# + +CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1; + +ALTER EVENT e1 COMMENT 'comment'; + +DROP EVENT e1; + +SET GLOBAL READ_ONLY = 0; + +# +# Connection: u1_con (mysqltest_u1@localhost/test). +# + +CREATE EVENT e1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND DO SET @a = 1; +CREATE EVENT e2 ON SCHEDULE EVERY 1 SECOND DO SET @a = 1; + +SELECT +event_name, +last_executed IS NULL, +definer +FROM INFORMATION_SCHEMA.EVENTS +WHERE event_schema = 'events_test'; +event_name last_executed IS NULL definer +e1 1 mysqltest_u1@localhost +e2 1 mysqltest_u1@localhost + +# +# Connection: root_con (root@localhost/events_test). +# + +SET GLOBAL READ_ONLY = 1; + +SET GLOBAL EVENT_SCHEDULER = ON; + +# Waiting for the event scheduler to execute and drop event e1... + +# Waiting for the event scheduler to execute and update event e2... + +SET GLOBAL EVENT_SCHEDULER = OFF; + +SELECT +event_name, +last_executed IS NULL, +definer +FROM INFORMATION_SCHEMA.EVENTS +WHERE event_schema = 'events_test'; +event_name last_executed IS NULL definer +e2 0 mysqltest_u1@localhost + +DROP EVENT e1; +ERROR HY000: Unknown event 'e1' + +# Cleanup. + +DROP EVENT e2; + +SET GLOBAL READ_ONLY = 0; + +# +# Connection: default +# + +DROP USER mysqltest_u1@localhost; + +##################################################################### +# +# End of BUG#31111. +# +##################################################################### + +DROP DATABASE events_test; diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index 36052fdb9af..ebd86f3a3d2 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -712,18 +712,6 @@ DROP TABLE event_log; #DROP DATABASE ev_db_1; SET GLOBAL event_scheduler = OFF; -# -# End of tests -# - -let $wait_condition= - select count(*) = 0 from information_schema.processlist - where db='events_test' and command = 'Connect' and user=current_user(); ---source include/wait_condition.inc - -DROP DATABASE events_test; - - # # Bug#28641 CREATE EVENT with '2038.01.18 03:00:00' let server crash. # @@ -737,3 +725,215 @@ CREATE EVENT bug28641 ON SCHEDULE AT '2038.01.18 03:00:00' DELIMITER ;| SET GLOBAL event_scheduler= OFF; DROP EVENT bug28641; + +########################################################################### + +--echo +--echo ##################################################################### +--echo # +--echo # BUG#31111: --read-only crashes MySQL (events fail to load). +--echo # +--echo ##################################################################### +--echo + +--error 0,ER_CANNOT_USER +DROP USER mysqltest_u1@localhost; + +--disable_warnings +DROP EVENT IF EXISTS e1; +DROP EVENT IF EXISTS e2; +--enable_warnings + +--echo + +# Check that an ordinary user can not create/update/drop events in the +# read-only mode. + +GRANT EVENT ON *.* TO mysqltest_u1@localhost; + +--echo + +SET GLOBAL READ_ONLY = 1; + +--echo + +--echo # +--echo # Connection: u1_con (mysqltest_u1@localhost/events_test). +--echo # + +--connect(u1_con,localhost,mysqltest_u1,,events_test) + +--echo + +--error ER_OPTION_PREVENTS_STATEMENT +CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1; + +--echo + +--error ER_OPTION_PREVENTS_STATEMENT +ALTER EVENT e1 COMMENT 'comment'; + +--echo + +--error ER_OPTION_PREVENTS_STATEMENT +DROP EVENT e1; + +--echo + +# Check that the super user still can create/update/drop events. + +--echo # +--echo # Connection: root_con (root@localhost/events_test). +--echo # + +--connect(root_con,localhost,root,,events_test) + +--echo + +CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1; + +--echo + +ALTER EVENT e1 COMMENT 'comment'; + +--echo + +DROP EVENT e1; + +--echo + +# +# Switch to read-write mode; create test events under the user mysqltest_u1; +# switch back to read-only mode. +# + +SET GLOBAL READ_ONLY = 0; + +--echo + +--echo # +--echo # Connection: u1_con (mysqltest_u1@localhost/test). +--echo # + +--connection u1_con + +--echo + +CREATE EVENT e1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND DO SET @a = 1; +CREATE EVENT e2 ON SCHEDULE EVERY 1 SECOND DO SET @a = 1; + +--echo + +SELECT + event_name, + last_executed IS NULL, + definer +FROM INFORMATION_SCHEMA.EVENTS +WHERE event_schema = 'events_test'; + +--echo + +--echo # +--echo # Connection: root_con (root@localhost/events_test). +--echo # + +--connection root_con + +--echo + +SET GLOBAL READ_ONLY = 1; + +# Check that the event scheduler is able to update event. + +--echo + +SET GLOBAL EVENT_SCHEDULER = ON; + +--echo + +--echo # Waiting for the event scheduler to execute and drop event e1... + +let $wait_timeout = 2; +let $wait_condition = + SELECT COUNT(*) = 0 + FROM INFORMATION_SCHEMA.EVENTS + WHERE event_schema = 'events_test' AND event_name = 'e1'; +--source include/wait_condition.inc + +--echo + +--echo # Waiting for the event scheduler to execute and update event e2... + +let $wait_condition = + SELECT last_executed IS NOT NULL + FROM INFORMATION_SCHEMA.EVENTS + WHERE event_schema = 'events_test' AND event_name = 'e2'; +--source include/wait_condition.inc + +--echo + +SET GLOBAL EVENT_SCHEDULER = OFF; + +--echo + +SELECT + event_name, + last_executed IS NULL, + definer +FROM INFORMATION_SCHEMA.EVENTS +WHERE event_schema = 'events_test'; + +--echo + +--error ER_EVENT_DOES_NOT_EXIST +DROP EVENT e1; + +--echo +--echo # Cleanup. +--echo + +DROP EVENT e2; + +--echo + +SET GLOBAL READ_ONLY = 0; + +--echo + +--echo # +--echo # Connection: default +--echo # + +--disconnect u1_con +--disconnect root_con +--connection default + +--echo + +DROP USER mysqltest_u1@localhost; + +--echo +--echo ##################################################################### +--echo # +--echo # End of BUG#31111. +--echo # +--echo ##################################################################### +--echo + + +########################################################################### +# +# End of tests +# +# !!! KEEP this section AT THE END of this file !!! +# +########################################################################### + +let $wait_condition= + select count(*) = 0 from information_schema.processlist + where db='events_test' and command = 'Connect' and user=current_user(); +--source include/wait_condition.inc + +DROP DATABASE events_test; + +# THIS MUST BE THE LAST LINE in this file. diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 787b04c12c6..adac2b596c1 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -2017,6 +2017,7 @@ end_no_lex_start: ret= 1; else { + ulong saved_master_access; /* Peculiar initialization order is a crutch to avoid races in SHOW PROCESSLIST which reads thd->{query/query_length} without a mutex. @@ -2024,8 +2025,19 @@ end_no_lex_start: thd->query_length= 0; thd->query= sp_sql.c_ptr_safe(); thd->query_length= sp_sql.length(); - if (Events::drop_event(thd, dbname, name, FALSE)) - ret= 1; + + /* + NOTE: even if we run in read-only mode, we should be able to lock + the mysql.event table for writing. In order to achieve this, we + should call mysql_lock_tables() under the super-user. + */ + + saved_master_access= thd->security_ctx->master_access; + thd->security_ctx->master_access |= SUPER_ACL; + + ret= Events::drop_event(thd, dbname, name, FALSE); + + thd->security_ctx->master_access= saved_master_access; } } #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 705bd8b2704..4451e763ff7 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -525,6 +525,10 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables, - whether this open mode would work under LOCK TABLES, or inside a stored function or trigger. + Note that if the table can't be locked successfully this operation will + close it. Therefore it provides guarantee that it either opens and locks + table or fails without leaving any tables open. + @param[in] thd Thread context @param[in] lock_type How to lock the table @param[out] table We will store the open table here @@ -544,7 +548,10 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, tables.init_one_table("mysql", "event", lock_type); if (simple_open_n_lock_tables(thd, &tables)) + { + close_thread_tables(thd, FALSE, FALSE); DBUG_RETURN(TRUE); + } *table= tables.table; tables.table->use_all_columns(); @@ -995,6 +1002,8 @@ update_timing_fields_for_event(THD *thd, if (thd->current_stmt_binlog_row_based) thd->clear_current_stmt_binlog_row_based(); + DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL); + if (open_event_table(thd, TL_WRITE, &table)) goto end; diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index b03b51f1134..d3a031fd8f8 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -399,6 +399,13 @@ Event_scheduler::start() new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER; new_thd->command= COM_DAEMON; + /* + We should run the event scheduler thread under the super-user privileges. + In particular, this is needed to be able to lock the mysql.event table + for writing when the server is running in the read-only mode. + */ + new_thd->security_ctx->master_access |= SUPER_ACL; + scheduler_param_value= (struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0)); scheduler_param_value->thd= new_thd; diff --git a/sql/events.cc b/sql/events.cc index 5246bccc388..1bfbc5d6645 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1124,11 +1124,25 @@ Events::load_events_from_db(THD *thd) READ_RECORD read_record_info; bool ret= TRUE; uint count= 0; + ulong saved_master_access; DBUG_ENTER("Events::load_events_from_db"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); - if (db_repository->open_event_table(thd, TL_WRITE, &table)) + /* + NOTE: even if we run in read-only mode, we should be able to lock the + mysql.event table for writing. In order to achieve this, we should call + mysql_lock_tables() under the super user. + */ + + saved_master_access= thd->security_ctx->master_access; + thd->security_ctx->master_access |= SUPER_ACL; + + ret= db_repository->open_event_table(thd, TL_WRITE, &table); + + thd->security_ctx->master_access= saved_master_access; + + if (ret) { sql_print_error("Event Scheduler: Failed to open table mysql.event"); DBUG_RETURN(TRUE); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ffbf0649961..d3ebfd94aa7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2404,6 +2404,7 @@ void Security_context::init() host= user= priv_user= ip= 0; host_or_ip= "connecting host"; priv_host[0]= '\0'; + master_access= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS db_access= NO_ACCESS; #endif From 7c00f8a3b474ef278004d29dcd8811f0c8f76d50 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Sat, 20 Oct 2007 01:20:38 +0400 Subject: [PATCH 46/92] Rename: query_error -> is_slave_error. Add comments. --- sql/ha_ndbcluster_binlog.cc | 4 +-- sql/handler.cc | 6 ++--- sql/log.cc | 4 +-- sql/log_event.cc | 54 ++++++++++++++++++++----------------- sql/log_event_old.cc | 12 ++++----- sql/mysqld.cc | 2 +- sql/protocol.cc | 4 +-- sql/slave.cc | 6 ++--- sql/sp_head.cc | 6 ++--- sql/sql_class.cc | 2 +- sql/sql_class.h | 11 ++++++-- sql/sql_connect.cc | 2 +- 12 files changed, 63 insertions(+), 50 deletions(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 5d5c8a26447..c22d5ac53f5 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -259,7 +259,7 @@ static void run_query(THD *thd, char *buf, char *end, DBUG_PRINT("query", ("%s", thd->query)); mysql_parse(thd, thd->query, thd->query_length, &found_semicolon); - if (no_print_error && thd->query_error) + if (no_print_error && thd->is_slave_error) { int i; Thd_ndb *thd_ndb= get_thd_ndb(thd); @@ -271,7 +271,7 @@ static void run_query(THD *thd, char *buf, char *end, sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d", buf, thd->net.last_error, thd->net.last_errno, thd_ndb->m_error_code, - thd->net.report_error, thd->query_error); + thd->net.report_error, thd->is_slave_error); } thd->options= save_thd_options; diff --git a/sql/handler.cc b/sql/handler.cc index 75c3a64bc27..706da76c000 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1447,7 +1447,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, (We should in the future either rewrite handler::print_error() or make a nice method of this. */ - bool query_error= thd->query_error; + bool is_slave_error= thd->is_slave_error; sp_rcontext *spcont= thd->spcont; SELECT_LEX *current_select= thd->lex->current_select; char buff[sizeof(thd->net.last_error)]; @@ -1455,7 +1455,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, int last_errno= thd->net.last_errno; strmake(buff, thd->net.last_error, sizeof(buff)-1); - thd->query_error= 0; + thd->is_slave_error= 0; thd->spcont= NULL; thd->lex->current_select= 0; thd->net.last_error[0]= 0; @@ -1475,7 +1475,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, strmake(new_error, thd->net.last_error, sizeof(buff)-1); /* restore thd */ - thd->query_error= query_error; + thd->is_slave_error= is_slave_error; thd->spcont= spcont; thd->lex->current_select= current_select; thd->net.last_errno= last_errno; diff --git a/sql/log.cc b/sql/log.cc index e923418b23a..02986bef493 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2891,8 +2891,8 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, *decrease_log_space-= file_size; ha_binlog_index_purge_file(current_thd, log_info.log_file_name); - if (current_thd->query_error) { - DBUG_PRINT("info",("query error: %d", current_thd->query_error)); + if (current_thd->is_slave_error) { + DBUG_PRINT("info",("slave error: %d", current_thd->is_slave_error)); if (my_errno == EMFILE) { DBUG_PRINT("info",("my_errno: %d, set ret = LOG_INFO_EMFILE", my_errno)); ret = LOG_INFO_EMFILE; diff --git a/sql/log_event.cc b/sql/log_event.cc index a435894382b..a6d07e72033 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -148,7 +148,7 @@ static void pretty_print_str(IO_CACHE* cache, char* str, int len) static void clear_all_errors(THD *thd, Relay_log_info *rli) { - thd->query_error = 0; + thd->is_slave_error = 0; thd->clear_error(); rli->clear_error(); } @@ -2106,7 +2106,7 @@ and was aborted. There is a chance that your master is inconsistent at this \ point. If you are sure that your master is ok, run this query manually on the \ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \ START SLAVE; . Query: '%s'", expected_error, thd->query); - thd->query_error= 1; + thd->is_slave_error= 1; } goto end; } @@ -2138,7 +2138,7 @@ Default database: '%s'. Query: '%s'", actual_error ? thd->net.last_error: "no error", actual_error, print_slave_db_safe(db), query_arg); - thd->query_error= 1; + thd->is_slave_error= 1; } /* If we get the same error code as expected, or they should be ignored. @@ -2153,14 +2153,14 @@ Default database: '%s'. Query: '%s'", /* Other cases: mostly we expected no error and get one. */ - else if (thd->query_error || thd->is_fatal_error) + else if (thd->is_slave_error || thd->is_fatal_error) { rli->report(ERROR_LEVEL, actual_error, "Error '%s' on query. Default database: '%s'. Query: '%s'", (actual_error ? thd->net.last_error : "unexpected success or fatal error"), print_slave_db_safe(thd->db), query_arg); - thd->query_error= 1; + thd->is_slave_error= 1; } /* @@ -2171,7 +2171,7 @@ Default database: '%s'. Query: '%s'", sql_print_error("Slave: did not get the expected number of affected \ rows running query from master - expected %d, got %d (this numbers \ should have matched modulo 4294967296).", 0, ...); - thd->query_error = 1; + thd->is_slave_error = 1; } We may also want an option to tell the slave to ignore "affected" mismatch. This mismatch could be implemented with a new ER_ code, and @@ -2215,7 +2215,7 @@ end: thd->first_successful_insert_id_in_prev_stmt= 0; thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); - return thd->query_error; + return thd->is_slave_error; } int Query_log_event::do_update_pos(Relay_log_info *rli) @@ -3255,7 +3255,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, thd->set_db(new_db.str, new_db.length); DBUG_ASSERT(thd->query == 0); thd->query_length= 0; // Should not be needed - thd->query_error= 0; + thd->is_slave_error= 0; clear_all_errors(thd, const_cast(rli)); /* see Query_log_event::do_apply_event() and BUG#13360 */ @@ -3429,7 +3429,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, List tmp_list; if (mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list, handle_dup, ignore, net != 0)) - thd->query_error= 1; + thd->is_slave_error= 1; if (thd->cuted_fields) { /* log_pos is the position of the LOAD event in the master log */ @@ -3468,9 +3468,9 @@ error: close_thread_tables(thd); DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", - thd->query_error= 0; thd->is_fatal_error= 1;); + thd->is_slave_error= 0; thd->is_fatal_error= 1;); - if (thd->query_error) + if (thd->is_slave_error) { /* this err/sql_errno code is copy-paste from net_send_error() */ const char *err; @@ -5655,7 +5655,7 @@ Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, m_width(tbl_arg ? tbl_arg->s->fields : 1), m_rows_buf(0), m_rows_cur(0), m_rows_end(0), m_flags(0) #ifdef HAVE_REPLICATION - ,m_key(NULL), m_curr_row(NULL), m_curr_row_end(NULL) + , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL) #endif { /* @@ -5703,7 +5703,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, #endif m_table_id(0), m_rows_buf(0), m_rows_cur(0), m_rows_end(0) #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - ,m_key(NULL), m_curr_row(NULL), m_curr_row_end(NULL) + , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL) #endif { DBUG_ENTER("Rows_log_event::Rows_log_event(const char*,...)"); @@ -5951,7 +5951,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) { if (!need_reopen) { - if (thd->query_error || thd->is_fatal_error) + if (thd->is_slave_error || thd->is_fatal_error) { /* Error reporting borrowed from Query_log_event with many excessive @@ -5995,7 +5995,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) uint tables_count= rli->tables_to_lock_count; if ((error= open_tables(thd, &tables, &tables_count, 0))) { - if (thd->query_error || thd->is_fatal_error) + if (thd->is_slave_error || thd->is_fatal_error) { /* Error reporting borrowed from Query_log_event with many excessive @@ -6006,7 +6006,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) "Error '%s' on reopening tables", (actual_error ? thd->net.last_error : "unexpected success or fatal error")); - thd->query_error= 1; + thd->is_slave_error= 1; } const_cast(rli)->clear_tables_to_lock(); DBUG_RETURN(error); @@ -6029,7 +6029,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) { mysql_unlock_tables(thd, thd->lock); thd->lock= 0; - thd->query_error= 1; + thd->is_slave_error= 1; const_cast(rli)->clear_tables_to_lock(); DBUG_RETURN(ERR_BAD_TABLE_DEF); } @@ -6159,7 +6159,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) "Error in %s event: row application failed. %s", get_type_str(), thd->net.last_error ? thd->net.last_error : ""); - thd->query_error= 1; + thd->is_slave_error= 1; break; } @@ -6221,7 +6221,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) */ thd->reset_current_stmt_binlog_row_based(); const_cast(rli)->cleanup_context(thd, error); - thd->query_error= 1; + thd->is_slave_error= 1; DBUG_RETURN(error); } @@ -6519,9 +6519,15 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_dblen(m_dbnam ? tbl->s->db.length : 0), m_tblnam(tbl->s->table_name.str), m_tbllen(tbl->s->table_name.length), - m_colcnt(tbl->s->fields), m_field_metadata(0), - m_field_metadata_size(0), m_memory(NULL), m_meta_memory(NULL), m_data_size(0), - m_table_id(tid), m_null_bits(0), m_flags(flags) + m_colcnt(tbl->s->fields), + m_memory(NULL), + m_table_id(tid), + m_flags(flags), + m_data_size(0), + m_field_metadata(0), + m_field_metadata_size(0), + m_null_bits(0), + m_meta_memory(NULL) { DBUG_ASSERT(m_table_id != ~0UL); /* @@ -6798,7 +6804,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) TABLE_LIST *tmp_table_list= table_list; if ((error= open_tables(thd, &tmp_table_list, &count, 0))) { - if (thd->query_error || thd->is_fatal_error) + if (thd->is_slave_error || thd->is_fatal_error) { /* Error reporting borrowed from Query_log_event with many excessive @@ -6810,7 +6816,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) (actual_error ? thd->net.last_error : "unexpected success or fatal error"), table_list->db, table_list->table_name); - thd->query_error= 1; + thd->is_slave_error= 1; } goto err; } diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 949179386ea..c6b691ec010 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -68,7 +68,7 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli { if (!need_reopen) { - if (thd->query_error || thd->is_fatal_error) + if (thd->is_slave_error || thd->is_fatal_error) { /* Error reporting borrowed from Query_log_event with many excessive @@ -112,7 +112,7 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli uint tables_count= rli->tables_to_lock_count; if ((error= open_tables(thd, &tables, &tables_count, 0))) { - if (thd->query_error || thd->is_fatal_error) + if (thd->is_slave_error || thd->is_fatal_error) { /* Error reporting borrowed from Query_log_event with many excessive @@ -123,7 +123,7 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli "Error '%s' on reopening tables", (actual_error ? thd->net.last_error : "unexpected success or fatal error")); - thd->query_error= 1; + thd->is_slave_error= 1; } const_cast(rli)->clear_tables_to_lock(); DBUG_RETURN(error); @@ -146,7 +146,7 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli { mysql_unlock_tables(thd, thd->lock); thd->lock= 0; - thd->query_error= 1; + thd->is_slave_error= 1; const_cast(rli)->clear_tables_to_lock(); DBUG_RETURN(Rows_log_event::ERR_BAD_TABLE_DEF); } @@ -255,7 +255,7 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli "Error in %s event: row application failed. %s", ev->get_type_str(), thd->net.last_error ? thd->net.last_error : ""); - thd->query_error= 1; + thd->is_slave_error= 1; break; } @@ -300,7 +300,7 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli */ thd->reset_current_stmt_binlog_row_based(); const_cast(rli)->cleanup_context(thd, error); - thd->query_error= 1; + thd->is_slave_error= 1; DBUG_RETURN(error); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a355c560996..cc964e417bf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2593,7 +2593,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags) DBUG_RETURN(0); } - thd->query_error= 1; // needed to catch query errors during replication + thd->is_slave_error= 1; // needed to catch query errors during replication if (!thd->no_warnings_for_error) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str); diff --git a/sql/protocol.cc b/sql/protocol.cc index 9d473912ba3..31d23ec94dd 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -84,7 +84,7 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) DBUG_VOID_RETURN; } - thd->query_error= 1; // needed to catch query errors during replication + thd->is_slave_error= 1; // needed to catch query errors during replication if (!err) { if (sql_errno) @@ -162,7 +162,7 @@ net_printf_error(THD *thd, uint errcode, ...) DBUG_VOID_RETURN; } - thd->query_error= 1; // needed to catch query errors during replication + thd->is_slave_error= 1; // needed to catch query errors during replication #ifndef EMBEDDED_LIBRARY query_cache_abort(net); // Safety #endif diff --git a/sql/slave.cc b/sql/slave.cc index fcbd4eb841b..494e13d8c9f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -980,7 +980,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, DBUG_RETURN(1); } thd->query= query; - thd->query_error = 0; + thd->is_slave_error = 0; thd->net.no_send_ok = 1; bzero((char*) &tables,sizeof(tables)); @@ -1009,7 +1009,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, thd->db_length= save_db_length; thd->options = save_options; - if (thd->query_error) + if (thd->is_slave_error) goto err; // mysql_parse took care of the error send thd->proc_info = "Opening master dump table"; @@ -2501,7 +2501,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, if (sys_init_slave.value_length) { execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave); - if (thd->query_error) + if (thd->is_slave_error) { sql_print_error("\ Slave SQL thread aborted. Can't execute init_slave query"); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 093544cdd0a..f7ab9bac3b1 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1108,7 +1108,7 @@ sp_head::execute(THD *thd) if ((ctx= thd->spcont)) ctx->clear_handler(); - thd->query_error= 0; + thd->is_slave_error= 0; old_arena= thd->stmt_arena; /* @@ -1275,8 +1275,8 @@ sp_head::execute(THD *thd) state= EXECUTED; done: - DBUG_PRINT("info", ("err_status: %d killed: %d query_error: %d report_error: %d", - err_status, thd->killed, thd->query_error, + DBUG_PRINT("info", ("err_status: %d killed: %d is_slave_error: %d report_error: %d", + err_status, thd->killed, thd->is_slave_error, thd->net.report_error)); if (thd->killed) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ffbf0649961..8c02fdb8289 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -395,7 +395,7 @@ THD::THD() count_cuted_fields= CHECK_FIELD_IGNORE; killed= NOT_KILLED; col_access=0; - query_error= thread_specific_used= FALSE; + is_slave_error= thread_specific_used= FALSE; hash_clear(&handler_tables_hash); tmp_table=0; used_tables=0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 97a63ed9448..5aec68e1c61 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1466,7 +1466,14 @@ public: /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ bool substitute_null_with_insert_id; bool in_lock_tables; - bool query_error, bootstrap, cleanup_done; + /** + True if a slave error. Causes the slave to stop. Not the same + as the statement execution error (net.report_error), since + a statement may be expected to return an error, e.g. because + it returned an error on master, and this is OK on the slave. + */ + bool is_slave_error; + bool bootstrap, cleanup_done; /** is set if some thread specific value(s) used in a statement. */ bool thread_specific_used; @@ -1695,7 +1702,7 @@ public: net.last_error[0]= 0; net.last_errno= 0; net.report_error= 0; - query_error= 0; + is_slave_error= 0; DBUG_VOID_RETURN; } inline bool vio_ok() const { return net.vio != 0; } diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 094bef9324e..afd97c27a55 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1030,7 +1030,7 @@ static void prepare_new_connection_state(THD* thd) if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) { execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); - if (thd->query_error) + if (thd->net.report_error) { thd->killed= THD::KILL_CONNECTION; sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), From 9a6f67314380ee56a1c7af02554de544bd796fc4 Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Sat, 20 Oct 2007 21:48:15 +0400 Subject: [PATCH 47/92] Fix for BUG#31148: bool close_thread_table(THD*, TABLE**): Assertion `table->key_read == 0' failed. The problem was that key_read on a table in a sub-select was not properly reset. That happens because the code responsible for that is copy&pasted all around the server. In some place, it was obviously forgotten to be pasted. The fix is to reset key_read properly. --- mysql-test/r/key.result | 15 +++++++++++++++ mysql-test/t/key.test | 23 +++++++++++++++++++++++ sql/sql_select.cc | 9 ++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index a2bed75a709..6c115435fb6 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -530,3 +530,18 @@ ORDER BY c.b, c.d a b c d e f g h i j a b c d 2 2 1 2004-11-30 12:00:00 1 0 0 0 0 0 2 3388000 -553000 NULL DROP TABLE t1, t2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT); +INSERT INTO t1 VALUES (), (), (); +SELECT 1 AS c1 +FROM t1 +ORDER BY ( +SELECT 1 AS c2 +FROM t1 +GROUP BY GREATEST(LAST_INSERT_ID(), t1.a) ASC +LIMIT 1); +c1 +1 +1 +1 +DROP TABLE t1; diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index f1eb8e68b49..cd6c480407d 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -501,3 +501,26 @@ ORDER BY c.b, c.d ; DROP TABLE t1, t2; + +# +# Bug #31148: bool close_thread_table(THD*, TABLE**): Assertion +# `table->key_read == 0' failed. +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT); + +INSERT INTO t1 VALUES (), (), (); + +SELECT 1 AS c1 +FROM t1 +ORDER BY ( + SELECT 1 AS c2 + FROM t1 + GROUP BY GREATEST(LAST_INSERT_ID(), t1.a) ASC + LIMIT 1); + +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index eb2731205ec..d041b2edcfa 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6651,7 +6651,14 @@ void JOIN::cleanup(bool full) for (tab= join_tab, end= tab+tables; tab != end; tab++) { if (tab->table) - tab->table->file->ha_index_or_rnd_end(); + { + if (tab->table->key_read) + { + tab->table->key_read= 0; + tab->table->file->extra(HA_EXTRA_NO_KEYREAD); + } + tab->table->file->ha_index_or_rnd_end(); + } } } } From 01f62e0d06d42b15035451c148cc5744b17ca94e Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Mon, 22 Oct 2007 23:02:05 +0400 Subject: [PATCH 48/92] WL#4104: Deprecate the Instance Manager. A deprecation warning added. --- server-tools/instance-manager/mysqlmanager.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index 6d6ebbee57d..276d1ca3b49 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -79,6 +79,9 @@ int main(int argc, char *argv[]) { int return_value; + puts("\n" + "WARNING: This program is deprecated and will be removed in 6.0.\n"); + /* Initialize. */ MY_INIT(argv[0]); From ac1dc64ebba5e829192a901609ca45eb6c22fa5c Mon Sep 17 00:00:00 2001 From: "jonas@perch.ndb.mysql.com" <> Date: Tue, 23 Oct 2007 11:24:34 +0200 Subject: [PATCH 49/92] ndb - bug#26450 partial backport from 6.2 + add fix of bug --- .../ndb/include/kernel/GlobalSignalNumbers.h | 8 +- .../ndb/include/kernel/signaldata/AccScan.hpp | 1 + .../include/kernel/signaldata/CopyFrag.hpp | 41 ++++++- storage/ndb/include/ndb_version.h.in | 47 ++++++++ .../debugger/signaldata/SignalNames.cpp | 4 + storage/ndb/src/kernel/blocks/ERROR_codes.txt | 4 +- storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp | 7 +- .../ndb/src/kernel/blocks/dbdih/DbdihInit.cpp | 5 + .../ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 111 +++++++++++++++++- storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp | 1 + .../ndb/src/kernel/blocks/dblqh/DblqhInit.cpp | 3 + .../ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 93 ++++++++++++++- storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp | 3 + .../ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp | 19 +++ .../ndb/src/kernel/blocks/dbtup/DbtupScan.cpp | 68 +++++++++-- storage/ndb/test/ndbapi/testSystemRestart.cpp | 54 +++++++++ .../ndb/test/run-test/daily-basic-tests.txt | 4 + storage/ndb/test/src/NdbRestarts.cpp | 1 + 18 files changed, 452 insertions(+), 22 deletions(-) diff --git a/storage/ndb/include/kernel/GlobalSignalNumbers.h b/storage/ndb/include/kernel/GlobalSignalNumbers.h index aa0596f102a..9653c20260f 100644 --- a/storage/ndb/include/kernel/GlobalSignalNumbers.h +++ b/storage/ndb/include/kernel/GlobalSignalNumbers.h @@ -195,9 +195,11 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; /* 132 not unused */ /* 133 not unused */ #define GSN_CM_HEARTBEAT 134 /* distr. */ -/* 135 unused */ -/* 136 unused */ -/* 137 unused */ + +#define GSN_PREPARE_COPY_FRAG_REQ 135 +#define GSN_PREPARE_COPY_FRAG_REF 136 +#define GSN_PREPARE_COPY_FRAG_CONF 137 + #define GSN_CM_NODEINFOCONF 138 /* distr. */ #define GSN_CM_NODEINFOREF 139 /* distr. */ #define GSN_CM_NODEINFOREQ 140 /* distr. */ diff --git a/storage/ndb/include/kernel/signaldata/AccScan.hpp b/storage/ndb/include/kernel/signaldata/AccScan.hpp index 73d69825069..a0aa38c8d8e 100644 --- a/storage/ndb/include/kernel/signaldata/AccScan.hpp +++ b/storage/ndb/include/kernel/signaldata/AccScan.hpp @@ -49,6 +49,7 @@ private: Uint32 savePointId; Uint32 gci; }; + Uint32 maxPage; /** * Previously there where also a scan type diff --git a/storage/ndb/include/kernel/signaldata/CopyFrag.hpp b/storage/ndb/include/kernel/signaldata/CopyFrag.hpp index 06dd4070264..d985358dce4 100644 --- a/storage/ndb/include/kernel/signaldata/CopyFrag.hpp +++ b/storage/ndb/include/kernel/signaldata/CopyFrag.hpp @@ -29,7 +29,7 @@ class CopyFragReq { */ friend class Dblqh; public: - STATIC_CONST( SignalLength = 9 ); + STATIC_CONST( SignalLength = 10 ); private: Uint32 userPtr; @@ -42,6 +42,7 @@ private: Uint32 gci; Uint32 nodeCount; Uint32 nodeList[1]; + //Uint32 maxPage; is stored in nodeList[nodeCount] }; class CopyFragConf { @@ -95,4 +96,42 @@ struct UpdateFragDistKeyOrd STATIC_CONST( SignalLength = 3 ); }; +struct PrepareCopyFragReq +{ + STATIC_CONST( SignalLength = 6 ); + + Uint32 senderRef; + Uint32 senderData; + Uint32 tableId; + Uint32 fragId; + Uint32 copyNodeId; + Uint32 startingNodeId; +}; + +struct PrepareCopyFragRef +{ + Uint32 senderRef; + Uint32 senderData; + Uint32 tableId; + Uint32 fragId; + Uint32 copyNodeId; + Uint32 startingNodeId; + Uint32 errorCode; + + STATIC_CONST( SignalLength = 7 ); +}; + +struct PrepareCopyFragConf +{ + STATIC_CONST( SignalLength = 7 ); + + Uint32 senderRef; + Uint32 senderData; + Uint32 tableId; + Uint32 fragId; + Uint32 copyNodeId; + Uint32 startingNodeId; + Uint32 maxPageNo; +}; + #endif diff --git a/storage/ndb/include/ndb_version.h.in b/storage/ndb/include/ndb_version.h.in index 5405ad4d7aa..6a479433b3b 100644 --- a/storage/ndb/include/ndb_version.h.in +++ b/storage/ndb/include/ndb_version.h.in @@ -88,5 +88,52 @@ Uint32 ndbGetOwnVersion(); #define NDBD_NODE_VERSION_REP NDB_MAKE_VERSION(6,1,1) +#define NDBD_PREPARE_COPY_FRAG_VERSION NDB_MAKE_VERSION(6,2,1) +#define NDBD_PREPARE_COPY_FRAG_V2_51 NDB_MAKE_VERSION(5,1,23) +#define NDBD_PREPARE_COPY_FRAG_V2_62 NDB_MAKE_VERSION(6,2,8) +#define NDBD_PREPARE_COPY_FRAG_V2_63 NDB_MAKE_VERSION(6,3,6) + +/** + * 0 = NO PREP COPY FRAG SUPPORT + * 1 = NO MAX PAGE SUPPORT + * 2 = LATEST VERSION + */ +static +inline +int +ndb_check_prep_copy_frag_version(Uint32 version) +{ + if (version == NDB_VERSION_D) + return 2; + + const Uint32 major = (version >> 16) & 0xFF; + const Uint32 minor = (version >> 8) & 0xFF; + if (major >= 6) + { + if (minor == 2) + { + if (version >= NDBD_PREPARE_COPY_FRAG_V2_62) + return 2; + if (version >= NDBD_PREPARE_COPY_FRAG_VERSION) + return 1; + return 0; + } + else if (minor == 3) + { + if (version >= NDBD_PREPARE_COPY_FRAG_V2_63) + return 2; + return 1; + } + return 2; + } + else if (major == 5 && minor == 1) + { + if (version >= NDBD_PREPARE_COPY_FRAG_V2_51) + return 2; + } + + return 0; +} + #endif diff --git a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp index 0d31cd5de7f..b4221cbec8e 100644 --- a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp +++ b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp @@ -640,5 +640,9 @@ const GsnName SignalNames [] = { ,{ GSN_ROUTE_ORD, "ROUTE_ORD" } ,{ GSN_NODE_VERSION_REP, "NODE_VERSION_REP" } + + ,{ GSN_PREPARE_COPY_FRAG_REQ, "PREPARE_COPY_FRAG_REQ" } + ,{ GSN_PREPARE_COPY_FRAG_REF, "PREPARE_COPY_FRAG_REF" } + ,{ GSN_PREPARE_COPY_FRAG_CONF, "PREPARE_COPY_FRAG_CONF" } }; const unsigned short NO_OF_SIGNAL_NAMES = sizeof(SignalNames)/sizeof(GsnName); diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index 5317d0e5c86..4d4d4fcafc4 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -3,7 +3,7 @@ Next NDBCNTR 1002 Next NDBFS 2000 Next DBACC 3002 Next DBTUP 4029 -Next DBLQH 5045 +Next DBLQH 5047 Next DBDICT 6008 Next DBDIH 7193 Next DBTC 8054 @@ -186,6 +186,8 @@ handling in DBTC to ensure that node failures are also well handled in time-out handling. They can also be used to test multiple node failure handling. +5045: Crash in PREPARE_COPY_FRAG_REQ +5046: Crash if LQHKEYREQ (NrCopy) comes when frag-state is incorrect ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBLQH ------------------------------------------------- diff --git a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index 1177500bc27..21826df28f9 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -545,7 +545,8 @@ public: TO_WAIT_ENDING = 21, ENDING = 22, - STARTING_LOCAL_FRAGMENTS = 24 + STARTING_LOCAL_FRAGMENTS = 24, + PREPARE_COPY = 25 }; enum ToSlaveStatus { TO_SLAVE_IDLE = 0, @@ -556,6 +557,7 @@ public: TO_SLAVE_COPY_COMPLETED = 5 }; Uint32 startGci; + Uint32 maxPage; Uint32 toCopyNode; Uint32 toCurrentFragid; Uint32 toCurrentReplica; @@ -672,6 +674,8 @@ private: void execNODE_FAILREP(Signal *); void execCOPY_FRAGCONF(Signal *); void execCOPY_FRAGREF(Signal *); + void execPREPARE_COPY_FRAG_REF(Signal*); + void execPREPARE_COPY_FRAG_CONF(Signal*); void execDIADDTABREQ(Signal *); void execDIGETNODESREQ(Signal *); void execDIRELEASEREQ(Signal *); @@ -1114,6 +1118,7 @@ private: void sendStartTo(Signal *, Uint32 takeOverPtr); void startNextCopyFragment(Signal *, Uint32 takeOverPtr); void toCopyFragLab(Signal *, Uint32 takeOverPtr); + void toStartCopyFrag(Signal *, TakeOverRecordPtr); void startHsAddFragConfLab(Signal *); void prepareSendCreateFragReq(Signal *, Uint32 takeOverPtr); void sendUpdateTo(Signal *, Uint32 takeOverPtr, Uint32 updateState); diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp index aff31d625f4..6ce281434c2 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp @@ -259,6 +259,11 @@ Dbdih::Dbdih(Block_context& ctx): addRecSignal(GSN_START_FRAGREF, &Dbdih::execSTART_FRAGREF); + + addRecSignal(GSN_PREPARE_COPY_FRAG_REF, + &Dbdih::execPREPARE_COPY_FRAG_REF); + addRecSignal(GSN_PREPARE_COPY_FRAG_CONF, + &Dbdih::execPREPARE_COPY_FRAG_CONF); apiConnectRecord = 0; connectRecord = 0; diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index dc35e6fba41..5403ac5cc38 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -3155,6 +3155,94 @@ void Dbdih::toCopyFragLab(Signal* signal, TakeOverRecordPtr takeOverPtr; RETURN_IF_TAKE_OVER_INTERRUPTED(takeOverPtrI, takeOverPtr); + /** + * Inform starting node that TakeOver is about to start + */ + Uint32 nodeId = takeOverPtr.p->toStartingNode; + + Uint32 version = getNodeInfo(nodeId).m_version; + if (ndb_check_prep_copy_frag_version(version)) + { + jam(); + TabRecordPtr tabPtr; + tabPtr.i = takeOverPtr.p->toCurrentTabref; + ptrCheckGuard(tabPtr, ctabFileSize, tabRecord); + + FragmentstorePtr fragPtr; + getFragstore(tabPtr.p, takeOverPtr.p->toCurrentFragid, fragPtr); + Uint32 nodes[MAX_REPLICAS]; + extractNodeInfo(fragPtr.p, nodes); + + PrepareCopyFragReq* req= (PrepareCopyFragReq*)signal->getDataPtrSend(); + req->senderRef = reference(); + req->senderData = takeOverPtrI; + req->tableId = takeOverPtr.p->toCurrentTabref; + req->fragId = takeOverPtr.p->toCurrentFragid; + req->copyNodeId = nodes[0]; // Src + req->startingNodeId = takeOverPtr.p->toStartingNode; // Dst + Uint32 ref = calcLqhBlockRef(takeOverPtr.p->toStartingNode); + + sendSignal(ref, GSN_PREPARE_COPY_FRAG_REQ, signal, + PrepareCopyFragReq::SignalLength, JBB); + + takeOverPtr.p->toMasterStatus = TakeOverRecord::PREPARE_COPY; + return; + } + + takeOverPtr.p->maxPage = RNIL; + toStartCopyFrag(signal, takeOverPtr); +} + +void +Dbdih::execPREPARE_COPY_FRAG_REF(Signal* signal) +{ + jamEntry(); + PrepareCopyFragRef ref = *(PrepareCopyFragRef*)signal->getDataPtr(); + + TakeOverRecordPtr takeOverPtr; + RETURN_IF_TAKE_OVER_INTERRUPTED(ref.senderData, takeOverPtr); + + ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::PREPARE_COPY); + + /** + * Treat this as copy frag ref + */ + CopyFragRef * cfref = (CopyFragRef*)signal->getDataPtrSend(); + cfref->userPtr = ref.senderData; + cfref->startingNodeId = ref.startingNodeId; + cfref->errorCode = ref.errorCode; + cfref->tableId = ref.tableId; + cfref->fragId = ref.fragId; + cfref->sendingNodeId = ref.copyNodeId; + takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_FRAG; + execCOPY_FRAGREF(signal); +} + +void +Dbdih::execPREPARE_COPY_FRAG_CONF(Signal* signal) +{ + PrepareCopyFragConf conf = *(PrepareCopyFragConf*)signal->getDataPtr(); + + TakeOverRecordPtr takeOverPtr; + RETURN_IF_TAKE_OVER_INTERRUPTED(conf.senderData, takeOverPtr); + + Uint32 version = getNodeInfo(refToNode(conf.senderRef)).m_version; + if (ndb_check_prep_copy_frag_version(version) >= 2) + { + jam(); + takeOverPtr.p->maxPage = conf.maxPageNo; + } + else + { + jam(); + takeOverPtr.p->maxPage = RNIL; + } + toStartCopyFrag(signal, takeOverPtr); +} + +void +Dbdih::toStartCopyFrag(Signal* signal, TakeOverRecordPtr takeOverPtr) +{ CreateReplicaRecordPtr createReplicaPtr; createReplicaPtr.i = 0; ptrAss(createReplicaPtr, createReplicaRecord); @@ -3178,8 +3266,8 @@ void Dbdih::toCopyFragLab(Signal* signal, createReplicaPtr.p->hotSpareUse = true; createReplicaPtr.p->dataNodeId = takeOverPtr.p->toStartingNode; - prepareSendCreateFragReq(signal, takeOverPtrI); -}//Dbdih::toCopyFragLab() + prepareSendCreateFragReq(signal, takeOverPtr.i); +}//Dbdih::toStartCopy() void Dbdih::prepareSendCreateFragReq(Signal* signal, Uint32 takeOverPtrI) { @@ -3412,10 +3500,12 @@ void Dbdih::execCREATE_FRAGCONF(Signal* signal) copyFragReq->schemaVersion = tabPtr.p->schemaVersion; copyFragReq->distributionKey = fragPtr.p->distributionKey; copyFragReq->gci = gci; - copyFragReq->nodeCount = extractNodeInfo(fragPtr.p, - copyFragReq->nodeList); + Uint32 len = copyFragReq->nodeCount = + extractNodeInfo(fragPtr.p, + copyFragReq->nodeList); + copyFragReq->nodeList[len] = takeOverPtr.p->maxPage; sendSignal(ref, GSN_COPY_FRAGREQ, signal, - CopyFragReq::SignalLength + copyFragReq->nodeCount, JBB); + CopyFragReq::SignalLength + len, JBB); } else { ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COMMIT_CREATE); jam(); @@ -4576,13 +4666,22 @@ void Dbdih::checkTakeOverInMasterStartNodeFailure(Signal* signal, ok = true; jam(); //----------------------------------------------------------------------- - // The starting node will discover the problem. We will receive either + // The copying node will discover the problem. We will receive either // COPY_FRAGREQ or COPY_FRAGCONF and then we can release the take over // record and end the process. If the copying node should also die then // we will try to send prepare create fragment and will then discover // that the starting node has failed. //----------------------------------------------------------------------- break; + case TakeOverRecord::PREPARE_COPY: + ok = true; + jam(); + /** + * We're waiting for the starting node...which just died... + * endTakeOver + */ + endTakeOver(takeOverPtr.i); + break; case TakeOverRecord::COPY_ACTIVE: ok = true; jam(); diff --git a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 1bed25fb5a8..95cad98b81c 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -2144,6 +2144,7 @@ private: void execSTORED_PROCCONF(Signal* signal); void execSTORED_PROCREF(Signal* signal); void execCOPY_FRAGREQ(Signal* signal); + void execPREPARE_COPY_FRAG_REQ(Signal* signal); void execUPDATE_FRAG_DIST_KEY_ORD(Signal*); void execCOPY_ACTIVEREQ(Signal* signal); void execCOPY_STATEREQ(Signal* signal); diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp index d6411ee1cb9..db6d201575f 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp @@ -310,6 +310,9 @@ Dblqh::Dblqh(Block_context& ctx): addRecSignal(GSN_UPDATE_FRAG_DIST_KEY_ORD, &Dblqh::execUPDATE_FRAG_DIST_KEY_ORD); + addRecSignal(GSN_PREPARE_COPY_FRAG_REQ, + &Dblqh::execPREPARE_COPY_FRAG_REQ); + initData(); #ifdef VM_TRACE diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index f511e00afaa..e0449e08ddd 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3670,6 +3670,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal) { ndbout_c("fragptr.p->fragStatus: %d", fragptr.p->fragStatus); + CRASH_INSERTION(5046); } ndbassert(fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION); fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY; @@ -10083,6 +10084,86 @@ Dblqh::calculateHash(Uint32 tableId, const Uint32* src) return md5_hash(Tmp, keyLen); }//Dblqh::calculateHash() +/** + * PREPARE COPY FRAG REQ + */ +void +Dblqh::execPREPARE_COPY_FRAG_REQ(Signal* signal) +{ + jamEntry(); + PrepareCopyFragReq req = *(PrepareCopyFragReq*)signal->getDataPtr(); + + CRASH_INSERTION(5045); + + tabptr.i = req.tableId; + ptrCheckGuard(tabptr, ctabrecFileSize, tablerec); + + Uint32 max_page = RNIL; + + if (getOwnNodeId() != req.startingNodeId) + { + jam(); + /** + * This is currently dead code... + * but is provided so we can impl. a better scan+delete on + * starting node wo/ having to change running node + */ + ndbrequire(getOwnNodeId() == req.copyNodeId); + c_tup->get_frag_info(req.tableId, req.fragId, &max_page); + + PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend(); + conf->senderData = req.senderData; + conf->senderRef = reference(); + conf->tableId = req.tableId; + conf->fragId = req.fragId; + conf->copyNodeId = req.copyNodeId; + conf->startingNodeId = req.startingNodeId; + conf->maxPageNo = max_page; + sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF, + signal, PrepareCopyFragConf::SignalLength, JBB); + + return; + } + + if (! DictTabInfo::isOrderedIndex(tabptr.p->tableType)) + { + jam(); + ndbrequire(getFragmentrec(signal, req.fragId)); + + /** + * + */ + if (cstartType == NodeState::ST_SYSTEM_RESTART) + { + jam(); + signal->theData[0] = fragptr.p->tabRef; + signal->theData[1] = fragptr.p->fragId; + sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB); + } + + + /** + * + */ + fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED; + fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION; + fragptr.p->logFlag = Fragrecord::STATE_FALSE; + + c_tup->get_frag_info(req.tableId, req.fragId, &max_page); + } + + PrepareCopyFragConf* conf = (PrepareCopyFragConf*)signal->getDataPtrSend(); + conf->senderData = req.senderData; + conf->senderRef = reference(); + conf->tableId = req.tableId; + conf->fragId = req.fragId; + conf->copyNodeId = req.copyNodeId; + conf->startingNodeId = req.startingNodeId; + conf->maxPageNo = max_page; + sendSignal(req.senderRef, GSN_PREPARE_COPY_FRAG_CONF, + signal, PrepareCopyFragConf::SignalLength, JBB); +} + /* *************************************** */ /* COPY_FRAGREQ: Start copying a fragment */ /* *************************************** */ @@ -10118,6 +10199,13 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal) for (i = 0; inodeList[i]); } + Uint32 maxPage = copyFragReq->nodeList[nodeCount]; + Uint32 version = getNodeInfo(refToNode(userRef)).m_version; + if (ndb_check_prep_copy_frag_version(version) < 2) + { + jam(); + maxPage = RNIL; + } if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) { jam(); @@ -10193,14 +10281,15 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal) req->requestInfo = 0; AccScanReq::setLockMode(req->requestInfo, 0); AccScanReq::setReadCommittedFlag(req->requestInfo, 0); - AccScanReq::setNRScanFlag(req->requestInfo, gci ? 1 : 0); + AccScanReq::setNRScanFlag(req->requestInfo, 1); AccScanReq::setNoDiskScanFlag(req->requestInfo, 1); req->transId1 = tcConnectptr.p->transid[0]; req->transId2 = tcConnectptr.p->transid[1]; req->savePointId = tcConnectptr.p->savePointId; + req->maxPage = maxPage; sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal, - AccScanReq::SignalLength, JBB); + AccScanReq::SignalLength + 1, JBB); if (! nodemask.isclear()) { diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 3db91c55849..45d124b8d7d 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -518,6 +518,7 @@ typedef Ptr FragoperrecPtr; Uint32 m_savePointId; Uint32 m_scanGCI; }; + Uint32 m_endPage; // lock waited for or obtained and not yet passed to LQH Uint32 m_accLockOp; @@ -1576,6 +1577,8 @@ public: void nr_delete_page_callback(Signal*, Uint32 op, Uint32 page); void nr_delete_log_buffer_callback(Signal*, Uint32 op, Uint32 page); + + bool get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage); private: BLOCK_DEFINES(Dbtup); diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp index c8df5f5154e..176efac8058 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp @@ -1464,3 +1464,22 @@ Dbtup::complete_restore_lcp(Uint32 tableId, Uint32 fragId) tabDesc += 2; } } + +bool +Dbtup::get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage) +{ + jamEntry(); + TablerecPtr tabPtr; + tabPtr.i= tableId; + ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); + + FragrecordPtr fragPtr; + getFragmentrec(fragPtr, fragId, tabPtr.p); + + if (maxPage) + { + * maxPage = fragPtr.p->noOfPages; + } + + return true; +} diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp index a5f7d4be0a9..5e9306909b4 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp @@ -95,7 +95,23 @@ Dbtup::execACC_SCANREQ(Signal* signal) } } - bits |= AccScanReq::getNRScanFlag(req->requestInfo) ? ScanOp::SCAN_NR : 0; + if (AccScanReq::getNRScanFlag(req->requestInfo)) + { + jam(); + bits |= ScanOp::SCAN_NR; + scanPtr.p->m_endPage = req->maxPage; + if (req->maxPage != RNIL && req->maxPage > frag.noOfPages) + { + ndbout_c("%u %u endPage: %u (noOfPages: %u)", + tablePtr.i, fragId, + req->maxPage, fragPtr.p->noOfPages); + } + } + else + { + jam(); + scanPtr.p->m_endPage = RNIL; + } // set up scan op new (scanPtr.p) ScanOp(); @@ -540,7 +556,7 @@ Dbtup::scanFirst(Signal*, ScanOpPtr scanPtr) ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord); Fragrecord& frag = *fragPtr.p; // in the future should not pre-allocate pages - if (frag.noOfPages == 0) { + if (frag.noOfPages == 0 && ((bits & ScanOp::SCAN_NR) == 0)) { jam(); scan.m_state = ScanOp::Last; return; @@ -632,11 +648,23 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) key.m_page_no++; if (key.m_page_no >= frag.noOfPages) { jam(); + + if ((bits & ScanOp::SCAN_NR) && (scan.m_endPage != RNIL)) + { + jam(); + if (key.m_page_no < scan.m_endPage) + { + jam(); + ndbout_c("scanning page %u", key.m_page_no); + goto cont; + } + } // no more pages, scan ends pos.m_get = ScanPos::Get_undef; scan.m_state = ScanOp::Last; return true; } + cont: key.m_page_idx = 0; pos.m_get = ScanPos::Get_page_mm; // clear cached value @@ -649,7 +677,13 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) { if (pos.m_realpid_mm == RNIL) { jam(); - pos.m_realpid_mm = getRealpid(fragPtr.p, key.m_page_no); + if (key.m_page_no < frag.noOfPages) + pos.m_realpid_mm = getRealpid(fragPtr.p, key.m_page_no); + else + { + ndbassert(bits & ScanOp::SCAN_NR); + goto nopage; + } } PagePtr pagePtr; c_page_pool.getPtr(pagePtr, pos.m_realpid_mm); @@ -657,9 +691,18 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) if (pagePtr.p->page_state == ZEMPTY_MM) { // skip empty page jam(); - pos.m_get = ScanPos::Get_next_page_mm; - break; // incr loop count + if (! (bits & ScanOp::SCAN_NR)) + { + pos.m_get = ScanPos::Get_next_page_mm; + break; // incr loop count + } + else + { + jam(); + pos.m_realpid_mm = RNIL; + } } + nopage: pos.m_page = pagePtr.p; pos.m_get = ScanPos::Get_tuple; } @@ -820,11 +863,11 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) { pos.m_get = ScanPos::Get_next_tuple_fs; th = (Tuple_header*)&page->m_data[key.m_page_idx]; - thbits = th->m_header_bits; if (likely(! (bits & ScanOp::SCAN_NR))) { jam(); + thbits = th->m_header_bits; if (! (thbits & Tuple_header::FREE)) { goto found_tuple; @@ -832,7 +875,15 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) } else { - if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI) + if (pos.m_realpid_mm == RNIL) + { + jam(); + foundGCI = 0; + goto found_deleted_rowid; + } + thbits = th->m_header_bits; + if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI || + foundGCI == 0) { if (! (thbits & Tuple_header::FREE)) { @@ -904,7 +955,8 @@ Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr) Fix_page *mmpage = (Fix_page*)c_page_pool.getPtr(pos.m_realpid_mm); th = (Tuple_header*)(mmpage->m_data + key_mm.m_page_idx); - if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI) + if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI || + foundGCI == 0) { if (! (thbits & Tuple_header::FREE)) break; diff --git a/storage/ndb/test/ndbapi/testSystemRestart.cpp b/storage/ndb/test/ndbapi/testSystemRestart.cpp index 3cd7a3798c5..89580c0cef8 100644 --- a/storage/ndb/test/ndbapi/testSystemRestart.cpp +++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp @@ -1501,6 +1501,54 @@ int runSR_DD_2(NDBT_Context* ctx, NDBT_Step* step) return result; } +int +runBug27434(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + NdbRestarter restarter; + Ndb* pNdb = GETNDB(step); + const Uint32 nodeCount = restarter.getNumDbNodes(); + + if (nodeCount < 2) + return NDBT_OK; + + int args[] = { DumpStateOrd::DihMaxTimeBetweenLCP }; + int dump[] = { DumpStateOrd::DihStartLcpImmediately }; + + int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_CHECKPOINT, 0 }; + NdbLogEventHandle handle = + ndb_mgm_create_logevent_handle(restarter.handle, filter); + + struct ndb_logevent event; + + do { + int node1 = restarter.getDbNodeId(rand() % nodeCount); + CHECK(restarter.restartOneDbNode(node1, false, true, true) == 0); + NdbSleep_SecSleep(3); + CHECK(restarter.waitNodesNoStart(&node1, 1) == 0); + + CHECK(restarter.dumpStateAllNodes(args, 1) == 0); + + for (Uint32 i = 0; i<3; i++) + { + CHECK(restarter.dumpStateAllNodes(dump, 1) == 0); + while(ndb_logevent_get_next(handle, &event, 0) >= 0 && + event.type != NDB_LE_LocalCheckpointStarted); + while(ndb_logevent_get_next(handle, &event, 0) >= 0 && + event.type != NDB_LE_LocalCheckpointCompleted); + } + + restarter.restartAll(false, true, true); + NdbSleep_SecSleep(3); + CHECK(restarter.waitClusterNoStart() == 0); + restarter.insertErrorInNode(node1, 5046); + restarter.startAll(); + CHECK(restarter.waitClusterStarted() == 0); + } while(false); + + return result; +} + NDBT_TESTSUITE(testSystemRestart); TESTCASE("SR1", "Basic system restart test. Focus on testing restart from REDO log.\n" @@ -1681,6 +1729,12 @@ TESTCASE("Bug24664", STEP(runBug24664); FINALIZER(runClearTable); } +TESTCASE("Bug27434", + "") +{ + INITIALIZER(runWaitStarted); + STEP(runBug27434); +} TESTCASE("SR_DD_1", "") { TC_PROPERTY("ALL", 1); diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 845cd5c21bb..103675d8e35 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -880,6 +880,10 @@ max-time: 1000 cmd: testNodeRestart args: -n Bug27466 T1 +max-time: 1500 +cmd: testSystemRestart +args: -n Bug27434 T1 + max-time: 1000 cmd: test_event args: -l 10 -n Bug27169 T1 diff --git a/storage/ndb/test/src/NdbRestarts.cpp b/storage/ndb/test/src/NdbRestarts.cpp index 6ec520887b5..86e71f4b3fc 100644 --- a/storage/ndb/test/src/NdbRestarts.cpp +++ b/storage/ndb/test/src/NdbRestarts.cpp @@ -607,6 +607,7 @@ NFDuringNR_codes[] = { 5026, 7139, 7132, + 5045, //LCP 8000, From dac55f09f0f1ed0e86ce04317fe8c52a1d4bb2bd Mon Sep 17 00:00:00 2001 From: "davi@moksha.local/moksha.com.br" <> Date: Tue, 23 Oct 2007 09:05:39 -0300 Subject: [PATCH 50/92] Bug#31669 Buffer overflow in mysql_change_user() The problem is that when copying the supplied username and database, no bounds checking is performed on the fixed-length buffer. A sufficiently large (> 512) user string can easily cause stack corruption. Since this API can be used from PHP and other programs, this is a serious problem. The solution is to increase the buffer size to the accepted size in similar functions and perform bounds checking when copying the username and database. --- libmysql/libmysql.c | 7 +-- tests/mysql_client_test.c | 94 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c7bdfc4c42c..5c015bd6b0f 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -706,7 +706,8 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd) my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db) { - char buff[512],*end=buff; + char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2]; + char *end= buff; int rc; DBUG_ENTER("mysql_change_user"); @@ -716,7 +717,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, passwd=""; /* Store user into the buffer */ - end=strmov(end,user)+1; + end= strmake(end, user, USERNAME_LENGTH) + 1; /* write scrambled password according to server capabilities */ if (passwd[0]) @@ -736,7 +737,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, else *end++= '\0'; /* empty password */ /* Add database if needed */ - end= strmov(end, db ? db : "") + 1; + end= strmake(end, db ? db : "", NAME_LEN) + 1; /* Write authentication package */ simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9962a108e45..59f0150aa7a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -15857,6 +15857,99 @@ static void test_bug29306() DBUG_VOID_RETURN; } + +/** + Bug#31669 Buffer overflow in mysql_change_user() +*/ + +#define LARGE_BUFFER_SIZE 2048 + +static void test_bug31669() +{ + int rc; + static char buff[LARGE_BUFFER_SIZE+1]; +#ifndef EMBEDDED_LIBRARY + static char user[USERNAME_LENGTH+1]; + static char db[NAME_LEN+1]; + static char query[LARGE_BUFFER_SIZE*2]; +#endif + + DBUG_ENTER("test_bug31669"); + myheader("test_bug31669"); + + rc= mysql_change_user(mysql, NULL, NULL, NULL); + DIE_UNLESS(rc); + + rc= mysql_change_user(mysql, "", "", ""); + DIE_UNLESS(rc); + + memset(buff, 'a', sizeof(buff)); + + rc= mysql_change_user(mysql, buff, buff, buff); + DIE_UNLESS(rc); + + rc = mysql_change_user(mysql, opt_user, opt_password, current_db); + DIE_UNLESS(!rc); + +#ifndef EMBEDDED_LIBRARY + memset(db, 'a', sizeof(db)); + db[NAME_LEN]= 0; + strxmov(query, "CREATE DATABASE IF NOT EXISTS ", db, NullS); + rc= mysql_query(mysql, query); + myquery(rc); + + memset(user, 'b', sizeof(user)); + user[USERNAME_LENGTH]= 0; + memset(buff, 'c', sizeof(buff)); + buff[LARGE_BUFFER_SIZE]= 0; + strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'%' IDENTIFIED BY " + "'", buff, "' WITH GRANT OPTION", NullS); + rc= mysql_query(mysql, query); + myquery(rc); + + rc= mysql_query(mysql, "FLUSH PRIVILEGES"); + myquery(rc); + + rc= mysql_change_user(mysql, user, buff, db); + DIE_UNLESS(!rc); + + user[USERNAME_LENGTH-1]= 'a'; + rc= mysql_change_user(mysql, user, buff, db); + DIE_UNLESS(rc); + + user[USERNAME_LENGTH-1]= 'b'; + buff[LARGE_BUFFER_SIZE-1]= 'd'; + rc= mysql_change_user(mysql, user, buff, db); + DIE_UNLESS(rc); + + buff[LARGE_BUFFER_SIZE-1]= 'c'; + db[NAME_LEN-1]= 'e'; + rc= mysql_change_user(mysql, user, buff, db); + DIE_UNLESS(rc); + + db[NAME_LEN-1]= 'a'; + rc= mysql_change_user(mysql, user, buff, db); + DIE_UNLESS(!rc); + + rc= mysql_change_user(mysql, user + 1, buff + 1, db + 1); + DIE_UNLESS(rc); + + rc = mysql_change_user(mysql, opt_user, opt_password, current_db); + DIE_UNLESS(!rc); + + strxmov(query, "DROP DATABASE ", db, NullS); + rc= mysql_query(mysql, query); + myquery(rc); + + strxmov(query, "DELETE FROM mysql.user WHERE User='", user, "'", NullS); + rc= mysql_query(mysql, query); + myquery(rc); + DIE_UNLESS(mysql_affected_rows(mysql) == 1); +#endif + + DBUG_VOID_RETURN; +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -16149,6 +16242,7 @@ static struct my_tests_st my_tests[]= { { "test_bug27592", test_bug27592 }, { "test_bug29948", test_bug29948 }, { "test_bug29306", test_bug29306 }, + { "test_bug31669", test_bug31669 }, { 0, 0 } }; From b2264ff81040fa021671181d8098778964458033 Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Tue, 23 Oct 2007 18:03:51 +0400 Subject: [PATCH 51/92] Patch for BUG#30736: Row Size Too Large Error Creating a Table and Inserting Data. The problem was that under some circumstances Field class was not properly initialized before calling create_length_to_internal_length() function, which led to assert failure. The fix is to do the proper initialization. The user-visible problem was that under some circumstances CREATE TABLE ... SELECT statement crashed the server or led to wrong error message (wrong results). --- mysql-test/r/select.result | 35 +++++++++++++++++++++++++++ mysql-test/t/select.test | 48 ++++++++++++++++++++++++++++++++++++++ sql/sql_table.cc | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index ed120a1bbb8..76022053702 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4096,4 +4096,39 @@ SELECT `x` FROM v3; x 1 DROP VIEW v1, v2, v3; + +# +# Bug#30736: Row Size Too Large Error Creating a Table and +# Inserting Data. +# +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; + +CREATE TABLE t1( +c1 DECIMAL(10, 2), +c2 FLOAT); + +INSERT INTO t1 VALUES (0, 1), (2, 3), (4, 5); + +CREATE TABLE t2( +c3 DECIMAL(10, 2)) +SELECT +c1 * c2 AS c3 +FROM t1; + +SELECT * FROM t1; +c1 c2 +0.00 1 +2.00 3 +4.00 5 + +SELECT * FROM t2; +c3 +0.00 +6.00 +20.00 + +DROP TABLE t1; +DROP TABLE t2; + End of 5.0 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 5c30a17e08e..6deb951c4e8 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3484,4 +3484,52 @@ DROP VIEW v1, v2, v3; --enable_ps_protocol +########################################################################### + +--echo +--echo # +--echo # Bug#30736: Row Size Too Large Error Creating a Table and +--echo # Inserting Data. +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +--echo + +CREATE TABLE t1( + c1 DECIMAL(10, 2), + c2 FLOAT); + +--echo + +INSERT INTO t1 VALUES (0, 1), (2, 3), (4, 5); + +--echo + +CREATE TABLE t2( + c3 DECIMAL(10, 2)) + SELECT + c1 * c2 AS c3 + FROM t1; + +--echo + +SELECT * FROM t1; + +--echo + +SELECT * FROM t2; + +--echo + +DROP TABLE t1; +DROP TABLE t2; + +--echo + +########################################################################### + --echo End of 5.0 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6cbe98fe862..b5628ab011b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -955,8 +955,8 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->length= dup_field->char_length; sql_field->pack_length= dup_field->pack_length; sql_field->key_length= dup_field->key_length; - sql_field->create_length_to_internal_length(); sql_field->decimals= dup_field->decimals; + sql_field->create_length_to_internal_length(); sql_field->unireg_check= dup_field->unireg_check; /* We're making one field from two, the result field will have From 2bc41b7e1e07b5c28e498175518c72afa8f43b25 Mon Sep 17 00:00:00 2001 From: "malff@lambda.hsd1.co.comcast.net." <> Date: Wed, 24 Oct 2007 19:01:08 -0600 Subject: [PATCH 52/92] Bug#30854 (Tables name show as binary in slave err msg on vm-win2003-64-b) The root cause of this defect is that a call to my_error() is using a 'LEX_STRING' parameter instead of a 'char*' This patch fixes the failing calls to my_error(), as well as similar calls found during investigation. This is a compiling bug (see the instrumentation in the bug report), no test cases provided. --- sql/sql_base.cc | 2 +- sql/sql_table.cc | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c4e90165ced..6307564c14f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7393,7 +7393,7 @@ open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, else { /* only VIEWs are supported now */ - my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), share->path, parser->type()->str); + my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), share->path.str, parser->type()->str); goto err; } DBUG_RETURN(0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 462b944e635..64d739aae7e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5200,7 +5200,8 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, if (error == HA_ERR_WRONG_COMMAND) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->s->table_name); + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), + table->s->table_name.str); error= 0; } else if (error) table->file->print_error(error, MYF(0)); @@ -5392,7 +5393,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { if (def->change && ! def->field) { - my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name); + my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str); goto err; } /* @@ -5427,7 +5428,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, } if (!find) { - my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name); + my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str); goto err; } find_it.after(def); // Put element after this @@ -5437,7 +5438,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (alter_info->alter_list.elements) { my_error(ER_BAD_FIELD_ERROR, MYF(0), - alter_info->alter_list.head()->name, table->s->table_name); + alter_info->alter_list.head()->name, table->s->table_name.str); goto err; } if (!new_create_list.elements) From a7f7875578e6c7f94bccb27a95e69c65fec32810 Mon Sep 17 00:00:00 2001 From: "knielsen@loke.(none)[knielsen]" <> Date: Thu, 25 Oct 2007 07:57:18 +0200 Subject: [PATCH 53/92] BUG#31761: Code for cluster is not safe for strict-alias optimization in new gcc Fix problem with AttributeHeader::init() seen with gcc 4.2.1. Using the same object as both Uint32 and class AttributeHeader violates strict aliasing rule. --- ndb/include/kernel/AttributeHeader.hpp | 10 +++++----- ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp | 5 +++-- ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp | 11 +++++------ ndb/src/kernel/blocks/dbutil/DbUtil.cpp | 5 ++--- ndb/src/ndbapi/NdbOperationDefine.cpp | 15 ++++++--------- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/ndb/include/kernel/AttributeHeader.hpp b/ndb/include/kernel/AttributeHeader.hpp index 3cb432067eb..239b1e08db4 100644 --- a/ndb/include/kernel/AttributeHeader.hpp +++ b/ndb/include/kernel/AttributeHeader.hpp @@ -42,8 +42,7 @@ public: STATIC_CONST( FRAGMENT_MEMORY= 0xFFF9 ); /** Initialize AttributeHeader at location aHeaderPtr */ - static AttributeHeader& init(void* aHeaderPtr, Uint32 anAttributeId, - Uint32 aDataSize); + static void init(Uint32* aHeaderPtr, Uint32 anAttributeId, Uint32 aDataSize); /** Returns size of AttributeHeader (usually one or two words) */ Uint32 getHeaderSize() const; // In 32-bit words @@ -101,10 +100,11 @@ public: */ inline -AttributeHeader& AttributeHeader::init(void* aHeaderPtr, Uint32 anAttributeId, - Uint32 aDataSize) +void AttributeHeader::init(Uint32* aHeaderPtr, Uint32 anAttributeId, + Uint32 aDataSize) { - return * new (aHeaderPtr) AttributeHeader(anAttributeId, aDataSize); + AttributeHeader ah(anAttributeId, aDataSize); + *aHeaderPtr = ah.m_value; } inline diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index a94d2f70343..a20e6ca59d2 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1578,8 +1578,8 @@ int Dbtup::interpreterNextLab(Signal* signal, Uint32 TdataForUpdate[3]; Uint32 Tlen; - AttributeHeader& ah = AttributeHeader::init(&TdataForUpdate[0], - TattrId, TattrNoOfWords); + AttributeHeader ah(TattrId, TattrNoOfWords); + TdataForUpdate[0] = ah.m_value; TdataForUpdate[1] = TregMemBuffer[theRegister + 2]; TdataForUpdate[2] = TregMemBuffer[theRegister + 3]; Tlen = TattrNoOfWords + 1; @@ -1595,6 +1595,7 @@ int Dbtup::interpreterNextLab(Signal* signal, // Write a NULL value into the attribute /* --------------------------------------------------------- */ ah.setNULL(); + TdataForUpdate[0] = ah.m_value; Tlen = 1; }//if int TnoDataRW= updateAttributes(pagePtr, diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index 8a55777ac05..7e617764645 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -677,8 +677,6 @@ bool Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr) { Uint32 keyReadBuffer[MAX_KEY_SIZE_IN_WORDS]; - Uint32 attributeHeader; - AttributeHeader* ahOut = (AttributeHeader*)&attributeHeader; AttributeHeader ahIn(*updateBuffer); Uint32 attributeId = ahIn.getAttributeId(); Uint32 attrDescriptorIndex = regTabPtr->tabDescriptor + (attributeId << ZAD_LOG_SIZE); @@ -701,16 +699,17 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr) ReadFunction f = regTabPtr->readFunctionArray[attributeId]; - AttributeHeader::init(&attributeHeader, attributeId, 0); + AttributeHeader attributeHeader(attributeId, 0); tOutBufIndex = 0; tMaxRead = MAX_KEY_SIZE_IN_WORDS; bool tmp = tXfrmFlag; tXfrmFlag = true; - ndbrequire((this->*f)(&keyReadBuffer[0], ahOut, attrDescriptor, attributeOffset)); + ndbrequire((this->*f)(&keyReadBuffer[0], &attributeHeader, attrDescriptor, + attributeOffset)); tXfrmFlag = tmp; - ndbrequire(tOutBufIndex == ahOut->getDataSize()); - if (ahIn.getDataSize() != ahOut->getDataSize()) { + ndbrequire(tOutBufIndex == attributeHeader.getDataSize()); + if (ahIn.getDataSize() != attributeHeader.getDataSize()) { ljam(); return true; }//if diff --git a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp index 0f45c407d83..316f71ff24c 100644 --- a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp +++ b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp @@ -1169,9 +1169,7 @@ DbUtil::prepareOperation(Signal* signal, PreparePtr prepPtr) /************************************************************** * Attribute found - store in mapping (AttributeId, Position) **************************************************************/ - AttributeHeader & attrMap = - AttributeHeader::init(attrMappingIt.data, - attrDesc.AttributeId, // 1. Store AttrId + AttributeHeader attrMap(attrDesc.AttributeId, // 1. Store AttrId 0); if (attrDesc.AttributeKeyFlag) { @@ -1200,6 +1198,7 @@ DbUtil::prepareOperation(Signal* signal, PreparePtr prepPtr) return; } } + *(attrMappingIt.data) = attrMap.m_value; #if 0 ndbout << "BEFORE: attrLength: " << attrLength << endl; #endif diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp index 835e33dfb40..f814f1c1d04 100644 --- a/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -363,9 +363,8 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue) return NULL; }//if }//if - Uint32 ah; - AttributeHeader::init(&ah, tAttrInfo->m_attrId, 0); - if (insertATTRINFO(ah) != -1) { + AttributeHeader ah(tAttrInfo->m_attrId, 0); + if (insertATTRINFO(ah.m_value) != -1) { // Insert Attribute Id into ATTRINFO part. /************************************************************************ @@ -496,12 +495,11 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, tAttrId = tAttrInfo->m_attrId; const char *aValue = aValuePassed; - Uint32 ahValue; if (aValue == NULL) { if (tAttrInfo->m_nullable) { - AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, 0); + AttributeHeader ah(tAttrId, 0); ah.setNULL(); - insertATTRINFO(ahValue); + insertATTRINFO(ah.m_value); // Insert Attribute Id with the value // NULL into ATTRINFO part. DBUG_RETURN(0); @@ -534,9 +532,8 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, }//if const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word const Uint32 sizeInWords = sizeInBytes / 4; // Excluding bits in last word - AttributeHeader& ah = AttributeHeader::init(&ahValue, tAttrId, - totalSizeInWords); - insertATTRINFO( ahValue ); + AttributeHeader ah(tAttrId, totalSizeInWords); + insertATTRINFO( ah.m_value ); /*********************************************************************** * Check if the pointer of the value passed is aligned on a 4 byte boundary. From e16f03cd64094f4e5a31c8c0896b5c46dd083713 Mon Sep 17 00:00:00 2001 From: "knielsen@loke.(none)[knielsen]" <> Date: Thu, 25 Oct 2007 08:40:42 +0200 Subject: [PATCH 54/92] BUG#31810: Potential infinite loop with autoincrement failures in ndb Fix extra semicolon causing if-statement to be disabled. --- sql/ha_ndbcluster.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b74b04f4238..f5207f8ca03 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2302,7 +2302,7 @@ int ha_ndbcluster::write_row(byte *record) auto_value, 1) == -1) { if (--retries && - ndb->getNdbError().status == NdbError::TemporaryError); + ndb->getNdbError().status == NdbError::TemporaryError) { my_sleep(retry_sleep); continue; @@ -4862,7 +4862,7 @@ ulonglong ha_ndbcluster::get_auto_increment() auto_value, cache_size, step, start)) { if (--retries && - ndb->getNdbError().status == NdbError::TemporaryError); + ndb->getNdbError().status == NdbError::TemporaryError) { my_sleep(retry_sleep); continue; From 39b1aaed0f55fae8fb4106f064cb9069a790f59a Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Fri, 26 Oct 2007 11:42:33 +0200 Subject: [PATCH 55/92] commit of WL#3686 test case already in 5.1 to get regression testing, no code committed --- .../suite/ndb/r/ndb_update_no_read.result | 75 ++++++++++++++++++ .../suite/ndb/t/ndb_update_no_read.test | 79 +++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 mysql-test/suite/ndb/r/ndb_update_no_read.result create mode 100644 mysql-test/suite/ndb/t/ndb_update_no_read.test diff --git a/mysql-test/suite/ndb/r/ndb_update_no_read.result b/mysql-test/suite/ndb/r/ndb_update_no_read.result new file mode 100644 index 00000000000..4373800d338 --- /dev/null +++ b/mysql-test/suite/ndb/r/ndb_update_no_read.result @@ -0,0 +1,75 @@ +DROP TABLE IF EXISTS t1; +create table t1 (a int not null primary key, b int not null, c int, +unique index_b (b) using hash) +engine ndb; +insert into t1 values (1,10,1),(2,9,1),(3,8,1),(4,7,1),(5,6,1),(6,5,2),(7,4,2),(8,3,2), +(9,2,2),(10,1,2); +update t1 set c = 111, b = 20 where a = 1; +select * from t1 where a = 1 order by a; +a b c +1 20 111 +delete from t1 where a = 1; +select * from t1 where a = 1 order by a; +a b c +update t1 set c = 12, b = 19 where b = 2; +select * from t1 where b = 2 order by a; +a b c +delete from t1 where b = 19; +select * from t1 where b = 19 order by a; +a b c +update t1 set c = 22 where a = 10 or a >= 10; +select * from t1 order by a; +a b c +2 9 1 +3 8 1 +4 7 1 +5 6 1 +6 5 2 +7 4 2 +8 3 2 +10 1 22 +update t1 set c = 23 where a in (8,10); +select * from t1 order by a; +a b c +2 9 1 +3 8 1 +4 7 1 +5 6 1 +6 5 2 +7 4 2 +8 3 23 +10 1 23 +update t1 set c = 23 where a in (7,8) or a >= 10; +select * from t1 order by a; +a b c +2 9 1 +3 8 1 +4 7 1 +5 6 1 +6 5 2 +7 4 23 +8 3 23 +10 1 23 +update t1 set c = 11 where a = 3 or b = 7; +select * from t1 where a = 3 or b = 7 order by a; +a b c +3 8 11 +4 7 11 +update t1 set a = 13, b = 20 where a = 3; +select * from t1 where a = 13 order by a; +a b c +13 20 11 +update t1 set a = 12, b = 19 where b = 7; +select * from t1 where b = 19 order by a; +a b c +12 19 11 +select * from t1 where b = 7 order by a; +a b c +update t1 set c = 12, b = 29 where a = 5 and b = 6; +select * from t1 where b = 19 order by a; +a b c +12 19 11 +delete from t1 where b = 6 and c = 12; +select * from t1 where b = 6 order by a; +a b c +drop table t1; diff --git a/mysql-test/suite/ndb/t/ndb_update_no_read.test b/mysql-test/suite/ndb/t/ndb_update_no_read.test new file mode 100644 index 00000000000..60bea53b7b5 --- /dev/null +++ b/mysql-test/suite/ndb/t/ndb_update_no_read.test @@ -0,0 +1,79 @@ +-- source include/have_ndb.inc +-- source include/not_embedded.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +# +# New test case for WL 3686 (which is not until CGE-6.3) +# but test is committed in 5.1 to verify consistant results. +# +# When only constant expressions in update statements and +# only PK or UK in WHERE clause. No extra WHERE parts are +# allowed. WL #3687 takes of more advanced variants of +# avoiding the read before the update/delete + +create table t1 (a int not null primary key, b int not null, c int, + unique index_b (b) using hash) +engine ndb; + +insert into t1 values (1,10,1),(2,9,1),(3,8,1),(4,7,1),(5,6,1),(6,5,2),(7,4,2),(8,3,2), + (9,2,2),(10,1,2); + +# These ones should use optimisation + +update t1 set c = 111, b = 20 where a = 1; + +select * from t1 where a = 1 order by a; + +delete from t1 where a = 1; + +select * from t1 where a = 1 order by a; + +update t1 set c = 12, b = 19 where b = 2; + +select * from t1 where b = 2 order by a; + +delete from t1 where b = 19; + +select * from t1 where b = 19 order by a; + +update t1 set c = 22 where a = 10 or a >= 10; + +select * from t1 order by a; + +update t1 set c = 23 where a in (8,10); + +select * from t1 order by a; + +update t1 set c = 23 where a in (7,8) or a >= 10; + +select * from t1 order by a; + +# These ones should not use optimisation + +update t1 set c = 11 where a = 3 or b = 7; + +select * from t1 where a = 3 or b = 7 order by a; + +update t1 set a = 13, b = 20 where a = 3; + +select * from t1 where a = 13 order by a; + +update t1 set a = 12, b = 19 where b = 7; + +select * from t1 where b = 19 order by a; + +select * from t1 where b = 7 order by a; + +update t1 set c = 12, b = 29 where a = 5 and b = 6; + +select * from t1 where b = 19 order by a; + +delete from t1 where b = 6 and c = 12; + +select * from t1 where b = 6 order by a; + +drop table t1; + From 93c95156bc0dc3d9ee9d7127cda95a51b73a15b3 Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Fri, 26 Oct 2007 11:43:05 +0200 Subject: [PATCH 56/92] correct unused code --- sql/sql_update.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index cb3f2fece89..7673126314f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -679,7 +679,7 @@ int mysql_update(THD *thd, */ if (will_batch && ((error= table->file->exec_bulk_update(&dup_key_found)) || - !dup_key_found)) + dup_key_found)) { if (error) { From ee25b4f56f417c09f11cda1ddd0347cec8b76c9f Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Mon, 29 Oct 2007 15:42:49 +0300 Subject: [PATCH 57/92] Fix for BUG#27610: ALTER TABLE ROW_FORMAT=... does not rebuild the table. The problem was that ROW_FORMAT clause in ALTER TABLE did not trigger table reconstruction. The fix is to rebuild a table if ROW_FORMAT is specified. --- mysql-test/include/mix1.inc | 49 ++++++++++++++++++++++++++++++++ mysql-test/r/innodb_mysql.result | 34 ++++++++++++++++++++++ sql/sql_table.cc | 1 + 3 files changed, 84 insertions(+) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index aee5613ff35..df9d79157af 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1019,6 +1019,55 @@ SELECT * FROM t1 ORDER BY b DESC, a ASC; DROP TABLE t1; +########################################################################### + +--echo +--echo # +--echo # Bug#27610: ALTER TABLE ROW_FORMAT=... does not rebuild the table. +--echo # + +--echo +--echo # - prepare; +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo + +CREATE TABLE t1(c INT) + ENGINE = InnoDB + ROW_FORMAT = COMPACT; + +--echo +--echo # - initial check; +--echo + +SELECT table_schema, table_name, row_format +FROM INFORMATION_SCHEMA.TABLES +WHERE table_schema = DATABASE() AND table_name = 't1'; + +--echo +--echo # - change ROW_FORMAT and check; +--echo + +ALTER TABLE t1 ROW_FORMAT = REDUNDANT; + +--echo + +SELECT table_schema, table_name, row_format +FROM INFORMATION_SCHEMA.TABLES +WHERE table_schema = DATABASE() AND table_name = 't1'; + +--echo +--echo # - that's it, cleanup. +--echo + +DROP TABLE t1; + +########################################################################### + --echo End of 5.0 tests # Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 3a6758b38f4..2a0f9a930b8 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1286,6 +1286,40 @@ a b 2 2 3 2 1 1 +DROP TABLE t1; + +# +# Bug#27610: ALTER TABLE ROW_FORMAT=... does not rebuild the table. +# + +# - prepare; + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1(c INT) +ENGINE = InnoDB +ROW_FORMAT = COMPACT; + +# - initial check; + +SELECT table_schema, table_name, row_format +FROM INFORMATION_SCHEMA.TABLES +WHERE table_schema = DATABASE() AND table_name = 't1'; +table_schema table_name row_format +test t1 Compact + +# - change ROW_FORMAT and check; + +ALTER TABLE t1 ROW_FORMAT = REDUNDANT; + +SELECT table_schema, table_name, row_format +FROM INFORMATION_SCHEMA.TABLES +WHERE table_schema = DATABASE() AND table_name = 't1'; +table_schema table_name row_format +test t1 Redundant + +# - that's it, cleanup. + DROP TABLE t1; End of 5.0 tests CREATE TABLE `t2` ( diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 64d739aae7e..2bd89d4a0ae 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4985,6 +4985,7 @@ compare_tables(TABLE *table, create_info->used_fields & HA_CREATE_USED_ENGINE || create_info->used_fields & HA_CREATE_USED_CHARSET || create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET || + create_info->used_fields & HA_CREATE_USED_ROW_FORMAT || (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) || order_num || !table->s->mysql_version || From 47c381fbb42cd8129fff8b99c70d44d6070532c1 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Tue, 30 Oct 2007 15:25:39 +0300 Subject: [PATCH 58/92] Make sure rpl.rpl_innodb_mixed_dml passes even if rpl_mixed.dat is read-only. This is important for a development environment where not all source files are checked out. --- mysql-test/suite/rpl/include/rpl_mixed_dml.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/include/rpl_mixed_dml.inc b/mysql-test/suite/rpl/include/rpl_mixed_dml.inc index 96dfdbed541..a3ff022c43c 100644 --- a/mysql-test/suite/rpl/include/rpl_mixed_dml.inc +++ b/mysql-test/suite/rpl/include/rpl_mixed_dml.inc @@ -53,7 +53,7 @@ DELETE FROM t2 WHERE a = 2; --echo ******************** LOAD DATA INFILE ******************** --exec cp ./suite/rpl/data/rpl_mixed.dat $MYSQLTEST_VARDIR/tmp/ LOAD DATA INFILE '../tmp/rpl_mixed.dat' INTO TABLE t1 FIELDS TERMINATED BY '|' ; ---exec rm $MYSQLTEST_VARDIR/tmp/rpl_mixed.dat +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_mixed.dat SELECT * FROM t1; --source suite/rpl/include/rpl_mixed_check_select.inc --source suite/rpl/include/rpl_mixed_clear_tables.inc From 5a09edd203ea125b846af82935b7d7e5da430435 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Tue, 30 Oct 2007 15:39:50 +0300 Subject: [PATCH 59/92] Fix failing init_connect.test (5.1-runtime). --- sql/sql_connect.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index afd97c27a55..c4367b2a8fb 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1030,7 +1030,17 @@ static void prepare_new_connection_state(THD* thd) if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) { execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); - if (thd->net.report_error) + /* + execute_init_command calls net_send_error. + If there was an error during execution of the init statements, + the error at this moment is present in thd->net.last_error and also + thd->is_slave_error and thd->net.report_error are set. + net_send_error sends the contents of thd->net.last_error and + clears thd->net.report_error. It doesn't, however, clean + thd->is_slave_error or thd->net.last_error. Here we make use of this + fact. + */ + if (thd->is_slave_error) { thd->killed= THD::KILL_CONNECTION; sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), From b0e90a43cbfac47614f6fb6360616644690ec15a Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Tue, 30 Oct 2007 14:04:41 +0100 Subject: [PATCH 60/92] correct manual merge --- .../rpl/r/rpl_extraColmaster_innodb.result | 24 +++++++++---------- .../rpl/r/rpl_extraColmaster_myisam.result | 24 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result b/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result index 28985eb8cba..a7d9e12aabd 100644 --- a/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result @@ -563,7 +563,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -581,7 +581,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -638,7 +638,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -656,7 +656,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -1703,7 +1703,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -1721,7 +1721,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -1778,7 +1778,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -1796,7 +1796,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -2843,7 +2843,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -2861,7 +2861,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -2918,7 +2918,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -2936,7 +2936,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; diff --git a/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result b/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result index 966f97e0578..a8762d447d6 100644 --- a/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result +++ b/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result @@ -563,7 +563,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -581,7 +581,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -638,7 +638,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -656,7 +656,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -1703,7 +1703,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -1721,7 +1721,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -1778,7 +1778,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -1796,7 +1796,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -2843,7 +2843,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -2861,7 +2861,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -2918,7 +2918,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -2936,7 +2936,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; From 38ce0fc24d88d6234c07e795421e60f3a6332b35 Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Tue, 30 Oct 2007 14:52:12 +0100 Subject: [PATCH 61/92] correct result file --- .../rpl_ndb/r/rpl_ndb_extraColMaster.result | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result index 38c8ab2afc5..d5d4658c01f 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraColMaster.result @@ -563,7 +563,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -581,7 +581,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -638,7 +638,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -656,7 +656,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -1703,7 +1703,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 Skip_Counter 0 Exec_Master_Log_Pos # @@ -1721,7 +1721,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 5, test.t10 has type 254 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -1778,7 +1778,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1532 +Last_Errno 1534 Last_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 Skip_Counter 0 Exec_Master_Log_Pos # @@ -1796,7 +1796,7 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno # Last_IO_Error # -Last_SQL_Errno 1532 +Last_SQL_Errno 1534 Last_SQL_Error Table definition on master and slave does not match: Column 2 type mismatch - received type 252, test.t11 has type 15 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; From e4b353c40c551e4ac0832dd0106219e7e0b716ba Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Tue, 30 Oct 2007 20:08:16 +0300 Subject: [PATCH 62/92] Use an inline getter method (thd->is_error()) to query if there is an error in THD. In future the error may be stored elsewhere (not in net.report_error) and it's important to start using an opaque getter to simplify merges. --- sql/filesort.cc | 4 ++-- sql/ha_ndbcluster_binlog.cc | 2 +- sql/item_func.cc | 4 ++-- sql/item_subselect.cc | 2 +- sql/set_var.cc | 2 +- sql/sp.cc | 2 +- sql/sp_head.cc | 6 +++--- sql/sql_base.cc | 10 +++++----- sql/sql_class.cc | 4 ++-- sql/sql_class.h | 16 +++++++++++++++- sql/sql_connect.cc | 6 +++--- sql/sql_delete.cc | 8 ++++---- sql/sql_insert.cc | 12 ++++++------ sql/sql_parse.cc | 22 +++++++++++----------- sql/sql_prepare.cc | 2 +- sql/sql_select.cc | 30 +++++++++++++++--------------- sql/sql_union.cc | 2 +- sql/sql_update.cc | 6 +++--- sql/sql_view.cc | 6 +++--- sql/sql_yacc.yy | 4 ++-- 20 files changed, 82 insertions(+), 68 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index c074f90e780..2e6f0ecaf05 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -555,7 +555,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, else file->unlock_row(); /* It does not make sense to read more keys in case of a fatal error */ - if (thd->net.report_error) + if (thd->is_error()) break; } if (quick_select) @@ -573,7 +573,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, file->ha_rnd_end(); } - if (thd->net.report_error) + if (thd->is_error()) DBUG_RETURN(HA_POS_ERROR); /* Signal we should use orignal column read and write maps */ diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index c22d5ac53f5..fc35a7a930e 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -271,7 +271,7 @@ static void run_query(THD *thd, char *buf, char *end, sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d", buf, thd->net.last_error, thd->net.last_errno, thd_ndb->m_error_code, - thd->net.report_error, thd->is_slave_error); + (int) thd->is_error(), thd->is_slave_error); } thd->options= save_thd_options; diff --git a/sql/item_func.cc b/sql/item_func.cc index 64574a9ad74..2d4d61de61b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -187,7 +187,7 @@ Item_func::fix_fields(THD *thd, Item **ref) } } fix_length_and_dec(); - if (thd->net.report_error) // An error inside fix_length_and_dec occured + if (thd->is_error()) // An error inside fix_length_and_dec occured return TRUE; fixed= 1; return FALSE; @@ -4073,7 +4073,7 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val) NOTES For now it always return OK. All problem with value evaluating - will be caught by thd->net.report_error check in sql_set_variables(). + will be caught by thd->is_error() check in sql_set_variables(). RETURN FALSE OK. diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 843c6ced263..8eb7421f854 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -248,7 +248,7 @@ bool Item_subselect::exec() { int res; - if (thd->net.report_error) + if (thd->is_error()) /* Do not execute subselect in case of a fatal error */ return 1; diff --git a/sql/set_var.cc b/sql/set_var.cc index 138c71fa559..11874b1020c 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3051,7 +3051,7 @@ int sql_set_variables(THD *thd, List *var_list) if ((error= var->check(thd))) goto err; } - if (!(error= test(thd->net.report_error))) + if (!(error= test(thd->is_error()))) { it.rewind(); while ((var= it++)) diff --git a/sql/sp.cc b/sql/sp.cc index 1b5d8ca87b8..b4f0ec7729b 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1866,7 +1866,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, an error with it's return value without calling my_error(), we set the generic "mysql.proc table corrupt" error here. */ - if (!thd->net.report_error) + if (! thd->is_error()) { /* SP allows full NAME_LEN chars thus he have to allocate enough diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f7ab9bac3b1..6e8749aa745 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -370,7 +370,7 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) thd->abort_on_warning= save_abort_on_warning; thd->transaction.stmt.modified_non_trans_table= save_stmt_modified_non_trans_table; - if (thd->net.report_error) + if (thd->is_error()) { /* Return error status if something went wrong. */ err_status= TRUE; @@ -1277,7 +1277,7 @@ sp_head::execute(THD *thd) done: DBUG_PRINT("info", ("err_status: %d killed: %d is_slave_error: %d report_error: %d", err_status, thd->killed, thd->is_slave_error, - thd->net.report_error)); + thd->is_error())); if (thd->killed) err_status= TRUE; @@ -2673,7 +2673,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, cleanup_items() is called in sp_head::execute() */ - DBUG_RETURN(res || thd->net.report_error); + DBUG_RETURN(res || thd->is_error()); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 10e6716cadf..223485f1e42 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6260,7 +6260,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, thd->lex->allow_sum_func= save_allow_sum_func; thd->mark_used_columns= save_mark_used_columns; DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); - DBUG_RETURN(test(thd->net.report_error)); + DBUG_RETURN(test(thd->is_error())); } @@ -6804,7 +6804,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, select_lex->conds_processed_with_permanent_arena= 1; } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; - DBUG_RETURN(test(thd->net.report_error)); + DBUG_RETURN(test(thd->is_error())); err_no_arena: select_lex->is_item_list_lookup= save_is_item_list_lookup; @@ -6886,7 +6886,7 @@ fill_record(THD * thd, List &fields, List &values, goto err; } } - DBUG_RETURN(thd->net.report_error); + DBUG_RETURN(thd->is_error()); err: if (table) table->auto_increment_field_not_null= FALSE; @@ -6971,7 +6971,7 @@ fill_record(THD *thd, Field **ptr, List &values, bool ignore_errors) table= (*ptr)->table; table->auto_increment_field_not_null= FALSE; } - while ((field = *ptr++) && !thd->net.report_error) + while ((field = *ptr++) && ! thd->is_error()) { value=v++; table= field->table; @@ -6980,7 +6980,7 @@ fill_record(THD *thd, Field **ptr, List &values, bool ignore_errors) if (value->save_in_field(field, 0) < 0) goto err; } - DBUG_RETURN(thd->net.report_error); + DBUG_RETURN(thd->is_error()); err: if (table) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d77e531ec13..707c8e83007 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1368,7 +1368,7 @@ bool select_send::send_data(List &items) thd->sent_row_count++; if (!thd->vio_ok()) DBUG_RETURN(0); - if (!thd->net.report_error) + if (! thd->is_error()) DBUG_RETURN(protocol->write()); protocol->remove_last_row(); DBUG_RETURN(1); @@ -1389,7 +1389,7 @@ bool select_send::send_eof() mysql_unlock_tables(thd, thd->lock); thd->lock=0; } - if (!thd->net.report_error) + if (! thd->is_error()) { ::send_eof(thd); status= 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index a7f196cd825..a3e71e183f3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1468,7 +1468,7 @@ public: bool in_lock_tables; /** True if a slave error. Causes the slave to stop. Not the same - as the statement execution error (net.report_error), since + as the statement execution error (is_error()), since a statement may be expected to return an error, e.g. because it returned an error on master, and this is OK on the slave. */ @@ -1716,6 +1716,20 @@ public: net.report_error= 1; DBUG_PRINT("error",("Fatal error set")); } + /** + TRUE if there is an error in the error stack. + + Please use this method instead of direct access to + net.report_error. + + If TRUE, the current (sub)-statement should be aborted. + The main difference between this member and is_fatal_error + is that a fatal error can not be handled by a stored + procedure continue handler, whereas a normal error can. + + To raise this flag, use my_error(). + */ + inline bool is_error() const { return net.report_error; } inline CHARSET_INFO *charset() { return variables.character_set_client; } void update_charset(); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index afd97c27a55..006cca4ee90 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -975,12 +975,12 @@ void end_connection(THD *thd) decrease_user_connections(thd->user_connect); if (thd->killed || - net->error && net->vio != 0 && net->report_error) + net->error && net->vio != 0 && thd->is_error()) { statistic_increment(aborted_threads,&LOCK_status); } - if (net->error && net->vio != 0 && net->report_error) + if (net->error && net->vio != 0 && thd->is_error()) { if (!thd->killed && thd->variables.log_warnings > 1) { @@ -1030,7 +1030,7 @@ static void prepare_new_connection_state(THD* thd) if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) { execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); - if (thd->net.report_error) + if (thd->is_error()) { thd->killed= THD::KILL_CONNECTION; sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 4c57fad8d87..219dc90429b 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -252,10 +252,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->mark_columns_needed_for_delete(); while (!(error=info.read_record(&info)) && !thd->killed && - !thd->net.report_error) + ! thd->is_error()) { - // thd->net.report_error is tested to disallow delete row on error - if (!(select && select->skip_record())&& !thd->net.report_error ) + // thd->is_error() is tested to disallow delete row on error + if (!(select && select->skip_record())&& ! thd->is_error() ) { if (table->triggers && @@ -389,7 +389,7 @@ cleanup: send_ok(thd, (ha_rows) thd->row_count_func); DBUG_PRINT("info",("%ld records deleted",(long) deleted)); } - DBUG_RETURN(error >= 0 || thd->net.report_error); + DBUG_RETURN(error >= 0 || thd->is_error()); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e868afede51..077141c4d7a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -738,7 +738,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table->triggers, TRG_EVENT_INSERT)) { - if (values_list.elements != 1 && !thd->net.report_error) + if (values_list.elements != 1 && ! thd->is_error()) { info.records++; continue; @@ -769,7 +769,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table->triggers, TRG_EVENT_INSERT)) { - if (values_list.elements != 1 && ! thd->net.report_error) + if (values_list.elements != 1 && ! thd->is_error()) { info.records++; continue; @@ -1909,7 +1909,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) thd->proc_info="got old table"; if (di->thd.killed) { - if (di->thd.net.report_error) + if (di->thd.is_error()) { /* Copy the error message. Note that we don't treat fatal @@ -1940,7 +1940,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) pthread_mutex_unlock(&di->mutex); if (table_list->table) { - DBUG_ASSERT(thd->net.report_error == 0); + DBUG_ASSERT(! thd->is_error()); thd->di= di; } /* Unlock the delayed insert object after its last access. */ @@ -1949,7 +1949,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) end_create: pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(thd->net.report_error); + DBUG_RETURN(thd->is_error()); } @@ -3015,7 +3015,7 @@ bool select_insert::send_data(List &values) thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields store_values(values); thd->count_cuted_fields= CHECK_FIELD_IGNORE; - if (thd->net.report_error) + if (thd->is_error()) DBUG_RETURN(1); if (table_list) // Not CREATE ... SELECT { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e6d953bcbe1..ac042960388 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -436,7 +436,7 @@ pthread_handler_t handle_bootstrap(void *arg) if (thd->is_fatal_error) break; - if (thd->net.report_error) + if (thd->is_error()) { /* The query failed, send error to log and abort bootstrap */ net_send_error(thd); @@ -990,7 +990,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_parse(thd, thd->query, thd->query_length, & found_semicolon); - while (!thd->killed && found_semicolon && !thd->net.report_error) + while (!thd->killed && found_semicolon && ! thd->is_error()) { char *next_packet= (char*) found_semicolon; net->no_send_error= 0; @@ -1355,9 +1355,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->transaction.xid_state.xid.null(); /* report error issued during command execution */ - if (thd->killed_errno() && !thd->net.report_error) + if (thd->killed_errno() && ! thd->is_error()) thd->send_kill_message(); - if (thd->net.report_error) + if (thd->is_error()) net_send_error(thd); log_slow_statement(thd); @@ -3930,7 +3930,7 @@ create_sp_error: thd->row_count_func)); else { - DBUG_ASSERT(thd->net.report_error == 1 || thd->killed); + DBUG_ASSERT(thd->is_error() || thd->killed); goto error; // Substatement should already have sent error } } @@ -4523,7 +4523,7 @@ finish: */ start_waiting_global_read_lock(thd); } - DBUG_RETURN(res || thd->net.report_error); + DBUG_RETURN(res || thd->is_error()); } @@ -5467,7 +5467,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, else #endif { - if (! thd->net.report_error) + if (! thd->is_error()) { /* Binlog logs a string starting from thd->query and having length @@ -5491,7 +5491,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, } else { - DBUG_ASSERT(thd->net.report_error); + DBUG_ASSERT(thd->is_error()); DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); @@ -6311,7 +6311,7 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List *using_fields, RETURN 0 ok - !=0 error. thd->killed or thd->net.report_error is set + !=0 error. thd->killed or thd->is_error() is set */ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, @@ -7274,10 +7274,10 @@ bool parse_sql(THD *thd, bool mysql_parse_status= MYSQLparse(thd) != 0; - /* Check that if MYSQLparse() failed, thd->net.report_error is set. */ + /* Check that if MYSQLparse() failed, thd->is_error() is set. */ DBUG_ASSERT(!mysql_parse_status || - mysql_parse_status && thd->net.report_error); + mysql_parse_status && thd->is_error()); /* Reset Lex_input_stream. */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a6cdcf14881..b1b1502f015 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2864,7 +2864,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) lex_start(thd); error= parse_sql(thd, &lip, NULL) || - thd->net.report_error || + thd->is_error() || init_param_array(this); lex->set_trg_event_type_for_tables(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fd0ce630a01..ef1151d82f3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -263,8 +263,8 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, result, unit, select_lex); } DBUG_PRINT("info",("res: %d report_error: %d", res, - thd->net.report_error)); - res|= thd->net.report_error; + thd->is_error())); + res|= thd->is_error(); if (unlikely(res)) result->abort(); @@ -491,7 +491,7 @@ JOIN::prepare(Item ***rref_pointer_array, (having->fix_fields(thd, &having) || having->check_cols(1))); select_lex->having_fix_field= 0; - if (having_fix_rc || thd->net.report_error) + if (having_fix_rc || thd->is_error()) DBUG_RETURN(-1); /* purecov: inspected */ thd->lex->allow_sum_func= save_allow_sum_func; } @@ -817,7 +817,7 @@ JOIN::optimize() } conds= optimize_cond(this, conds, join_list, &cond_value); - if (thd->net.report_error) + if (thd->is_error()) { error= 1; DBUG_PRINT("error",("Error from optimize_cond")); @@ -826,7 +826,7 @@ JOIN::optimize() { having= optimize_cond(this, having, join_list, &having_value); - if (thd->net.report_error) + if (thd->is_error()) { error= 1; DBUG_PRINT("error",("Error from optimize_cond")); @@ -1031,7 +1031,7 @@ JOIN::optimize() { ORDER *org_order= order; order=remove_const(this, order,conds,1, &simple_order); - if (thd->net.report_error) + if (thd->is_error()) { error= 1; DBUG_PRINT("error",("Error from remove_const")); @@ -1162,7 +1162,7 @@ JOIN::optimize() group_list= remove_const(this, (old_group_list= group_list), conds, rollup.state == ROLLUP::STATE_NONE, &simple_group); - if (thd->net.report_error) + if (thd->is_error()) { error= 1; DBUG_PRINT("error",("Error from remove_const")); @@ -1185,7 +1185,7 @@ JOIN::optimize() { group_list= procedure->group= remove_const(this, procedure->group, conds, 1, &simple_group); - if (thd->net.report_error) + if (thd->is_error()) { error= 1; DBUG_PRINT("error",("Error from remove_const")); @@ -2098,10 +2098,10 @@ JOIN::exec() } } } - /* XXX: When can we have here thd->net.report_error not zero? */ - if (thd->net.report_error) + /* XXX: When can we have here thd->is_error() not zero? */ + if (thd->is_error()) { - error= thd->net.report_error; + error= thd->is_error(); DBUG_VOID_RETURN; } curr_join->having= curr_join->tmp_having; @@ -2307,7 +2307,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, join->having_history= (join->having?join->having:join->tmp_having); } - if (thd->net.report_error) + if (thd->is_error()) goto err; join->exec(); @@ -2333,7 +2333,7 @@ err: { thd->proc_info="end"; err|= select_lex->cleanup(); - DBUG_RETURN(err || thd->net.report_error); + DBUG_RETURN(err || thd->is_error()); } DBUG_RETURN(join->error); } @@ -10717,7 +10717,7 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) DBUG_PRINT("error",("Error: do_select() failed")); } #endif - DBUG_RETURN(join->thd->net.report_error ? -1 : rc); + DBUG_RETURN(join->thd->is_error() ? -1 : rc); } @@ -16050,7 +16050,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) first->options | thd->options | SELECT_DESCRIBE, result, unit, first); } - DBUG_RETURN(res || thd->net.report_error); + DBUG_RETURN(res || thd->is_error()); } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 5da4b97cc5d..a48cff82715 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -58,7 +58,7 @@ bool select_union::send_data(List &values) return 0; } fill_record(thd, table->field, values, 1); - if (thd->net.report_error) + if (thd->is_error()) return 1; if ((error= table->file->ha_write_row(table->record[0]))) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4071bb86c90..036d7e06d0e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -844,7 +844,7 @@ int mysql_update(THD *thd, } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ thd->abort_on_warning= 0; - DBUG_RETURN((error >= 0 || thd->net.report_error) ? 1 : 0); + DBUG_RETURN((error >= 0 || thd->is_error()) ? 1 : 0); err: delete select; @@ -1193,8 +1193,8 @@ bool mysql_multi_update(THD *thd, OPTION_SETUP_TABLES_DONE, result, unit, select_lex); DBUG_PRINT("info",("res: %d report_error: %d", res, - thd->net.report_error)); - res|= thd->net.report_error; + (int) thd->is_error())); + res|= thd->is_error(); if (unlikely(res)) { /* If we had a another error reported earlier then this will be ignored */ diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 6e27af63e8a..f7223cafb5e 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -607,7 +607,7 @@ err: thd->proc_info= "end"; lex->link_first_table_back(view, link_to_local); unit->cleanup(); - DBUG_RETURN(res || thd->net.report_error); + DBUG_RETURN(res || thd->is_error()); } @@ -823,7 +823,7 @@ loop_out: view_parameters + revision_number_position, 1, &file_parser_dummy_hook)) { - error= thd->net.report_error? -1 : 0; + error= thd->is_error() ? -1 : 0; goto err; } } @@ -886,7 +886,7 @@ loop_out: if (sql_create_definition_file(&dir, &file, view_file_type, (uchar*)view, view_parameters, num_view_backups)) { - error= thd->net.report_error? -1 : 1; + error= thd->is_error() ? -1 : 1; goto err; } DBUG_RETURN(0); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 109e8f5434f..b893014aacb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9804,7 +9804,7 @@ NUM_literal: | DECIMAL_NUM { $$= new Item_decimal($1.str, $1.length, YYTHD->charset()); - if (YYTHD->net.report_error) + if (YYTHD->is_error()) { MYSQL_YYABORT; } @@ -9812,7 +9812,7 @@ NUM_literal: | FLOAT_NUM { $$ = new Item_float($1.str, $1.length); - if (YYTHD->net.report_error) + if (YYTHD->is_error()) { MYSQL_YYABORT; } From 230604f33c12b760694473af51ffae59fd4c9536 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Tue, 30 Oct 2007 22:35:14 +0300 Subject: [PATCH 63/92] In ha_delete_table, use a standard mechanism to intercept the error message and convert it to a warning instead of direct manipulation with the thread error stack. Fix a bug in handler::print_erorr when a garbled message was printed for HA_ERR_NO_SUCH_TABLE. This is a pre-requisite patch for the fix for Bug#12713 Error in a stored function called from a SELECT doesn't cause ROLLBACK of statem --- sql/handler.cc | 72 +++++++++++++++++++++++++++++++----------------- sql/log.cc | 3 +- sql/mysqld.cc | 2 +- sql/sql_base.cc | 3 +- sql/sql_class.cc | 4 +-- sql/sql_class.h | 3 +- sql/sql_error.cc | 2 +- 7 files changed, 56 insertions(+), 33 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 3ba52ca1c71..22374d57e99 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1414,6 +1414,36 @@ static const char *check_lowercase_names(handler *file, const char *path, } +/** + An interceptor to hijack the text of the error message without + setting an error in the thread. We need the text to present it + in the form of a warning to the user. +*/ + +struct Ha_delete_table_error_handler: public Internal_error_handler +{ +public: + virtual bool handle_error(uint sql_errno, + const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd); + char buff[MYSQL_ERRMSG_SIZE]; +}; + + +bool +Ha_delete_table_error_handler:: +handle_error(uint sql_errno, + const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd) +{ + /* Grab the error message */ + strmake(buff, message, sizeof(buff)-1); + return TRUE; +} + + /** @brief This should return ENOENT if the file doesn't exists. The .frm file will be deleted only if we return 0 or ENOENT @@ -1442,23 +1472,11 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, { /* Because file->print_error() use my_error() to generate the error message - we must store the error state in thd, reset it and restore it to - be able to get hold of the error message. - (We should in the future either rewrite handler::print_error() or make - a nice method of this. + we use an internal error handler to intercept it and store the text + in a temporary buffer. Later the message will be presented to user + as a warning. */ - bool is_slave_error= thd->is_slave_error; - sp_rcontext *spcont= thd->spcont; - SELECT_LEX *current_select= thd->lex->current_select; - char buff[sizeof(thd->net.last_error)]; - char new_error[sizeof(thd->net.last_error)]; - int last_errno= thd->net.last_errno; - - strmake(buff, thd->net.last_error, sizeof(buff)-1); - thd->is_slave_error= 0; - thd->spcont= NULL; - thd->lex->current_select= 0; - thd->net.last_error[0]= 0; + Ha_delete_table_error_handler ha_delete_table_error_handler; /* Fill up strucutures that print_error may need */ dummy_share.path.str= (char*) path; @@ -1471,16 +1489,18 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, file->table_share= &dummy_share; file->table= &dummy_table; - file->print_error(error, 0); - strmake(new_error, thd->net.last_error, sizeof(buff)-1); - /* restore thd */ - thd->is_slave_error= is_slave_error; - thd->spcont= spcont; - thd->lex->current_select= current_select; - thd->net.last_errno= last_errno; - strmake(thd->net.last_error, buff, sizeof(buff)-1); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, new_error); + thd->push_internal_handler(&ha_delete_table_error_handler); + file->print_error(error, 0); + + thd->pop_internal_handler(); + + /* + XXX: should we convert *all* errors to warnings here? + What if the error is fatal? + */ + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, + ha_delete_table_error_handler.buff); } delete file; DBUG_RETURN(error); @@ -2203,7 +2223,7 @@ void handler::print_error(int error, myf errflag) case HA_ERR_NO_SUCH_TABLE: my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str, table_share->table_name.str); - break; + DBUG_VOID_RETURN; case HA_ERR_RBR_LOGGING_FAILED: textno= ER_BINLOG_ROW_LOGGING_FAILED; break; diff --git a/sql/log.cc b/sql/log.cc index 02986bef493..688ed03d5d1 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -72,13 +72,14 @@ public: virtual ~Silence_log_table_errors() {} - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd); }; bool Silence_log_table_errors::handle_error(uint /* sql_errno */, + const char * /* message */, MYSQL_ERROR::enum_warning_level /* level */, THD * /* thd */) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cc964e417bf..c76bd8bd712 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2583,7 +2583,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags) TODO: There are two exceptions mechanism (THD and sp_rcontext), this could be improved by having a common stack of handlers. */ - if (thd->handle_error(error, + if (thd->handle_error(error, str, MYSQL_ERROR::WARN_LEVEL_ERROR)) DBUG_RETURN(0); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 223485f1e42..2584390d756 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -44,7 +44,7 @@ public: virtual ~Prelock_error_handler() {} - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd); @@ -58,6 +58,7 @@ private: bool Prelock_error_handler::handle_error(uint sql_errno, + const char * /* message */, MYSQL_ERROR::enum_warning_level /* level */, THD * /* thd */) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 707c8e83007..b5a29783044 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -498,12 +498,12 @@ void THD::push_internal_handler(Internal_error_handler *handler) } -bool THD::handle_error(uint sql_errno, +bool THD::handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level) { if (m_internal_handler) { - return m_internal_handler->handle_error(sql_errno, level, this); + return m_internal_handler->handle_error(sql_errno, message, level, this); } return FALSE; // 'FALSE', as per coding style diff --git a/sql/sql_class.h b/sql/sql_class.h index a3e71e183f3..db847c814a0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -969,6 +969,7 @@ public: @return true if the error is handled */ virtual bool handle_error(uint sql_errno, + const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd) = 0; }; @@ -1923,7 +1924,7 @@ public: @param level the error level @return true if the error is handled */ - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level); /** diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 8bdb2e59ed5..89cff73d153 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -137,7 +137,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, level= MYSQL_ERROR::WARN_LEVEL_ERROR; } - if (thd->handle_error(code, level)) + if (thd->handle_error(code, msg, level)) DBUG_RETURN(NULL); if (thd->spcont && From 756a86f06d9a8722657e6ea3d7386da538990c84 Mon Sep 17 00:00:00 2001 From: "davi@endora.local" <> Date: Tue, 30 Oct 2007 20:51:04 -0200 Subject: [PATCH 64/92] Bug#30904 SET PASSWORD statement is non-transactional The SET PASSWORD statement is non-transactional (no explicit transaction boundaries) in nature and hence is forbidden inside stored functions and triggers, but it weren't being effectively forbidden. The implemented fix is to issue a implicit commit with every SET PASSWORD statement, effectively prohibiting these statements in stored functions and triggers. --- mysql-test/r/sp-error.result | 10 ++++++++++ mysql-test/t/sp-error.test | 19 +++++++++++++++++++ sql/sql_lex.h | 2 +- sql/sql_parse.cc | 4 ++++ sql/sql_yacc.yy | 8 ++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 1b14d75cd9c..300fa42f3ad 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1523,3 +1523,13 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp SELECT ..inexistent(); 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 '.inexistent()' at line 1 USE test; +create function f1() returns int +begin +set @test = 1, password = password('foo'); +return 1; +end| +ERROR HY000: Not allowed to set autocommit from a stored function or trigger +create trigger t1 +before insert on t2 for each row set password = password('foo'); +delimiter ;| +ERROR HY000: Not allowed to set autocommit from a stored function or trigger diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index a956a246770..9f20d02480c 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2222,6 +2222,25 @@ SELECT .inexistent(); SELECT ..inexistent(); USE test; +# +# Bug#30904 SET PASSWORD statement is non-transactional +# + +delimiter |; + +--error ER_SP_CANT_SET_AUTOCOMMIT +create function f1() returns int +begin + set @test = 1, password = password('foo'); + return 1; +end| + +--error ER_SP_CANT_SET_AUTOCOMMIT +create trigger t1 + before insert on t2 for each row set password = password('foo'); + +delimiter ;| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a26c4fd1ca0..507d64daf89 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1616,7 +1616,7 @@ typedef struct st_lex : public Query_tables_list uint8 create_view_algorithm; uint8 create_view_check; bool drop_if_exists, drop_temporary, local_file, one_shot_set; - + bool autocommit; bool verbose, no_write_to_binlog; bool tx_chain, tx_release; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ac042960388..85457fea41b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3053,6 +3053,10 @@ end_with_restore_list: case SQLCOM_SET_OPTION: { List *lex_var_list= &lex->var_list; + + if (lex->autocommit && end_active_trans(thd)) + goto error; + if ((check_table_access(thd, SELECT_ACL, all_tables, 0) || open_and_lock_tables(thd, all_tables))) goto error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b893014aacb..69cd7060778 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10516,6 +10516,7 @@ set: lex->option_type=OPT_SESSION; lex->var_list.empty(); lex->one_shot_set= 0; + lex->autocommit= 0; } option_value_list {} @@ -10558,6 +10559,7 @@ option_type_value: lex->option_type=OPT_SESSION; lex->var_list.empty(); lex->one_shot_set= 0; + lex->autocommit= 0; lex->sphead->m_tmp_query= lip->get_tok_start(); } } @@ -10799,10 +10801,16 @@ option_value: user->host=null_lex_str; user->user.str=thd->security_ctx->priv_user; thd->lex->var_list.push_back(new set_var_password(user, $3)); + thd->lex->autocommit= TRUE; + if (lex->sphead) + lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; } | PASSWORD FOR_SYM user equal text_or_password { Lex->var_list.push_back(new set_var_password($3,$5)); + Lex->autocommit= TRUE; + if (Lex->sphead) + Lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; } ; From 4852cc7fc412f7bfcc7b1504ef9e015b2c6bf391 Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Wed, 31 Oct 2007 09:53:58 +0300 Subject: [PATCH 65/92] Fix result files after patch for BUG#31035. --- mysql-test/r/group_min_max.result | 4 ++-- mysql-test/r/index_merge_myisam.result | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 02b1459afd0..f62fd662a5d 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2251,7 +2251,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +2 SUBQUERY t1 range NULL a 5 NULL 8 EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); id select_type table type possible_keys key key_len ref rows Extra @@ -2268,7 +2268,7 @@ AND t1_outer1.b = t1_outer2.b; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index 1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer -2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +2 SUBQUERY t1 range NULL a 5 NULL 8 EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result index 9d7d06f7f1b..ebeba53fdfa 100644 --- a/mysql-test/r/index_merge_myisam.result +++ b/mysql-test/r/index_merge_myisam.result @@ -286,7 +286,7 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 -2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where; Using index +2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where create table t3 like t0; insert into t3 select * from t0; alter table t3 add key9 int not null, add index i9(key9); From 62d2ee935e5038b805a368c5eb2f0a30adce1c29 Mon Sep 17 00:00:00 2001 From: "anozdrin/alik@station." <> Date: Wed, 31 Oct 2007 12:04:19 +0300 Subject: [PATCH 66/92] Fix for a BUG#31649: events.test fails: NULL "state" field of SHOW PROCESSLIST. The problem was a race condition: if the Event Scheduler was not quick enough, the following scenario happens: - The Event Scheduler picks up the created event; - The event is executed; - event_scheduler_thread->proc_info is set to NULL; - The client issues SELECT FROM I_S. The fix is to wait for the Event Scheduler to reach 'Waiting for next activation' state. --- mysql-test/t/events.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index d1ca5f1b609..a4c7eaebc30 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -454,7 +454,8 @@ create event закачка on schedule every 10 hour do select get_lock("test_l --echo "Should have only 2 processes: the scheduler and the locked event" let $wait_condition= select count(*) = 2 from information_schema.processlist where ( (state like 'User lock%' AND info like 'select get_lock%') - OR (command='Daemon' AND user='event_scheduler')); + OR (command='Daemon' AND user='event_scheduler' AND + state = 'Waiting for next activation')); --source include/wait_condition.inc select /*2*/ user, host, db, command, state, info From 8549a8ea8fd2f1f7a64772bac35db839c9ed6618 Mon Sep 17 00:00:00 2001 From: "thek@adventure.(none)" <> Date: Wed, 31 Oct 2007 12:25:18 +0100 Subject: [PATCH 67/92] Bug#31347 Increase in memory usage after many DROP USER statements Dropping users causes huge increase in memory usage because field values were allocated on the server memory root for temporary usage but never deallocated. This patch changes the target memory root to be that of the thread handler instead since this root is cleared between each statement. --- sql/sql_acl.cc | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6bc6cce5e72..d03aacd7f07 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -311,7 +311,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) continue; } - const char *password= get_field(&mem, table->field[2]); + const char *password= get_field(thd->mem_root, table->field[2]); uint password_len= password ? strlen(password) : 0; set_user_salt(&user, password, password_len); if (user.salt_len == 0 && password_len != 0) @@ -364,7 +364,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) /* Starting from 4.0.2 we have more fields */ if (table->s->fields >= 31) { - char *ssl_type=get_field(&mem, table->field[next_field++]); + char *ssl_type=get_field(thd->mem_root, table->field[next_field++]); if (!ssl_type) user.ssl_type=SSL_TYPE_NONE; else if (!strcmp(ssl_type, "ANY")) @@ -378,11 +378,11 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) user.x509_issuer= get_field(&mem, table->field[next_field++]); user.x509_subject= get_field(&mem, table->field[next_field++]); - char *ptr = get_field(&mem, table->field[next_field++]); + char *ptr = get_field(thd->mem_root, table->field[next_field++]); user.user_resource.questions=ptr ? atoi(ptr) : 0; - ptr = get_field(&mem, table->field[next_field++]); + ptr = get_field(thd->mem_root, table->field[next_field++]); user.user_resource.updates=ptr ? atoi(ptr) : 0; - ptr = get_field(&mem, table->field[next_field++]); + ptr = get_field(thd->mem_root, table->field[next_field++]); user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0; if (user.user_resource.questions || user.user_resource.updates || user.user_resource.conn_per_hour) @@ -391,7 +391,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) if (table->s->fields >= 36) { /* Starting from 5.0.3 we have max_user_connections field */ - ptr= get_field(&mem, table->field[next_field++]); + ptr= get_field(thd->mem_root, table->field[next_field++]); user.user_resource.user_conn= ptr ? atoi(ptr) : 0; } else @@ -4865,6 +4865,7 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, byte user_key[MAX_KEY_LENGTH]; uint key_prefix_length; DBUG_ENTER("handle_grant_table"); + THD *thd= current_thd; if (! table_no) // mysql.user table { @@ -4932,17 +4933,18 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, DBUG_PRINT("info",("scan error: %d", error)); continue; } - if (! (host= get_field(&mem, host_field))) + if (! (host= get_field(thd->mem_root, host_field))) host= ""; - if (! (user= get_field(&mem, user_field))) + if (! (user= get_field(thd->mem_root, user_field))) user= ""; #ifdef EXTRA_DEBUG DBUG_PRINT("loop",("scan fields: '%s'@'%s' '%s' '%s' '%s'", user, host, - get_field(&mem, table->field[1]) /*db*/, - get_field(&mem, table->field[3]) /*table*/, - get_field(&mem, table->field[4]) /*column*/)); + get_field(thd->mem_root, table->field[1]) /*db*/, + get_field(thd->mem_root, table->field[3]) /*table*/, + get_field(thd->mem_root, + table->field[4]) /*column*/)); #endif if (strcmp(user_str, user) || my_strcasecmp(system_charset_info, host_str, host)) From 96f8d086f8dc002fdbbde589e0abaf045d53a07d Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Wed, 31 Oct 2007 17:16:53 +0300 Subject: [PATCH 68/92] Cleanup: use helper functions to set an error in MYSQL or MYSQL_STMT. No functionality added or changed. This is a pre-requisite for the fix for Bug#12713 Error in a stored function called from a SELECT doesn't cause ROLLBACK of statem Address post-review comments. --- include/sql_common.h | 6 +- libmysql/libmysql.c | 152 +++++++++++++++++++------------------------ libmysqld/lib_sql.cc | 22 +++---- sql-common/client.c | 148 +++++++++++++++++++---------------------- 4 files changed, 144 insertions(+), 184 deletions(-) diff --git a/include/sql_common.h b/include/sql_common.h index 80504140fae..56e7305130f 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -36,8 +36,10 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, const unsigned char *arg, ulong arg_length, my_bool skip_check, MYSQL_STMT *stmt); unsigned long cli_safe_read(MYSQL *mysql); -void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, - const char *sqlstate); +void net_clear_error(NET *net); +void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net); +void set_stmt_error(MYSQL_STMT *stmt, int errcode, const char *sqlstate, + const char *err); void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); #ifdef __cplusplus } diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index e2e42fe4a2d..76928ec798c 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -686,9 +686,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd) if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net)) { - net->last_errno= CR_SERVER_LOST; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); return 1; } /* Read what server thinks about out new auth message report */ @@ -860,8 +858,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) /* copy filename into local memory and allocate read buffer */ if (!(buf=my_malloc(packet_length, MYF(0)))) { - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(1); } @@ -887,9 +884,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) { DBUG_PRINT("error", ("Lost connection to MySQL server during LOAD DATA of local file")); - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno=CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto err; } } @@ -897,9 +892,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) /* Send empty packet to mark end of file */ if (my_net_write(net, (const uchar*) "", 0) || net_flush(net)) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno=CR_SERVER_LOST; - sprintf(net->last_error,ER(net->last_errno),errno); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto err; } @@ -1400,9 +1393,7 @@ const char *cli_read_statistics(MYSQL *mysql) mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */ if (!mysql->net.read_pos[0]) { - strmov(mysql->net.sqlstate, unknown_sqlstate); - mysql->net.last_errno=CR_WRONG_HOST_INFO; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); + set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate); return mysql->net.last_error; } return (char*) mysql->net.read_pos; @@ -1848,24 +1839,17 @@ static my_bool my_realloc_str(NET *net, ulong length) if (buf_length + length > net->max_packet) { res= net_realloc(net, buf_length + length); + if (res) + { + strmov(net->sqlstate, unknown_sqlstate); + strmov(net->last_error, ER(net->last_errno)); + } net->write_pos= net->buff+ buf_length; } DBUG_RETURN(res); } -/* Clear possible error statee of struct NET */ - -static void net_clear_error(NET *net) -{ - if (net->last_errno) - { - net->last_errno= 0; - net->last_error[0]= '\0'; - strmov(net->sqlstate, not_error_sqlstate); - } -} - static void stmt_clear_error(MYSQL_STMT *stmt) { if (stmt->last_errno) @@ -1876,18 +1860,21 @@ static void stmt_clear_error(MYSQL_STMT *stmt) } } -/* +/** Set statement error code, sqlstate, and error message from given errcode and sqlstate. */ -static void set_stmt_error(MYSQL_STMT * stmt, int errcode, - const char *sqlstate) +void set_stmt_error(MYSQL_STMT * stmt, int errcode, + const char *sqlstate, const char *err) { DBUG_ENTER("set_stmt_error"); DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode))); DBUG_ASSERT(stmt != 0); + if (err == 0) + err= ER(errcode); + stmt->last_errno= errcode; strmov(stmt->last_error, ER(errcode)); strmov(stmt->sqlstate, sqlstate); @@ -1896,21 +1883,24 @@ static void set_stmt_error(MYSQL_STMT * stmt, int errcode, } -/* - Set statement error code, sqlstate, and error message. +/** + Set statement error code, sqlstate, and error message from NET. + + @param stmt a statement handle. Copy the error here. + @param net mysql->net. Source of the error. */ -void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, - const char *sqlstate) +void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net) { DBUG_ENTER("set_stmt_errmsg"); - DBUG_PRINT("enter", ("error: %d/%s '%s'", errcode, sqlstate, err)); + DBUG_PRINT("enter", ("error: %d/%s '%s'", net->last_errno, net->sqlstate, + net->last_error)); DBUG_ASSERT(stmt != 0); - stmt->last_errno= errcode; - if (err && err[0]) - strmov(stmt->last_error, err); - strmov(stmt->sqlstate, sqlstate); + stmt->last_errno= net->last_errno; + if (net->last_error && net->last_error[0]) + strmov(stmt->last_error, net->last_error); + strmov(stmt->sqlstate, net->sqlstate); DBUG_VOID_RETURN; } @@ -2085,7 +2075,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) if (!mysql) { /* mysql can be reset in mysql_close called from mysql_reconnect */ - set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -2123,23 +2113,20 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) stmt->state= MYSQL_STMT_INIT_DONE; if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); DBUG_RETURN(1); } } if (stmt_command(mysql, COM_STMT_PREPARE, (const uchar*) query, length, stmt)) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); DBUG_RETURN(1); } if ((*mysql->methods->read_prepare_result)(mysql, stmt)) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); DBUG_RETURN(1); } @@ -2154,7 +2141,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) (stmt->param_count + stmt->field_count)))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL); DBUG_RETURN(1); } stmt->bind= stmt->params + stmt->param_count; @@ -2284,7 +2271,7 @@ mysql_stmt_result_metadata(MYSQL_STMT *stmt) if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result), MYF(MY_WME | MY_ZEROFILL)))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL); DBUG_RETURN(0); } @@ -2517,7 +2504,7 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) */ if ((my_realloc_str(net, *param->length))) { - set_stmt_error(stmt, net->last_errno, unknown_sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } (*param->store_param_func)(net, param); @@ -2554,7 +2541,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) stmt->insert_id= mysql->insert_id; if (res) { - set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -2577,13 +2564,13 @@ int cli_stmt_execute(MYSQL_STMT *stmt) if (!stmt->bind_param_done) { - set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate); + set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate, NULL); DBUG_RETURN(1); } if (mysql->status != MYSQL_STATUS_READY || mysql->server_status & SERVER_MORE_RESULTS_EXISTS) { - set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); + set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -2592,7 +2579,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) null_count= (stmt->param_count+7) /8; if (my_realloc_str(net, null_count + 1)) { - set_stmt_error(stmt, net->last_errno, unknown_sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } bzero((char*) net->write_pos, null_count); @@ -2605,7 +2592,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) { if (my_realloc_str(net, 2 * stmt->param_count)) { - set_stmt_error(stmt, net->last_errno, unknown_sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } /* @@ -2628,7 +2615,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) /* TODO: Look into avoding the following memdup */ if (!(param_data= my_memdup(net->buff, length, MYF(0)))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL); DBUG_RETURN(1); } result= execute(stmt, param_data, length); @@ -2692,20 +2679,19 @@ static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row) */ if (!mysql) { - set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL); return 1; } if (mysql->status != MYSQL_STATUS_GET_RESULT) { set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ? CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC, - unknown_sqlstate); + unknown_sqlstate, NULL); goto error; } if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row)) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); /* If there was an error, there are no more pending rows: reset statement status to not hang up in following @@ -2766,7 +2752,7 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row) buff, sizeof(buff), (uchar*) 0, 0, 1, NULL)) { - set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + set_stmt_errmsg(stmt, net); return 1; } if ((*mysql->methods->read_rows_from_cursor)(stmt)) @@ -2797,7 +2783,7 @@ static int stmt_read_row_no_result_set(MYSQL_STMT *stmt __attribute__((unused)), unsigned char **row __attribute__((unused))) { - set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate); + set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate, NULL); return 1; } @@ -2847,7 +2833,7 @@ my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt, } return FALSE; err_not_implemented: - set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate); + set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate, NULL); return TRUE; } @@ -3232,7 +3218,7 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *my_bind) { if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE) { - set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); + set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate, NULL); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -3397,7 +3383,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, */ if (param_number >= stmt->param_count) { - set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate); + set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -3433,8 +3419,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, buff, sizeof(buff), (uchar*) data, length, 1, NULL)) { - set_stmt_errmsg(stmt, mysql->net.last_error, - mysql->net.last_errno, mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); DBUG_RETURN(1); } } @@ -3903,7 +3888,8 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, if (field->flags & ZEROFILL_FLAG && length < field->length && field->length < MAX_DOUBLE_STRING_REP_LENGTH - 1) { - bmove_upp((char*) buff + field->length, buff + length, length); + bmove_upp((uchar*) buff + field->length, (uchar*) buff + length, + length); bfill((char*) buff, field->length - length, '0'); length= field->length; } @@ -4502,7 +4488,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *my_bind) { int errorcode= (int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE ? CR_NO_PREPARE_STMT : CR_NO_STMT_METADATA; - set_stmt_error(stmt, errorcode, unknown_sqlstate); + set_stmt_error(stmt, errorcode, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -4682,12 +4668,12 @@ int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *my_bind, if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE) { - set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate); + set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate, NULL); return 1; } if (column >= stmt->field_count) { - set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate); + set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -4733,7 +4719,7 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) if (!mysql) { - set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -4748,7 +4734,7 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc, sizeof(MYSQL_ROWS) + pkt_len - 1))) { - set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate); + set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL); goto err; } cur->data= (MYSQL_ROW) (cur+1); @@ -4769,7 +4755,7 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) DBUG_RETURN(0); } } - set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + set_stmt_errmsg(stmt, net); err: DBUG_RETURN(1); @@ -4836,7 +4822,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE) { - set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); + set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -4856,13 +4842,13 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff), (uchar*) 0, 0, 1, NULL)) { - set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } } else if (mysql->status != MYSQL_STATUS_GET_RESULT) { - set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); + set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL); DBUG_RETURN(1); } @@ -5043,8 +5029,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff, sizeof(buff), 0, 0, 0, NULL)) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); stmt->state= MYSQL_STMT_INIT_DONE; return 1; } @@ -5117,8 +5102,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) int4store(buff, stmt->stmt_id); if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))) { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); } } } @@ -5139,7 +5123,7 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt) if (!stmt->mysql) { /* mysql can be reset in mysql_close called from mysql_reconnect */ - set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL); DBUG_RETURN(1); } /* Reset the client and server sides of the prepared statement */ @@ -5243,15 +5227,11 @@ int STDCALL mysql_next_result(MYSQL *mysql) if (mysql->status != MYSQL_STATUS_READY) { - strmov(mysql->net.sqlstate, unknown_sqlstate); - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); DBUG_RETURN(1); } - mysql->net.last_error[0]= 0; - mysql->net.last_errno= 0; - strmov(mysql->net.sqlstate, not_error_sqlstate); + net_clear_error(&mysql->net); mysql->affected_rows= ~(my_ulonglong) 0; if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 4e525f8447f..13847c324e1 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -81,8 +81,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, /* Check that we are calling the client functions in right order */ if (mysql->status != MYSQL_STATUS_READY) { - strmov(net->last_error, - ER(net->last_errno=CR_COMMANDS_OUT_OF_SYNC)); + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); return 1; } @@ -90,7 +89,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, thd->clear_error(); mysql->affected_rows= ~(my_ulonglong) 0; mysql->field_count= 0; - net->last_errno= 0; + net_clear_error(net); thd->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect @@ -245,8 +244,7 @@ static my_bool emb_read_query_result(MYSQL *mysql) mysql->fields= res->embedded_info->fields_list; mysql->affected_rows= res->embedded_info->affected_rows; mysql->insert_id= res->embedded_info->insert_id; - mysql->net.last_errno= 0; - mysql->net.last_error[0]= 0; + net_clear_error(&mysql->net); mysql->info= 0; if (res->embedded_info->info[0]) @@ -288,7 +286,7 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) if (res) { NET *net= &stmt->mysql->net; - set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -299,14 +297,12 @@ int emb_read_binary_rows(MYSQL_STMT *stmt) MYSQL_DATA *data; if (!(data= emb_read_rows(stmt->mysql, 0, 0))) { - set_stmt_errmsg(stmt, stmt->mysql->net.last_error, - stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate); + set_stmt_errmsg(stmt, &stmt->mysql->net); return 1; } stmt->result= *data; my_free((char *) data, MYF(0)); - set_stmt_errmsg(stmt, stmt->mysql->net.last_error, - stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate); + set_stmt_errmsg(stmt, &stmt->mysql->net); return 0; } @@ -320,16 +316,14 @@ int emb_read_rows_from_cursor(MYSQL_STMT *stmt) if (res->embedded_info->last_errno) { embedded_get_error(mysql, res); - set_stmt_errmsg(stmt, mysql->net.last_error, - mysql->net.last_errno, mysql->net.sqlstate); + set_stmt_errmsg(stmt, &mysql->net); return 1; } thd->cur_data= res; mysql->warning_count= res->embedded_info->warning_count; mysql->server_status= res->embedded_info->server_status; - mysql->net.last_errno= 0; - mysql->net.last_error[0]= 0; + net_clear_error(&mysql->net); return emb_read_binary_rows(stmt); } diff --git a/sql-common/client.c b/sql-common/client.c index baf154dcc43..a6e02376a40 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -312,42 +312,34 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, break; if (GetLastError() != ERROR_PIPE_BUSY) { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), host, unix_socket, - (ulong) GetLastError()); + set_mysql_extended_error(mysql, CR_NAMEDPIPEOPEN_ERROR, + unknown_sqlstate, ER(CR_NAMEDPIPEOPEN_ERROR), + host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; } /* wait for for an other instance */ if (! WaitNamedPipe(pipe_name, connect_timeout*1000) ) { - net->last_errno=CR_NAMEDPIPEWAIT_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), host, unix_socket, - (ulong) GetLastError()); + set_mysql_extended_error(mysql, CR_NAMEDPIPEWAIT_ERROR, unknown_sqlstate, + ER(CR_NAMEDPIPEWAIT_ERROR), + host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; } } if (hPipe == INVALID_HANDLE_VALUE) { - net->last_errno=CR_NAMEDPIPEOPEN_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), host, unix_socket, - (ulong) GetLastError()); + set_mysql_extended_error(mysql, CR_NAMEDPIPEOPEN_ERROR, unknown_sqlstate, + ER(CR_NAMEDPIPEOPEN_ERROR), host, unix_socket, + (ulong) GetLastError()); return INVALID_HANDLE_VALUE; } dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) ) { CloseHandle( hPipe ); - net->last_errno=CR_NAMEDPIPESETSTATE_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno),host, unix_socket, - (ulong) GetLastError()); + set_mysql_extended_error(mysql, CR_NAMEDPIPESETSTATE_ERROR, + unknown_sqlstate, ER(CR_NAMEDPIPESETSTATE_ERROR), + host, unix_socket, (ulong) GetLastError()); return INVALID_HANDLE_VALUE; } *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */ @@ -566,14 +558,12 @@ err: CloseHandle(handle_connect_file_map); if (error_allow) { - net->last_errno=error_allow; - strmov(net->sqlstate, unknown_sqlstate); if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) - my_snprintf(net->last_error,sizeof(net->last_error)-1, - ER(net->last_errno),suffix_pos,error_code); + set_mysql_extended_error(mysql, error_allow, unknown_sqlstate, + ER(error_allow), suffix_pos, error_code); else - my_snprintf(net->last_error,sizeof(net->last_error)-1, - ER(net->last_errno),error_code); + set_mysql_extended_error(mysql, error_allow, unknown_sqlstate, + ER(error_allow), error_code); return(INVALID_HANDLE_VALUE); } return(handle_map); @@ -683,10 +673,8 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, DBUG_RETURN(1); } - net->last_error[0]=0; - net->last_errno= 0; - strmov(net->sqlstate, not_error_sqlstate); - mysql->net.report_error=0; + net_clear_error(net); + net->report_error=0; mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; /* @@ -703,8 +691,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, socket_errno)); if (net->last_errno == ER_NET_PACKET_TOO_LARGE) { - net->last_errno=CR_NET_PACKET_TOO_LARGE; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate); goto end; } end_server(mysql); @@ -713,8 +700,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, if (net_write_command(net,(uchar) command, header, header_length, arg, arg_length)) { - net->last_errno=CR_SERVER_GONE_ERROR; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate); goto end; } } @@ -760,6 +746,19 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate) DBUG_VOID_RETURN; } +/** + Clear possible error state of struct NET + + @param net clear the state of the argument +*/ + +void net_clear_error(NET *net) +{ + net->last_errno= 0; + net->last_error[0]= '\0'; + strmov(net->sqlstate, not_error_sqlstate); +} + static void set_mysql_extended_error(MYSQL *mysql, int errcode, const char *sqlstate, @@ -846,9 +845,8 @@ static int check_license(MYSQL *mysql) { if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE) { - net->last_errno= CR_WRONG_LICENSE; - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), required_license); + set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate, + ER(CR_WRONG_LICENSE), required_license); } return 1; } @@ -864,9 +862,8 @@ static int check_license(MYSQL *mysql) (!row || !row[0] || strncmp(row[0], required_license, sizeof(required_license)))) { - net->last_errno= CR_WRONG_LICENSE; - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), required_license); + set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate, + ER(CR_WRONG_LICENSE), required_license); } mysql_free_result(res); return net->last_errno; @@ -1761,24 +1758,22 @@ int mysql_init_character_set(MYSQL *mysql) } charsets_dir= save; } - + if (!mysql->charset) { - net->last_errno=CR_CANT_READ_CHARSET; - strmov(net->sqlstate, unknown_sqlstate); if (mysql->options.charset_dir) - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), - mysql->options.charset_name, - mysql->options.charset_dir); + set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate, + ER(CR_CANT_READ_CHARSET), + mysql->options.charset_name, + mysql->options.charset_dir); else { char cs_dir_name[FN_REFLEN]; get_charsets_dir(cs_dir_name); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(net->last_errno), - mysql->options.charset_name, - cs_dir_name); + set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate, + ER(CR_CANT_READ_CHARSET), + mysql->options.charset_name, + cs_dir_name); } return 1; } @@ -1910,10 +1905,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) { - net->last_errno=CR_SOCKET_CREATE_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error,sizeof(net->last_error)-1, - ER(net->last_errno),socket_errno); + set_mysql_extended_error(mysql, CR_SOCKET_CREATE_ERROR, + unknown_sqlstate, + ER(CR_SOCKET_CREATE_ERROR), + socket_errno); goto error; } net->vio= vio_new(sock, VIO_TYPE_SOCKET, @@ -1926,10 +1921,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, { DBUG_PRINT("error",("Got error %d on connect to local server", socket_errno)); - net->last_errno=CR_CONNECTION_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error,sizeof(net->last_error)-1, - ER(net->last_errno),unix_socket,socket_errno); + set_mysql_extended_error(mysql, CR_CONNECTION_ERROR, + unknown_sqlstate, + ER(CR_CONNECTION_ERROR), + unix_socket, socket_errno); goto error; } mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; @@ -1986,10 +1981,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, #endif if (sock == SOCKET_ERROR) { - net->last_errno=CR_IPSOCK_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error,sizeof(net->last_error)-1, - ER(net->last_errno),socket_errno); + set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate, + ER(CR_IPSOCK_ERROR), socket_errno); goto error; } net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ); @@ -2014,10 +2007,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if (!hp) { my_gethostbyname_r_free(); - net->last_errno=CR_UNKNOWN_HOST; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(CR_UNKNOWN_HOST), host, tmp_errno); + set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate, + ER(CR_UNKNOWN_HOST), host, tmp_errno); goto error; } memcpy(&sock_addr.sin_addr, hp->h_addr, @@ -2030,10 +2021,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, { DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, host)); - net->last_errno= CR_CONN_HOST_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(CR_CONN_HOST_ERROR), host, socket_errno); + set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate, + ER(CR_CONN_HOST_ERROR), host, socket_errno); goto error; } } @@ -2097,11 +2086,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, PROTOCOL_VERSION, mysql->protocol_version)); if (mysql->protocol_version != PROTOCOL_VERSION) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno= CR_VERSION_ERROR; - my_snprintf(net->last_error, sizeof(net->last_error)-1, - ER(CR_VERSION_ERROR), mysql->protocol_version, - PROTOCOL_VERSION); + set_mysql_extended_error(mysql, CR_VERSION_ERROR, unknown_sqlstate, + ER(CR_VERSION_ERROR), mysql->protocol_version, + PROTOCOL_VERSION); goto error; } end=strend((char*) net->read_pos+1); @@ -2625,7 +2612,7 @@ void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)), for (; element; element= element->next) { MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; - set_stmt_errmsg(stmt, buff, CR_STMT_CLOSED, unknown_sqlstate); + set_stmt_error(stmt, CR_STMT_CLOSED, unknown_sqlstate, buff); stmt->mysql= 0; /* No need to call list_delete for statement here */ } @@ -3142,11 +3129,8 @@ int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name) { char cs_dir_name[FN_REFLEN]; get_charsets_dir(cs_dir_name); - mysql->net.last_errno= CR_CANT_READ_CHARSET; - strmov(mysql->net.sqlstate, unknown_sqlstate); - my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error) - 1, - ER(mysql->net.last_errno), cs_name, cs_dir_name); - + set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate, + ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name); } charsets_dir= save_csdir; return mysql->net.last_errno; From 3154b2bee4dc99b3313081effe2ac9c4c4a487f9 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Wed, 31 Oct 2007 18:33:13 +0300 Subject: [PATCH 69/92] Cleanup: rename select_send::status to select_send::is_result_set_started. Add select_send::cleanup. Fix a compilation warning. Issues spotted while working on the fix for Bug#12713. --- sql-common/client.c | 1 - sql/sql_class.cc | 30 ++++++++++++++++++++++-------- sql/sql_class.h | 10 ++++++++-- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index a6e02376a40..e92a9bd0cdc 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1714,7 +1714,6 @@ static MYSQL_METHODS client_methods= C_MODE_START int mysql_init_character_set(MYSQL *mysql) { - NET *net= &mysql->net; const char *default_collation_name; /* Set character set */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b5a29783044..a904023cbff 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1305,23 +1305,26 @@ bool select_send::send_fields(List &list, uint flags) { bool res; if (!(res= thd->protocol->send_fields(&list, flags))) - status= 1; + is_result_set_started= 1; return res; } void select_send::abort() { DBUG_ENTER("select_send::abort"); - if (status && thd->spcont && + if (is_result_set_started && thd->spcont && thd->spcont->find_handler(thd, thd->net.last_errno, MYSQL_ERROR::WARN_LEVEL_ERROR)) { /* - Executing stored procedure without a handler. - Here we should actually send an error to the client, - but as an error will break a multiple result set, the only thing we - can do for now is to nicely end the current data set and remembering - the error so that the calling routine will abort + We're executing a stored procedure, have an open result + set, an SQL exception conditiona and a handler for it. + In this situation we must abort the current statement, + silence the error and start executing the continue/exit + handler. + Before aborting the statement, let's end the open result set, as + otherwise the client will hang due to the violation of the + client/server protocol. */ thd->net.report_error= 0; send_eof(); @@ -1331,6 +1334,17 @@ void select_send::abort() } +/** + Cleanup an instance of this class for re-use + at next execution of a prepared statement/ + stored procedure statement. +*/ + +void select_send::cleanup() +{ + is_result_set_started= FALSE; +} + /* Send data to client. Returns 0 if ok */ bool select_send::send_data(List &items) @@ -1392,7 +1406,7 @@ bool select_send::send_eof() if (! thd->is_error()) { ::send_eof(thd); - status= 0; + is_result_set_started= 0; return 0; } else diff --git a/sql/sql_class.h b/sql/sql_class.h index db847c814a0..632c440266f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2051,14 +2051,20 @@ public: class select_send :public select_result { - int status; + /** + True if we have sent result set metadata to the client. + In this case the client always expects us to end the result + set with an eof or error packet + */ + bool is_result_set_started; public: - select_send() :status(0) {} + select_send() :is_result_set_started(FALSE) {} bool send_fields(List &list, uint flags); bool send_data(List &items); bool send_eof(); virtual bool check_simple_select() const { return FALSE; } void abort(); + virtual void cleanup(); }; From 8620673f932f62c8c9fbf74b8551ccd4c4a2b8ac Mon Sep 17 00:00:00 2001 From: "davi@endora.local/endora" <> Date: Wed, 31 Oct 2007 13:54:53 -0200 Subject: [PATCH 70/92] Post merge fix for bug 31669. --- tests/mysql_client_test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 808d6fe30de..0cb9ff49128 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -17112,8 +17112,8 @@ static void test_bug31669() int rc; static char buff[LARGE_BUFFER_SIZE+1]; #ifndef EMBEDDED_LIBRARY - static char user[USERNAME_LENGTH+1]; - static char db[NAME_LEN+1]; + static char user[USERNAME_CHAR_LENGTH+1]; + static char db[NAME_CHAR_LEN+1]; static char query[LARGE_BUFFER_SIZE*2]; #endif @@ -17136,13 +17136,13 @@ static void test_bug31669() #ifndef EMBEDDED_LIBRARY memset(db, 'a', sizeof(db)); - db[NAME_LEN]= 0; + db[NAME_CHAR_LEN]= 0; strxmov(query, "CREATE DATABASE IF NOT EXISTS ", db, NullS); rc= mysql_query(mysql, query); myquery(rc); memset(user, 'b', sizeof(user)); - user[USERNAME_LENGTH]= 0; + user[USERNAME_CHAR_LENGTH]= 0; memset(buff, 'c', sizeof(buff)); buff[LARGE_BUFFER_SIZE]= 0; strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'%' IDENTIFIED BY " @@ -17156,21 +17156,21 @@ static void test_bug31669() rc= mysql_change_user(mysql, user, buff, db); DIE_UNLESS(!rc); - user[USERNAME_LENGTH-1]= 'a'; + user[USERNAME_CHAR_LENGTH-1]= 'a'; rc= mysql_change_user(mysql, user, buff, db); DIE_UNLESS(rc); - user[USERNAME_LENGTH-1]= 'b'; + user[USERNAME_CHAR_LENGTH-1]= 'b'; buff[LARGE_BUFFER_SIZE-1]= 'd'; rc= mysql_change_user(mysql, user, buff, db); DIE_UNLESS(rc); buff[LARGE_BUFFER_SIZE-1]= 'c'; - db[NAME_LEN-1]= 'e'; + db[NAME_CHAR_LEN-1]= 'e'; rc= mysql_change_user(mysql, user, buff, db); DIE_UNLESS(rc); - db[NAME_LEN-1]= 'a'; + db[NAME_CHAR_LEN-1]= 'a'; rc= mysql_change_user(mysql, user, buff, db); DIE_UNLESS(!rc); From c26aef8fc6a026808fc41f78c55440bfe7c5a008 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Wed, 31 Oct 2007 23:48:41 +0300 Subject: [PATCH 71/92] Try to fix a Windows compilation warning. --- sql-common/client.c | 125 +++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index e92a9bd0cdc..5ece9c39d6c 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -272,6 +272,76 @@ static int wait_for_data(my_socket fd, uint timeout) } #endif /* defined(__WIN__) || defined(__NETWARE__) */ +/** + Set the internal error message to mysql handler + + @param mysql connection handle (client side) + @param errcode CR_ error code, passed to ER macro to get + error text + @parma sqlstate SQL standard sqlstate +*/ + +void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate) +{ + NET *net; + DBUG_ENTER("set_mysql_error"); + DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode))); + DBUG_ASSERT(mysql != 0); + + net= &mysql->net; + net->last_errno= errcode; + strmov(net->last_error, ER(errcode)); + strmov(net->sqlstate, sqlstate); + + DBUG_VOID_RETURN; +} + +/** + Clear possible error state of struct NET + + @param net clear the state of the argument +*/ + +void net_clear_error(NET *net) +{ + net->last_errno= 0; + net->last_error[0]= '\0'; + strmov(net->sqlstate, not_error_sqlstate); +} + +/** + Set an error message on the client. + + @param mysql connection handle + @param errcode CR_* errcode, for client errors + @param sqlstate SQL standard sql state, unknown_sqlstate for the + majority of client errors. + @param format error message template, in sprintf format + @param ... variable number of arguments +*/ + +static void set_mysql_extended_error(MYSQL *mysql, int errcode, + const char *sqlstate, + const char *format, ...) +{ + NET *net; + va_list args; + DBUG_ENTER("set_mysql_extended_error"); + DBUG_PRINT("enter", ("error :%d '%s'", errcode, format)); + DBUG_ASSERT(mysql != 0); + + net= &mysql->net; + net->last_errno= errcode; + va_start(args, format); + my_vsnprintf(net->last_error, sizeof(net->last_error)-1, + format, args); + va_end(args); + strmov(net->sqlstate, sqlstate); + + DBUG_VOID_RETURN; +} + + /* Create a named pipe connection @@ -727,61 +797,6 @@ void free_old_query(MYSQL *mysql) DBUG_VOID_RETURN; } -/* - Set the internal error message to mysql handler -*/ - -void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate) -{ - NET *net; - DBUG_ENTER("set_mysql_error"); - DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode))); - DBUG_ASSERT(mysql != 0); - - net= &mysql->net; - net->last_errno= errcode; - strmov(net->last_error, ER(errcode)); - strmov(net->sqlstate, sqlstate); - - DBUG_VOID_RETURN; -} - -/** - Clear possible error state of struct NET - - @param net clear the state of the argument -*/ - -void net_clear_error(NET *net) -{ - net->last_errno= 0; - net->last_error[0]= '\0'; - strmov(net->sqlstate, not_error_sqlstate); -} - - -static void set_mysql_extended_error(MYSQL *mysql, int errcode, - const char *sqlstate, - const char *format, ...) -{ - NET *net; - va_list args; - DBUG_ENTER("set_mysql_extended_error"); - DBUG_PRINT("enter", ("error :%d '%s'", errcode, format)); - DBUG_ASSERT(mysql != 0); - - net= &mysql->net; - net->last_errno= errcode; - va_start(args, format); - my_vsnprintf(net->last_error, sizeof(net->last_error)-1, - format, args); - va_end(args); - strmov(net->sqlstate, sqlstate); - - DBUG_VOID_RETURN; -} - - /* Flush result set sent from server */ From c0bb7f8682cd11ad9fc9915781c8447ac2818094 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 00:10:58 +0300 Subject: [PATCH 72/92] Remove net_printf_error(). Do not talk to network directly in check_user()/check_connection()/check_for_max_user_connections(). This is a pre-requisite patch for the fix for Bug#12713 "Error in a stored function called from a SELECT doesn't cause ROLLBACK of statem" Implement review comments. --- sql/mysql_priv.h | 1 - sql/mysqld.cc | 6 +- sql/protocol.cc | 120 +---------------------------- sql/protocol.h | 1 - sql/sql_connect.cc | 183 +++++++++++++++++++++++++-------------------- sql/sql_parse.cc | 5 -- 6 files changed, 108 insertions(+), 208 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3b88fe0fca8..3484b8096e3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -920,7 +920,6 @@ bool init_new_connection_handler_thread(); void reset_mqh(LEX_USER *lu, bool get_them); bool check_mqh(THD *thd, uint check_command); void time_out_user_resource_limits(THD *thd, USER_CONN *uc); -int check_for_max_user_connections(THD *thd, USER_CONN *uc); void decrease_user_connections(USER_CONN *uc); void thd_init_client_charset(THD *thd, uint cs_number); bool setup_connection_thread_globals(THD *thd); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c76bd8bd712..4cf6e05751f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4302,6 +4302,7 @@ void create_thread_to_handle_connection(THD *thd) } else { + char error_message_buff[MYSQL_ERRMSG_SIZE]; /* Create new thread to handle connection */ int error; thread_created++; @@ -4320,7 +4321,10 @@ void create_thread_to_handle_connection(THD *thd) thd->killed= THD::KILL_CONNECTION; // Safety (void) pthread_mutex_unlock(&LOCK_thread_count); statistic_increment(aborted_connects,&LOCK_status); - net_printf_error(thd, ER_CANT_CREATE_THREAD, error); + /* Can't use my_error() since store_globals has not been called. */ + my_snprintf(error_message_buff, sizeof(error_message_buff), + ER(ER_CANT_CREATE_THREAD), error); + net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff); (void) pthread_mutex_lock(&LOCK_thread_count); close_connection(thd,0,0); delete thd; diff --git a/sql/protocol.cc b/sql/protocol.cc index 51d408de9de..bf8faec006a 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -58,7 +58,7 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length) Design note: - net_printf_error and net_send_error are low-level functions + net_send_error is a low-level functions that shall be used only when a new connection is being established or at server startup. For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's @@ -120,124 +120,6 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) DBUG_VOID_RETURN; } -/* - Write error package and flush to client - It's a little too low level, but I don't want to use another buffer for - this - - Design note: - - net_printf_error and net_send_error are low-level functions - that shall be used only when a new connection is being - established or at server startup. - For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's - critical that every error that can be intercepted is issued in one - place only, my_message_sql. -*/ - -void -net_printf_error(THD *thd, uint errcode, ...) -{ - va_list args; - uint length,offset; - const char *format; -#ifndef EMBEDDED_LIBRARY - const char *text_pos; - int head_length= NET_HEADER_SIZE; -#else - char text_pos[1024]; -#endif - NET *net= &thd->net; - - DBUG_ENTER("net_printf_error"); - DBUG_PRINT("enter",("message: %u",errcode)); - - DBUG_ASSERT(!thd->spcont); - - if (net && net->no_send_error) - { - thd->clear_error(); - thd->is_fatal_error= 0; // Error message is given - DBUG_PRINT("info", ("sending error messages prohibited")); - DBUG_VOID_RETURN; - } - - thd->is_slave_error= 1; // needed to catch query errors during replication -#ifndef EMBEDDED_LIBRARY - query_cache_abort(net); // Safety -#endif - va_start(args,errcode); - /* - The following is needed to make net_printf_error() work with 0 argument - for errorcode and use the argument after that as the format string. This - is useful for rare errors that are not worth the hassle to put in - errmsg.sys, but at the same time, the message is not fixed text - */ - if (errcode) - format= ER(errcode); - else - { - format=va_arg(args,char*); - errcode= ER_UNKNOWN_ERROR; - } - offset= (net->return_errno ? - ((thd->client_capabilities & CLIENT_PROTOCOL_41) ? - 2+SQLSTATE_LENGTH+1 : 2) : 0); -#ifndef EMBEDDED_LIBRARY - text_pos=(char*) net->buff + head_length + offset + 1; - length= (uint) ((char*)net->buff_end - text_pos); -#else - length=sizeof(text_pos)-1; -#endif - length=my_vsnprintf(my_const_cast(char*) (text_pos), - min(length, sizeof(net->last_error)), - format,args); - va_end(args); - - /* Replication slave relies on net->last_* to see if there was error */ - net->last_errno= errcode; - strmake(net->last_error, text_pos, sizeof(net->last_error)-1); - -#ifndef EMBEDDED_LIBRARY - if (net->vio == 0) - { - if (thd->bootstrap) - { - /* - In bootstrap it's ok to print on stderr - This may also happen when we get an error from a slave thread - */ - fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos); - thd->fatal_error(); - } - DBUG_VOID_RETURN; - } - - int3store(net->buff,length+1+offset); - net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); - net->buff[head_length]=(uchar) 255; // Error package - if (offset) - { - uchar *pos= net->buff+head_length+1; - int2store(pos, errcode); - if (thd->client_capabilities & CLIENT_PROTOCOL_41) - { - pos[2]= '#'; /* To make the protocol backward compatible */ - memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH); - } - } - VOID(net_real_write(net, net->buff, length+head_length+1+offset)); -#else - net->last_errno= errcode; - strmake(net->last_error, text_pos, length); - strmake(net->sqlstate, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH); -#endif - if (thd->killed != THD::KILL_CONNECTION) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, errcode, - text_pos ? text_pos : ER(errcode)); - thd->is_fatal_error=0; // Error message is given - DBUG_VOID_RETURN; -} /* Return ok to the client. diff --git a/sql/protocol.h b/sql/protocol.h index 46a2b6d36b6..53584326f03 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -172,7 +172,6 @@ public: }; void send_warning(THD *thd, uint sql_errno, const char *err=0); -void net_printf_error(THD *thd, uint sql_errno, ...); void net_send_error(THD *thd, uint sql_errno=0, const char *err=0); void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 8a817e5993a..9b5f1a9b0e5 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -87,7 +87,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, my_malloc(sizeof(struct user_conn) + temp_len+1, MYF(MY_WME))))) { - net_send_error(thd, 0, NullS); // Out of memory + /* MY_WME ensures an error is set in THD. */ return_val= 1; goto end; } @@ -100,8 +100,8 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->reset_utime= thd->thr_create_utime; if (my_hash_insert(&hash_user_connections, (uchar*) uc)) { + /* The only possible error is out of memory, MY_WME sets an error. */ my_free((char*) uc,0); - net_send_error(thd, 0, NullS); // Out of memory return_val= 1; goto end; } @@ -132,6 +132,7 @@ end: 1 error */ +static int check_for_max_user_connections(THD *thd, USER_CONN *uc) { int error=0; @@ -141,7 +142,7 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc) if (max_user_connections && !uc->user_resources.user_conn && max_user_connections < (uint) uc->connections) { - net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user); + my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user); error=1; goto end; } @@ -149,24 +150,24 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc) if (uc->user_resources.user_conn && uc->user_resources.user_conn < uc->connections) { - net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, - "max_user_connections", - (long) uc->user_resources.user_conn); + my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, + "max_user_connections", + (long) uc->user_resources.user_conn); error= 1; goto end; } if (uc->user_resources.conn_per_hour && uc->user_resources.conn_per_hour <= uc->conn_per_hour) { - net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, - "max_connections_per_hour", - (long) uc->user_resources.conn_per_hour); + my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, + "max_connections_per_hour", + (long) uc->user_resources.conn_per_hour); error=1; goto end; } uc->conn_per_hour++; - end: +end: if (error) uc->connections--; // no need for decrease_user_connections() here (void) pthread_mutex_unlock(&LOCK_user_conn); @@ -258,8 +259,8 @@ bool check_mqh(THD *thd, uint check_command) if (uc->user_resources.questions && uc->questions++ >= uc->user_resources.questions) { - net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions", - (long) uc->user_resources.questions); + my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_questions", + (long) uc->user_resources.questions); error=1; goto end; } @@ -270,8 +271,8 @@ bool check_mqh(THD *thd, uint check_command) (sql_command_flags[check_command] & CF_CHANGES_DATA) && uc->updates++ >= uc->user_resources.updates) { - net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates", - (long) uc->user_resources.updates); + my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_updates", + (long) uc->user_resources.updates); error=1; goto end; } @@ -284,33 +285,33 @@ end: #endif /* NO_EMBEDDED_ACCESS_CHECKS */ -/* - Check if user exist and password supplied is correct. +/** + Check if user exist and password supplied is correct. - SYNOPSIS - check_user() - thd thread handle, thd->security_ctx->{host,user,ip} are used - command originator of the check: now check_user is called - during connect and change user procedures; used for - logging. - passwd scrambled password received from client - passwd_len length of scrambled password - db database name to connect to, may be NULL - check_count dont know exactly + @param thd thread handle, thd->security_ctx->{host,user,ip} are used + @param command originator of the check: now check_user is called + during connect and change user procedures; used for + logging. + @param passwd scrambled password received from client + @param passwd_len length of scrambled password + @param db database name to connect to, may be NULL + @param check_count TRUE if establishing a new connection. In this case + check that we have not exceeded the global + max_connections limist - Note, that host, user and passwd may point to communication buffer. - Current implementation does not depend on that, but future changes - should be done with this in mind; 'thd' is INOUT, all other params - are 'IN'. + @note Host, user and passwd may point to communication buffer. + Current implementation does not depend on that, but future changes + should be done with this in mind; 'thd' is INOUT, all other params + are 'IN'. - RETURN VALUE - 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and - thd->db are updated; OK is sent to client; - -1 access denied or handshake error; error is sent to client; - >0 error, not sent to client + @retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and + thd->db are updated; OK is sent to the client. + @retval 1 error, e.g. access denied or handshake error, not sent to + the client. A message is pushed into the error stack. */ -int check_user(THD *thd, enum enum_server_command command, +int +check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count) { @@ -328,11 +329,7 @@ int check_user(THD *thd, enum enum_server_command command, */ thd->reset_db(NULL, 0); if (mysql_change_db(thd, &db_str, FALSE)) - { - /* Send the error to the client */ - net_send_error(thd); - DBUG_RETURN(-1); - } + DBUG_RETURN(1); } send_ok(thd); DBUG_RETURN(0); @@ -349,14 +346,17 @@ int check_user(THD *thd, enum enum_server_command command, */ if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323) { - net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE); + my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0)); general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); - DBUG_RETURN(-1); + DBUG_RETURN(1); } if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH && passwd_len != SCRAMBLE_LENGTH_323) - DBUG_RETURN(ER_HANDSHAKE_ERROR); + { + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + DBUG_RETURN(1); + } /* Clear thd->db as it points to something, that will be freed when @@ -380,20 +380,21 @@ int check_user(THD *thd, enum enum_server_command command, NET *net= &thd->net; if (opt_secure_auth_local) { - net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE, - thd->main_security_ctx.user, - thd->main_security_ctx.host_or_ip); + my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0), + thd->main_security_ctx.user, + thd->main_security_ctx.host_or_ip); general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE), thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip); - DBUG_RETURN(-1); + DBUG_RETURN(1); } /* We have to read very specific packet size */ if (send_old_password_request(thd) || my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) { inc_host_errors(&thd->remote.sin_addr); - DBUG_RETURN(ER_HANDSHAKE_ERROR); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + DBUG_RETURN(1); } /* Final attempt to check the user based on reply */ /* So as passwd is short, errcode is always >= 0 */ @@ -427,8 +428,8 @@ int check_user(THD *thd, enum enum_server_command command, VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (!count_ok) { // too many connections - net_send_error(thd, ER_CON_COUNT_ERROR); - DBUG_RETURN(-1); + my_error(ER_CON_COUNT_ERROR, MYF(0)); + DBUG_RETURN(1); } } @@ -462,24 +463,29 @@ int check_user(THD *thd, enum enum_server_command command, (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip : thd->main_security_ctx.priv_host), &ur)) - DBUG_RETURN(-1); + { + /* The error is set by get_or_create_user_conn(). */ + DBUG_RETURN(1); + } if (thd->user_connect && (thd->user_connect->user_resources.conn_per_hour || thd->user_connect->user_resources.user_conn || max_user_connections) && check_for_max_user_connections(thd, thd->user_connect)) - DBUG_RETURN(-1); + { + /* The error is set in check_for_max_user_connections(). */ + DBUG_RETURN(1); + } /* Change database if necessary */ if (db && db[0]) { if (mysql_change_db(thd, &db_str, FALSE)) { - /* Send error to the client */ - net_send_error(thd); + /* mysql_change_db() has pushed the error message. */ if (thd->user_connect) decrease_user_connections(thd->user_connect); - DBUG_RETURN(-1); + DBUG_RETURN(1); } } send_ok(thd); @@ -490,19 +496,19 @@ int check_user(THD *thd, enum enum_server_command command, } else if (res == 2) // client gave short hash, server has long hash { - net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE); + my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0)); general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); - DBUG_RETURN(-1); + DBUG_RETURN(1); } - net_printf_error(thd, ER_ACCESS_DENIED_ERROR, - thd->main_security_ctx.user, - thd->main_security_ctx.host_or_ip, - passwd_len ? ER(ER_YES) : ER(ER_NO)); + my_error(ER_ACCESS_DENIED_ERROR, MYF(0), + thd->main_security_ctx.user, + thd->main_security_ctx.host_or_ip, + passwd_len ? ER(ER_YES) : ER(ER_NO)); general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); - DBUG_RETURN(-1); + DBUG_RETURN(1); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -666,9 +672,12 @@ static int check_connection(THD *thd) char ip[30]; if (vio_peer_addr(net->vio, ip, &thd->peer_port)) - return (ER_BAD_HOST_ERROR); - if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0)))) - return (ER_OUT_OF_RESOURCES); + { + my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; + } + if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME)))) + return 1; /* The error is set by my_strdup(). */ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; vio_in_addr(net->vio,&thd->remote.sin_addr); if (!(specialflag & SPECIAL_NO_RESOLVE)) @@ -685,7 +694,10 @@ static int check_connection(THD *thd) thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; } if (connect_errors > max_connect_errors) - return(ER_HOST_IS_BLOCKED); + { + my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; + } } DBUG_PRINT("info",("Host: %s ip: %s", (thd->main_security_ctx.host ? @@ -693,7 +705,11 @@ static int check_connection(THD *thd) (thd->main_security_ctx.ip ? thd->main_security_ctx.ip : "unknown ip"))); if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip)) - return(ER_HOST_NOT_PRIVILEGED); + { + my_error(ER_HOST_NOT_PRIVILEGED, MYF(0), + thd->main_security_ctx.host_or_ip); + return 1; + } } else /* Hostname given means that the connection was on a socket */ { @@ -753,7 +769,9 @@ static int check_connection(THD *thd) pkt_len < MIN_HANDSHAKE_SIZE) { inc_host_errors(&thd->remote.sin_addr); - return(ER_HANDSHAKE_ERROR); + my_error(ER_HANDSHAKE_ERROR, MYF(0), + thd->main_security_ctx.host_or_ip); + return 1; } } #ifdef _CUSTOMCONFIG_ @@ -762,7 +780,7 @@ static int check_connection(THD *thd) if (connect_errors) reset_host_errors(&thd->remote.sin_addr); if (thd->packet.alloc(thd->variables.net_buffer_length)) - return(ER_OUT_OF_RESOURCES); + return 1; /* The error is set by alloc(). */ thd->client_capabilities=uint2korr(net->read_pos); if (thd->client_capabilities & CLIENT_PROTOCOL_41) @@ -790,14 +808,16 @@ static int check_connection(THD *thd) if (!ssl_acceptor_fd) { inc_host_errors(&thd->remote.sin_addr); - return(ER_HANDSHAKE_ERROR); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; } DBUG_PRINT("info", ("IO layer change in progress...")); if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout)) { DBUG_PRINT("error", ("Failed to accept new SSL connection")); inc_host_errors(&thd->remote.sin_addr); - return(ER_HANDSHAKE_ERROR); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; } DBUG_PRINT("info", ("Reading user information over SSL layer")); if ((pkt_len= my_net_read(net)) == packet_error || @@ -806,7 +826,8 @@ static int check_connection(THD *thd) DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", pkt_len)); inc_host_errors(&thd->remote.sin_addr); - return(ER_HANDSHAKE_ERROR); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; } } #endif /* HAVE_OPENSSL */ @@ -814,7 +835,8 @@ static int check_connection(THD *thd) if (end >= (char*) net->read_pos+ pkt_len +2) { inc_host_errors(&thd->remote.sin_addr); - return(ER_HANDSHAKE_ERROR); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; } if (thd->client_capabilities & CLIENT_INTERACTIVE) @@ -851,7 +873,8 @@ static int check_connection(THD *thd) if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) { inc_host_errors(&thd->remote.sin_addr); - return ER_HANDSHAKE_ERROR; + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; } /* Since 4.1 all database names are stored in utf8 */ @@ -879,8 +902,8 @@ static int check_connection(THD *thd) if (thd->main_security_ctx.user) x_free(thd->main_security_ctx.user); - if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0)))) - return (ER_OUT_OF_RESOURCES); + if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME)))) + return 1; /* The error is set by my_strdup(). */ return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE); } @@ -929,7 +952,6 @@ bool setup_connection_thread_globals(THD *thd) bool login_connection(THD *thd) { - int error; NET *net= &thd->net; Security_context *sctx= thd->security_ctx; DBUG_ENTER("login_connection"); @@ -942,10 +964,9 @@ bool login_connection(THD *thd) my_net_set_read_timeout(net, connect_timeout); my_net_set_write_timeout(net, connect_timeout); - if ((error=check_connection(thd))) + if (check_connection(thd)) { // Wrong permissions - if (error > 0) - net_printf_error(thd, error, sctx->host_or_ip); + net_send_error(thd); #ifdef __NT__ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) my_sleep(1000); /* must wait after eof() */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ac042960388..803d29d83d6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -915,11 +915,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (res) { - /* authentication failure, we shall restore old user */ - if (res > 0) - my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - else - thd->clear_error(); // Error already sent to client x_free(thd->security_ctx->user); *thd->security_ctx= save_security_ctx; thd->user_connect= save_user_connect; From 26326ed0b7a630fd2990d560b009895fa1ea818f Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 00:31:57 +0300 Subject: [PATCH 73/92] A fix for Bug#32007 select udf_function() doesn't return an error if error during udf initialization. The bug is spotted while working on Bug 12713. If a user-defined function was used in a SELECT statement, and an error would occur during UDF initialization, this error would not terminate execution of the SELECT, but rather would be converted to a warning. The fix is to use a stack buffer to store the message from udf_init instead of private my_error() buffer. --- mysql-test/r/udf.result | 12 ++++++------ mysql-test/t/udf.test | 12 ++++++------ sql/item_func.cc | 5 +++-- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index da27a71c1a1..cb5afcf5f17 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -11,7 +11,7 @@ RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; select myfunc_double(); -ERROR HY000: myfunc_double must have at least one argument +ERROR HY000: Can't initialize function 'myfunc_double'; myfunc_double must have at least one argument select myfunc_double(1); myfunc_double(1) 49.00 @@ -24,26 +24,26 @@ select myfunc_int(); myfunc_int() 0 select lookup(); -ERROR HY000: Wrong arguments to lookup; Use the source +ERROR HY000: Can't initialize function 'lookup'; Wrong arguments to lookup; Use the source select lookup("127.0.0.1"); lookup("127.0.0.1") 127.0.0.1 select lookup(127,0,0,1); -ERROR HY000: Wrong arguments to lookup; Use the source +ERROR HY000: Can't initialize function 'lookup'; Wrong arguments to lookup; Use the source select lookup("localhost"); lookup("localhost") 127.0.0.1 select reverse_lookup(); -ERROR HY000: Wrong number of arguments to reverse_lookup; Use the source +ERROR HY000: Can't initialize function 'reverse_lookup'; Wrong number of arguments to reverse_lookup; Use the source select reverse_lookup("127.0.0.1"); select reverse_lookup(127,0,0,1); select reverse_lookup("localhost"); reverse_lookup("localhost") NULL select avgcost(); -ERROR HY000: wrong number of arguments: AVGCOST() requires two arguments +ERROR HY000: Can't initialize function 'avgcost'; wrong number of arguments: AVGCOST() requires two arguments select avgcost(100,23.76); -ERROR HY000: wrong argument type: AVGCOST() requires an INT and a REAL +ERROR HY000: Can't initialize function 'avgcost'; wrong argument type: AVGCOST() requires an INT and a REAL create table t1(sum int, price float(24)); insert into t1 values(100, 50.00), (100, 100.00); select avgcost(sum, price) from t1; diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 663dc08d72e..32cfca57546 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -35,20 +35,20 @@ eval CREATE FUNCTION reverse_lookup eval CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "$UDF_EXAMPLE_LIB"; ---error 0 +--error ER_CANT_INITIALIZE_UDF select myfunc_double(); select myfunc_double(1); select myfunc_double(78654); --error 1305 select myfunc_nonexist(); select myfunc_int(); ---error 0 +--error ER_CANT_INITIALIZE_UDF select lookup(); select lookup("127.0.0.1"); ---error 0 +--error ER_CANT_INITIALIZE_UDF select lookup(127,0,0,1); select lookup("localhost"); ---error 0 +--error ER_CANT_INITIALIZE_UDF select reverse_lookup(); # These two functions should return "localhost", but it's @@ -59,9 +59,9 @@ select reverse_lookup(127,0,0,1); --enable_result_log select reverse_lookup("localhost"); ---error 0 +--error ER_CANT_INITIALIZE_UDF select avgcost(); ---error 0 +--error ER_CANT_INITIALIZE_UDF select avgcost(100,23.76); create table t1(sum int, price float(24)); insert into t1 values(100, 50.00), (100, 100.00); diff --git a/sql/item_func.cc b/sql/item_func.cc index 2d4d61de61b..ec0ecc89394 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2897,6 +2897,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, if (u_d->func_init) { + char init_msg_buff[MYSQL_ERRMSG_SIZE]; char *to=num_buffer; for (uint i=0; i < arg_count; i++) { @@ -2949,10 +2950,10 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, } thd->net.last_error[0]=0; Udf_func_init init= u_d->func_init; - if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) + if ((error=(uchar) init(&initid, &f_args, init_msg_buff))) { my_error(ER_CANT_INITIALIZE_UDF, MYF(0), - u_d->name.str, thd->net.last_error); + u_d->name.str, init_msg_buff); free_udf(u_d); DBUG_RETURN(TRUE); } From 480ee022ad81257ad16072f2cdcd7cba8d20722d Mon Sep 17 00:00:00 2001 From: "jmiller/ndbdev@mysql.com/ndb15.mysql.com" <> Date: Wed, 31 Oct 2007 22:37:10 +0100 Subject: [PATCH 74/92] Adding dbutil to ndb test lib --- storage/ndb/test/include/dbutil.hpp | 97 +++++++++++++++ storage/ndb/test/src/Makefile.am | 2 +- storage/ndb/test/src/dbutil.cpp | 176 ++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+), 1 deletion(-) create mode 100755 storage/ndb/test/include/dbutil.hpp create mode 100755 storage/ndb/test/src/dbutil.cpp diff --git a/storage/ndb/test/include/dbutil.hpp b/storage/ndb/test/include/dbutil.hpp new file mode 100755 index 00000000000..2b36965715f --- /dev/null +++ b/storage/ndb/test/include/dbutil.hpp @@ -0,0 +1,97 @@ +// dbutil.h: interface for the database utilities class. +////////////////////////////////////////////////////////////////////// +// Supplies a database to the test application +////////////////////////////////////////////////////////////////////// + +#ifndef DBUTIL_HPP +#define DBUTIL_HPP + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include +#include +#include +#include +//include "rand.h" +#include + +//#define DEBUG +#define DIE_UNLESS(expr) \ + ((void) ((expr) ? 0 : (Die(__FILE__, __LINE__, #expr), 0))) +#define DIE(expr) \ + Die(__FILE__, __LINE__, #expr) +#define myerror(msg) PrintError(msg) +#define mysterror(stmt, msg) PrintStError(stmt, msg) +#define CheckStmt(stmt) \ +{ \ +if ( stmt == 0) \ + myerror(NULL); \ +DIE_UNLESS(stmt != 0); \ +} + +#define check_execute(stmt, r) \ +{ \ +if (r) \ + mysterror(stmt, NULL); \ +DIE_UNLESS(r == 0);\ +} + +#define TRUE 1 +#define FALSE 0 + + +class dbutil +{ +public: + + dbutil(const char * databaseName); + ~dbutil(); + + void DatabaseLogin(const char * system, + const char * usr, + const char * password, + unsigned int portIn, + const char * sockIn, + bool transactional); + char * GetDbName(){return dbs;}; + char * GetUser(){return user;}; + char * GetPassword(){return pass;}; + char * GetHost(){return host;}; + char * GetSocket(){return socket;}; + const char * GetServerType(){return mysql_get_server_info(myDbHandel);}; + MYSQL* GetDbHandel(){return myDbHandel;}; + MYSQL_STMT *STDCALL MysqlSimplePrepare(const char *query); + int Select_DB(); + int Do_Query(char * stm); + const char * GetError(); + int GetErrorNumber(); + unsigned long SelectCountTable(const char * table); + +private: + + //Connect variables + char * databaseName; //hold results file name + char host[256]; // Computer to connect to + char user[256]; // MySQL User + char pass[256]; // MySQL User Password + char dbs[256]; // Database to use (TPCB) + unsigned int port; // MySQL Server port + char socket[256]; // MySQL Server Unix Socket + MYSQL *myDbHandel; + + void DatabaseLogout(); + + void SetDbName(const char * name){strcpy((char *)dbs, name);}; + void SetUser(const char * userName){strcpy((char *)user, userName);}; + void SetPassword(const char * password){strcpy((char *)pass,password);}; + void SetHost(const char * system){strcpy((char*)host, system);}; + void SetPort(unsigned int portIn){port=portIn;}; + void SetSocket(const char * sockIn){strcpy((char *)socket, sockIn);}; + void PrintError(const char *msg); + void PrintStError(MYSQL_STMT *stmt, const char *msg); + void Die(const char *file, int line, const char *expr); // stop program + +}; +#endif + diff --git a/storage/ndb/test/src/Makefile.am b/storage/ndb/test/src/Makefile.am index a025579cb72..aa486108235 100644 --- a/storage/ndb/test/src/Makefile.am +++ b/storage/ndb/test/src/Makefile.am @@ -24,7 +24,7 @@ libNDBT_a_SOURCES = \ NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \ NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \ NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c \ - CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp + CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp dbutil.cpp INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi diff --git a/storage/ndb/test/src/dbutil.cpp b/storage/ndb/test/src/dbutil.cpp new file mode 100755 index 00000000000..0c936f53182 --- /dev/null +++ b/storage/ndb/test/src/dbutil.cpp @@ -0,0 +1,176 @@ +// dbutil.cpp: implementation of the database utilities class. +// +////////////////////////////////////////////////////////////////////// + +#include "dbutil.hpp" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +dbutil::dbutil(const char * dbname) +{ + memset(host,' ',sizeof(host)); + memset(user,' ',sizeof(pass)); + memset(dbs,' ',sizeof(dbs)); + port = 0; + memset(socket,' ',sizeof(socket)); + this->SetDbName(dbname); +} + +dbutil::~dbutil() +{ + this->DatabaseLogout(); +} + +////////////////////////////////////////////////////////////////////// +// Database Login +////////////////////////////////////////////////////////////////////// +void dbutil::DatabaseLogin(const char* system, + const char* usr, + const char* password, + unsigned int portIn, + const char* sockIn, + bool transactional + ){ + if (!(myDbHandel = mysql_init(NULL))){ + myerror("mysql_init() failed"); + exit(1); + } + this->SetUser(usr); + this->SetHost(system); + this->SetPassword(password); + this->SetPort(portIn); + this->SetSocket(sockIn); + + if (!(mysql_real_connect(myDbHandel, host, user, pass, "test", port, socket, 0))){ + myerror("connection failed"); + mysql_close(myDbHandel); + fprintf(stdout, "\n Check the connection options using --help or -?\n"); + exit(1); + } + + myDbHandel->reconnect= 1; + + /* set AUTOCOMMIT */ + if(!transactional){ + mysql_autocommit(myDbHandel, TRUE); + } + else{ + mysql_autocommit(myDbHandel, FALSE); + } + + fprintf(stdout, "\n\tConnected to MySQL server version: %s (%lu)\n\n", + mysql_get_server_info(myDbHandel), + (unsigned long) mysql_get_server_version(myDbHandel)); +} + +////////////////////////////////////////////////////////////////////// +// Database Logout +////////////////////////////////////////////////////////////////////// +void dbutil::DatabaseLogout(){ + if (myDbHandel){ + fprintf(stdout, "\n\tClosing the MySQL database connection ...\n\n"); + mysql_close(myDbHandel); + } +} + +////////////////////////////////////////////////////////////////////// +// Prepare MySQL Statements Cont +////////////////////////////////////////////////////////////////////// +MYSQL_STMT *STDCALL dbutil::MysqlSimplePrepare(const char *query){ +#ifdef DEBUG +printf("Inside dbutil::MysqlSimplePrepare\n"); +#endif +int result = 0; + MYSQL_STMT *my_stmt= mysql_stmt_init(this->GetDbHandel()); + if (my_stmt && (result = mysql_stmt_prepare(my_stmt, query, strlen(query)))){ + printf("res = %s\n",mysql_stmt_error(my_stmt)); + mysql_stmt_close(my_stmt); + return 0; + } + return my_stmt; +} +////////////////////////////////////////////////////////////////////// +// Error Printing +////////////////////////////////////////////////////////////////////// +void dbutil::PrintError(const char *msg){ + if (this->GetDbHandel() + && mysql_errno(this->GetDbHandel())){ + if (this->GetDbHandel()->server_version){ + fprintf(stdout, "\n [MySQL-%s]", + this->GetDbHandel()->server_version); + } + else + fprintf(stdout, "\n [MySQL]"); + fprintf(stdout, "[%d] %s\n", + mysql_errno(this->GetDbHandel()), + mysql_error(this->GetDbHandel())); + } + else if (msg) + fprintf(stderr, " [MySQL] %s\n", msg); +} + +void dbutil::PrintStError(MYSQL_STMT *stmt, const char *msg) +{ + if (stmt && mysql_stmt_errno(stmt)) + { + if (this->GetDbHandel() + && this->GetDbHandel()->server_version) + fprintf(stdout, "\n [MySQL-%s]", + this->GetDbHandel()->server_version); + else + fprintf(stdout, "\n [MySQL]"); + + fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt), + mysql_stmt_error(stmt)); + } + else if (msg) + fprintf(stderr, " [MySQL] %s\n", msg); +} +///////////////////////////////////////////////////// +int dbutil::Select_DB() +{ + return mysql_select_db(this->GetDbHandel(), + this->GetDbName()); +} +//////////////////////////////////////////////////// +int dbutil::Do_Query(char * stm) +{ + return mysql_query(this->GetDbHandel(), stm); +} +//////////////////////////////////////////////////// +const char * dbutil::GetError() +{ + return mysql_error(this->GetDbHandel()); +} +//////////////////////////////////////////////////// +int dbutil::GetErrorNumber() +{ + return mysql_errno(this->GetDbHandel()); +} +//////////////////////////////////////////////////// +unsigned long dbutil::SelectCountTable(const char * table) +{ + unsigned long count = 0; + MYSQL_RES *result; + char query[1024]; + MYSQL_ROW row; + + sprintf(query,"select count(*) from `%s`", table); + if (mysql_query(this->GetDbHandel(),query) || !(result=mysql_store_result(this->GetDbHandel()))) + { + printf("error\n"); + return 1; + } + row= mysql_fetch_row(result); + count= (ulong) strtoull(row[0], (char**) 0, 10); + mysql_free_result(result); + + return count; +} +void dbutil::Die(const char *file, int line, const char *expr){ + fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr); + abort(); +} + + From 8423c7ef227cf34f9f274659778abfdc8f869ef0 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 00:55:25 +0300 Subject: [PATCH 75/92] Another attempt to fix the Windows compilation failre. --- sql-common/client.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 5ece9c39d6c..0ca7ef16c0d 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -349,7 +349,7 @@ static void set_mysql_extended_error(MYSQL *mysql, int errcode, #ifdef __WIN__ -HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, +HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host, char **arg_unix_socket) { HANDLE hPipe=INVALID_HANDLE_VALUE; @@ -1950,8 +1950,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, (! have_tcpip && (unix_socket || !host && is_NT())))) { sock=0; - if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout, - (char**) &host, (char**) &unix_socket)) == + if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout, + (char**) &host, (char**) &unix_socket)) == INVALID_HANDLE_VALUE) { DBUG_PRINT("error", From 084849d917a7fe499c4392fa67ca709ed47c482f Mon Sep 17 00:00:00 2001 From: "knielsen@ymer.(none)" <> Date: Thu, 1 Nov 2007 07:59:55 +0100 Subject: [PATCH 76/92] Bug #31848: Test failure: Cluster has problems on insert with auto-increment Fix uninitialized variable causing failures for some interpreted update operations on gcc 4.2.1. --- ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 1986a108e5d..298fb183bc3 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1138,7 +1138,8 @@ Dbtup::updateStartLab(Signal* signal, regOperPtr->attrinbufLen); } else { jam(); - if (interpreterStartLab(signal, pagePtr, regOperPtr->pageOffset) == -1) + retValue = interpreterStartLab(signal, pagePtr, regOperPtr->pageOffset); + if (retValue == -1) { jam(); return -1; From 91b070b082d8a3cbcc1bb207a70c136a5c957c20 Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Thu, 1 Nov 2007 12:02:41 +0100 Subject: [PATCH 77/92] disable tests --- .bzrignore | 1 + mysql-test/suite/rpl/t/disabled.def | 4 ++-- mysql-test/suite/rpl_ndb/t/disabled.def | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.bzrignore b/.bzrignore index e1ad5a89015..c0bac9d05f1 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3004,3 +3004,4 @@ win/vs71cache.txt win/vs8cache.txt zlib/*.ds? zlib/*.vcproj +libmysql_r/client_settings.h diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index 0c90eaa4378..426bf93ae97 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -13,5 +13,5 @@ rpl_ddl : BUG#26418 2007-03-01 mleich Slave out of sync after CREATE/DROP TEMPORARY TABLE + ROLLBACK on master rpl_invoked_features : BUG#29020 2007-06-21 Lars Non-deterministic test case rpl_auto_increment_11932 : Bug#29809 2007-07-16 ingo Slave SQL errors in warnings file -rpl_stm_extraColmaster_ndb : WL#3915 : Statement-based replication not supported in ndb. Enable test when supported. -rpl_row_extraColmaster_ndb : BUG#29549 : Replication of BLOBs fail for NDB +rpl_extraColmaster_innodb : BUG#30854 : Tables name show as binary in slave err msg on vm-win2003-64-b and Solaris +rpl_extraColmaster_myisam : BUG#30854 diff --git a/mysql-test/suite/rpl_ndb/t/disabled.def b/mysql-test/suite/rpl_ndb/t/disabled.def index f372d44cb90..c51a9b5a4b9 100644 --- a/mysql-test/suite/rpl_ndb/t/disabled.def +++ b/mysql-test/suite/rpl_ndb/t/disabled.def @@ -11,8 +11,8 @@ ############################################################################## -rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated -rpl_ndb_2myisam : BUG#19227 Seems to pass currently +rpl_ndb_2innodb : Bug#29549 rpl_ndb_myisam2ndb,rpl_ndb_innodb2ndb failed on Solaris for pack_length issue +rpl_ndb_2myisam : Bug#29549 rpl_ndb_myisam2ndb,rpl_ndb_innodb2ndb failed on Solaris for pack_length issue rpl_ndb_2other : BUG#21842 2007-08-30 tsmith test has never worked on bigendian (sol10-sparc-a, powermacg5 rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD rpl_ndb_innodb2ndb : Bug#29549 rpl_ndb_myisam2ndb,rpl_ndb_innodb2ndb failed on Solaris for pack_length issue From f60b89096771e0d4eb05c2532540e7d57d04b826 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 17:00:24 +0300 Subject: [PATCH 78/92] Fix a compilation warning. --- sql/sql_connect.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 9b5f1a9b0e5..90df233896a 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -953,7 +953,6 @@ bool setup_connection_thread_globals(THD *thd) bool login_connection(THD *thd) { NET *net= &thd->net; - Security_context *sctx= thd->security_ctx; DBUG_ENTER("login_connection"); DBUG_PRINT("info", ("login_connection called by thread %lu", thd->thread_id)); From 6bd9f5c1cb1875b1a0b962a29c408f299222479e Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 17:08:02 +0300 Subject: [PATCH 79/92] Use thd->is_error() instead of direct access to thd->net.report_error in evaluate_join_record(). A minor cleanup required for the fix for Bug#12713. --- sql/sql_select.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ef1151d82f3..338b5f0cc3f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -122,7 +122,7 @@ static int do_select(JOIN *join,List *fields,TABLE *tmp_table, static enum_nested_loop_state evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, - int error, my_bool *report_error); + int error); static enum_nested_loop_state evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab); static enum_nested_loop_state @@ -10871,7 +10871,6 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) int error; enum_nested_loop_state rc; - my_bool *report_error= &(join->thd->net.report_error); READ_RECORD *info= &join_tab->read_record; if (join->resume_nested_loop) @@ -10903,13 +10902,13 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) join->thd->row_count= 0; error= (*join_tab->read_first_record)(join_tab); - rc= evaluate_join_record(join, join_tab, error, report_error); + rc= evaluate_join_record(join, join_tab, error); } while (rc == NESTED_LOOP_OK) { error= info->read_record(info); - rc= evaluate_join_record(join, join_tab, error, report_error); + rc= evaluate_join_record(join, join_tab, error); } if (rc == NESTED_LOOP_NO_MORE_ROWS && @@ -10933,13 +10932,13 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) static enum_nested_loop_state evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, - int error, my_bool *report_error) + int error) { bool not_used_in_distinct=join_tab->not_used_in_distinct; ha_rows found_records=join->found_records; COND *select_cond= join_tab->select_cond; - if (error > 0 || (*report_error)) // Fatal error + if (error > 0 || (join->thd->is_error())) // Fatal error return NESTED_LOOP_ERROR; if (error < 0) return NESTED_LOOP_NO_MORE_ROWS; From 7e119ec0d19f72a0f37823ee678409de85f5c676 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 18:06:46 +0300 Subject: [PATCH 80/92] Use Internal_error_handler mechanism to silence ER_TOO_MANY_FIELDS error in mysql_create_frm instead of direct access to my_error() members. This is a pre-requisite for the patch for Bug#12713. --- sql/unireg.cc | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/sql/unireg.cc b/sql/unireg.cc index f9e8e54439a..f2238d69973 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -47,6 +47,35 @@ static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type, uint reclength, ulong data_offset, handler *handler); +/** + An interceptor to hijack ER_TOO_MANY_FIELDS error from + pack_screens and retry again without UNIREG screens. + + XXX: what is a UNIREG screen? +*/ + +struct Pack_header_error_handler: public Internal_error_handler +{ + virtual bool handle_error(uint sql_errno, + const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd); + bool is_handled; + Pack_header_error_handler() :is_handled(FALSE) {} +}; + + +bool +Pack_header_error_handler:: +handle_error(uint sql_errno, + const char * /* message */, + MYSQL_ERROR::enum_warning_level /* level */, + THD * /* thd */) +{ + is_handled= (sql_errno == ER_TOO_MANY_FIELDS); + return is_handled; +} + /* Create a frm (table definition) file @@ -86,6 +115,8 @@ bool mysql_create_frm(THD *thd, const char *file_name, #ifdef WITH_PARTITION_STORAGE_ENGINE partition_info *part_info= thd->work_part_info; #endif + Pack_header_error_handler pack_header_error_handler; + int error; DBUG_ENTER("mysql_create_frm"); DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension @@ -99,17 +130,22 @@ bool mysql_create_frm(THD *thd, const char *file_name, create_info->null_bits++; data_offset= (create_info->null_bits + 7) / 8; - if (pack_header(forminfo, ha_legacy_type(create_info->db_type), - create_fields,info_length, - screens, create_info->table_options, - data_offset, db_file)) + thd->push_internal_handler(&pack_header_error_handler); + + error= pack_header(forminfo, ha_legacy_type(create_info->db_type), + create_fields,info_length, + screens, create_info->table_options, + data_offset, db_file); + + thd->pop_internal_handler(); + + if (error) { my_free(screen_buff, MYF(0)); - if (thd->net.last_errno != ER_TOO_MANY_FIELDS) + if (! pack_header_error_handler.is_handled) DBUG_RETURN(1); // Try again without UNIREG screens (to get more columns) - thd->net.last_error[0]=0; if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1))) DBUG_RETURN(1); if (pack_header(forminfo, ha_legacy_type(create_info->db_type), From 8f90f66d434d27d840fd258e0fa9270c5dd1f2fe Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Thu, 1 Nov 2007 18:33:51 +0300 Subject: [PATCH 81/92] Cleanup execute_ddl_log_recovery() to not generate an error if there is nothing to recover. Discovered while working on Bug#12713 --- sql/sql_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6edb8494b03..328b5e71a44 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -434,7 +434,7 @@ static uint read_ddl_log_header() create_ddl_log_file_name(file_name); if ((global_ddl_log.file_id= my_open(file_name, - O_RDWR | O_BINARY, MYF(MY_WME))) >= 0) + O_RDWR | O_BINARY, MYF(0))) >= 0) { if (read_ddl_log_file_entry(0UL)) { From a76f0e3d12feedf8a8ee87a4e1249deaead14a7f Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Thu, 1 Nov 2007 17:24:21 +0100 Subject: [PATCH 82/92] disable test --- mysql-test/suite/rpl_ndb/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl_ndb/t/disabled.def b/mysql-test/suite/rpl_ndb/t/disabled.def index c51a9b5a4b9..05e8297bf0e 100644 --- a/mysql-test/suite/rpl_ndb/t/disabled.def +++ b/mysql-test/suite/rpl_ndb/t/disabled.def @@ -20,7 +20,7 @@ rpl_ndb_myisam2ndb : Bug#29549 rpl_ndb_myisam2ndb,rpl_ndb_innodb2ndb faile rpl_ndb_ddl : BUG#28798 2007-05-31 lars Valgrind failure in NDB rpl_ndb_mix_innodb : BUG#28123 rpl_ndb_mix_innodb.test casue slave to core on sol10-sparc-a rpl_ndb_ctype_ucs2_def : BUG#27404 util thd mysql_parse sig11 when mysqld default multibyte charset - +rpl_ndb_extraColMaster : BUG#30854 : Tables name show as binary in slave err msg on vm-win2003-64-b and Solaris # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open From 968af721502f47b061e716f955716293e9f2597e Mon Sep 17 00:00:00 2001 From: "davi@endora.local" <> Date: Thu, 1 Nov 2007 17:29:20 -0200 Subject: [PATCH 83/92] Bug#31850 Test crashes in "embedded" server The mysql_change_user command fails to properly update the database pointer when no database is selected, leading to "use after free" errors. The same happens on the user privilege pointer in the thread security context. The solution is to properly reset and update the database name. Also update the user_priv pointer so that it doesn't point to freed memory. --- sql/sql_connect.cc | 23 +++++++++-------------- sql/sql_parse.cc | 5 +++-- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 8a817e5993a..adf0b9e01ed 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -316,17 +316,20 @@ int check_user(THD *thd, enum enum_server_command command, { DBUG_ENTER("check_user"); LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 }; - + + /* + Clear thd->db as it points to something, that will be freed when + connection is closed. We don't want to accidentally free a wrong + pointer if connect failed. Also in case of 'CHANGE USER' failure, + current database will be switched to 'no database selected'. + */ + thd->reset_db(NULL, 0); + #ifdef NO_EMBEDDED_ACCESS_CHECKS thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights /* Change database if necessary */ if (db && db[0]) { - /* - thd->db is saved in caller and needs to be freed by caller if this - function returns 0 - */ - thd->reset_db(NULL, 0); if (mysql_change_db(thd, &db_str, FALSE)) { /* Send the error to the client */ @@ -358,14 +361,6 @@ int check_user(THD *thd, enum enum_server_command command, passwd_len != SCRAMBLE_LENGTH_323) DBUG_RETURN(ER_HANDSHAKE_ERROR); - /* - Clear thd->db as it points to something, that will be freed when - connection is closed. We don't want to accidentally free a wrong pointer - if connect failed. Also in case of 'CHANGE USER' failure, current - database will be switched to 'no database selected'. - */ - thd->reset_db(NULL, 0); - USER_RESOURCES ur; int res= acl_getroot(thd, &ur, passwd, passwd_len); #ifndef EMBEDDED_LIBRARY diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 85457fea41b..b2f2e74999b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -911,6 +911,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Clear variables that are allocated */ thd->user_connect= 0; + thd->security_ctx->priv_user= thd->security_ctx->user; res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); if (res) @@ -933,8 +934,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (save_user_connect) decrease_user_connections(save_user_connect); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ - x_free((uchar*) save_db); - x_free((uchar*) save_security_ctx.user); + x_free(save_db); + x_free(save_security_ctx.user); if (cs_number) { From cc007acb785d12cb6f5f176320ad9d099937fd9c Mon Sep 17 00:00:00 2001 From: "davi@endora.local" <> Date: Thu, 1 Nov 2007 18:52:56 -0200 Subject: [PATCH 84/92] Bug#30882 Dropping a temporary table inside a stored function may cause a server crash If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed). --- mysql-test/include/handler.inc | 32 +++++++ mysql-test/r/handler_innodb.result | 62 +++++++++++++ mysql-test/r/handler_myisam.result | 62 +++++++++++++ mysql-test/r/sp-error.result | 52 ++++++++++- mysql-test/t/sp-error.test | 74 ++++++++++++++- sql/event_db_repository.cc | 2 +- sql/mysql_priv.h | 4 +- sql/slave.cc | 2 +- sql/sp_head.cc | 2 +- sql/sql_base.cc | 141 ++++++++++++++++++----------- sql/sql_handler.cc | 14 +++ sql/sql_insert.cc | 2 +- sql/sql_parse.cc | 15 ++- sql/sql_table.cc | 28 ++++-- sql/table.h | 22 ++++- 15 files changed, 431 insertions(+), 83 deletions(-) diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index 71647112126..79e21382d4c 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -566,3 +566,35 @@ reap; connection default; drop table t2; disconnect flush; + +# +# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash +# +# Test HANDLER statements in conjunction with temporary tables. While the temporary table +# is open by a HANDLER, no other statement can access it. +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create temporary table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), + (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +select a,b from t1; +handler t1 open as a1; +handler a1 read a first; +handler a1 read a next; +handler a1 read a next; +--error ER_CANT_REOPEN_TABLE +select a,b from t1; +handler a1 read a prev; +handler a1 read a prev; +handler a1 read a=(6) where b="g"; +handler a1 close; +select a,b from t1; +handler t1 open as a2; +handler a2 read a first; +handler a2 read a last; +handler a2 read a prev; +handler a2 close; +drop table t1; diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/r/handler_innodb.result index e9e5c7dbdd5..d9a1a0aa12b 100644 --- a/mysql-test/r/handler_innodb.result +++ b/mysql-test/r/handler_innodb.result @@ -575,3 +575,65 @@ ERROR 42S02: Table 'test.t1' doesn't exist handler t1 close; handler t2 close; drop table t2; +drop table if exists t1; +create temporary table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +select a,b from t1; +a b +0 a +1 b +2 c +3 d +4 e +5 f +6 g +7 h +8 i +9 j +handler t1 open as a1; +handler a1 read a first; +a b +0 a +handler a1 read a next; +a b +1 b +handler a1 read a next; +a b +2 c +select a,b from t1; +ERROR HY000: Can't reopen table: 'a1' +handler a1 read a prev; +a b +1 b +handler a1 read a prev; +a b +0 a +handler a1 read a=(6) where b="g"; +a b +6 g +handler a1 close; +select a,b from t1; +a b +0 a +1 b +2 c +3 d +4 e +5 f +6 g +7 h +8 i +9 j +handler t1 open as a2; +handler a2 read a first; +a b +0 a +handler a2 read a last; +a b +9 j +handler a2 read a prev; +a b +8 i +handler a2 close; +drop table t1; diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index 715e5ab03d6..b42fdc864fe 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -575,3 +575,65 @@ ERROR 42S02: Table 'test.t1' doesn't exist handler t1 close; handler t2 close; drop table t2; +drop table if exists t1; +create temporary table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +select a,b from t1; +a b +0 a +1 b +2 c +3 d +4 e +5 f +6 g +7 h +8 i +9 j +handler t1 open as a1; +handler a1 read a first; +a b +0 a +handler a1 read a next; +a b +1 b +handler a1 read a next; +a b +2 c +select a,b from t1; +ERROR HY000: Can't reopen table: 'a1' +handler a1 read a prev; +a b +1 b +handler a1 read a prev; +a b +0 a +handler a1 read a=(6) where b="g"; +a b +6 g +handler a1 close; +select a,b from t1; +a b +0 a +1 b +2 c +3 d +4 e +5 f +6 g +7 h +8 i +9 j +handler t1 open as a2; +handler a2 read a first; +a b +0 a +handler a2 read a last; +a b +9 j +handler a2 read a prev; +a b +8 i +handler a2 close; +drop table t1; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 300fa42f3ad..b81f8ea64c9 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1428,7 +1428,6 @@ create function bug20701() returns varchar(25) binary return "test"; ERROR 42000: This version of MySQL doesn't yet support 'return value collation' create function bug20701() returns varchar(25) return "test"; drop function bug20701; -End of 5.1 tests create procedure proc_26503_error_1() begin retry: @@ -1530,6 +1529,53 @@ return 1; end| ERROR HY000: Not allowed to set autocommit from a stored function or trigger create trigger t1 -before insert on t2 for each row set password = password('foo'); -delimiter ;| +before insert on t2 for each row set password = password('foo');| ERROR HY000: Not allowed to set autocommit from a stored function or trigger +drop function if exists f1; +drop function if exists f2; +drop table if exists t1, t2; +create function f1() returns int +begin +drop temporary table t1; +return 1; +end| +create temporary table t1 as select f1(); +ERROR HY000: Can't reopen table: 't1' +create function f2() returns int +begin +create temporary table t2 as select f1(); +return 1; +end| +create temporary table t1 as select f2(); +ERROR HY000: Can't reopen table: 't1' +drop function f1; +drop function f2; +create function f1() returns int +begin +drop temporary table t2,t1; +return 1; +end| +create function f2() returns int +begin +create temporary table t2 as select f1(); +return 1; +end| +create temporary table t1 as select f2(); +ERROR HY000: Can't reopen table: 't2' +drop function f1; +drop function f2; +create temporary table t2(a int); +select * from t2; +a +create function f2() returns int +begin +drop temporary table t2; +return 1; +end| +select f2(); +f2() +1 +drop function f2; +drop table t2; +ERROR 42S02: Unknown table 't2' +End of 5.1 tests diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 9f20d02480c..606c2a673bc 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2078,10 +2078,6 @@ create function bug20701() returns varchar(25) binary return "test"; create function bug20701() returns varchar(25) return "test"; drop function bug20701; - ---echo End of 5.1 tests - - # # Bug#26503 (Illegal SQL exception handler code causes the server to crash) # @@ -2237,10 +2233,78 @@ end| --error ER_SP_CANT_SET_AUTOCOMMIT create trigger t1 - before insert on t2 for each row set password = password('foo'); + before insert on t2 for each row set password = password('foo');| delimiter ;| +# +# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash +# + +--disable_warnings +drop function if exists f1; +drop function if exists f2; +drop table if exists t1, t2; +--enable_warnings + +delimiter |; +create function f1() returns int +begin + drop temporary table t1; + return 1; +end| +delimiter ;| +--error ER_CANT_REOPEN_TABLE +create temporary table t1 as select f1(); + +delimiter |; +create function f2() returns int +begin + create temporary table t2 as select f1(); + return 1; +end| +delimiter ;| +--error ER_CANT_REOPEN_TABLE +create temporary table t1 as select f2(); + +drop function f1; +drop function f2; + +delimiter |; +create function f1() returns int +begin + drop temporary table t2,t1; + return 1; +end| +create function f2() returns int +begin + create temporary table t2 as select f1(); + return 1; +end| +delimiter ;| +--error ER_CANT_REOPEN_TABLE +create temporary table t1 as select f2(); + +drop function f1; +drop function f2; + +create temporary table t2(a int); +select * from t2; +delimiter |; +create function f2() returns int +begin + drop temporary table t2; + return 1; +end| +delimiter ;| +select f2(); + +drop function f2; +--error ER_BAD_TABLE_ERROR +drop table t2; + +--echo End of 5.1 tests + # # BUG#NNNN: New bug synopsis # diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 4451e763ff7..9a33b33d8c9 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -549,7 +549,7 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, if (simple_open_n_lock_tables(thd, &tables)) { - close_thread_tables(thd, FALSE, FALSE); + close_thread_tables(thd); DBUG_RETURN(TRUE); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3484b8096e3..12838317646 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -679,7 +679,7 @@ extern my_decimal decimal_zero; void free_items(Item *item); void cleanup_items(Item *item); class THD; -void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); +void close_thread_tables(THD *thd); bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables); bool check_single_table_access(THD *thd, ulong privilege, TABLE_LIST *tables, bool no_errors); @@ -1419,7 +1419,7 @@ TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, bool check_alias); TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name); TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list); -bool close_temporary_table(THD *thd, TABLE_LIST *table_list); +int drop_temporary_table(THD *thd, TABLE_LIST *table_list); void close_temporary_table(THD *thd, TABLE *table, bool free_share, bool delete_table); void close_temporary(TABLE *table, bool free_share, bool delete_table); diff --git a/sql/slave.cc b/sql/slave.cc index 494e13d8c9f..7abcf50fa75 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2353,7 +2353,7 @@ err: change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE); DBUG_ASSERT(thd->net.buff != 0); net_end(&thd->net); // destructor will not free it, because net.vio is 0 - close_thread_tables(thd, 0); + close_thread_tables(thd); pthread_mutex_lock(&LOCK_thread_count); THD_CHECK_SENTRY(thd); delete thd; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6e8749aa745..c0ea73a6c00 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1872,7 +1872,7 @@ sp_head::execute_procedure(THD *thd, List *args) we'll leave it here. */ if (!thd->in_sub_stmt) - close_thread_tables(thd, 0, 0); + close_thread_tables(thd); DBUG_PRINT("info",(" %.*s: eval args done", (int) m_name.length, m_name.str)); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 2584390d756..ddc5f88f577 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1055,6 +1055,29 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, } +/** + Mark all temporary tables which were used by the current statement or + substatement as free for reuse, but only if the query_id can be cleared. + + @param thd thread context + + @remark For temp tables associated with a open SQL HANDLER the query_id + is not reset until the HANDLER is closed. +*/ + +static void mark_temp_tables_as_free_for_reuse(THD *thd) +{ + for (TABLE *table= thd->temporary_tables ; table ; table= table->next) + { + if ((table->query_id == thd->query_id) && ! table->open_by_handler) + { + table->query_id= 0; + table->file->ha_reset(); + } + } +} + + /* Mark all tables in the list which were used by current substatement as free for reuse. @@ -1091,6 +1114,42 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) } +/** + Auxiliary function to close all tables in the open_tables list. + + @param thd Thread context. + + @remark It should not ordinarily be called directly. +*/ + +static void close_open_tables(THD *thd) +{ + bool found_old_table= 0; + + safe_mutex_assert_not_owner(&LOCK_open); + + VOID(pthread_mutex_lock(&LOCK_open)); + + DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); + + while (thd->open_tables) + found_old_table|= close_thread_table(thd, &thd->open_tables); + thd->some_tables_deleted= 0; + + /* Free tables to hold down open files */ + while (open_cache.records > table_cache_size && unused_tables) + VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ + check_unused(); + if (found_old_table) + { + /* Tell threads waiting for refresh that something has happened */ + broadcast_refresh(); + } + + VOID(pthread_mutex_unlock(&LOCK_open)); +} + + /* Close all tables used by the current substatement, or all tables used by this thread if we are on the upper level. @@ -1098,26 +1157,19 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) SYNOPSIS close_thread_tables() thd Thread handler - lock_in_use Set to 1 (0 = default) if caller has a lock on - LOCK_open - skip_derived Set to 1 (0 = default) if we should not free derived - tables. - stopper When closing tables from thd->open_tables(->next)*, - don't close/remove tables starting from stopper. IMPLEMENTATION Unlocks tables and frees derived tables. Put all normal tables used by thread in free list. - When in prelocked mode it will only close/mark as free for reuse - tables opened by this substatement, it will also check if we are - closing tables after execution of complete query (i.e. we are on - upper level) and will leave prelocked mode if needed. + It will only close/mark as free for reuse tables opened by this + substatement, it will also check if we are closing tables after + execution of complete query (i.e. we are on upper level) and will + leave prelocked mode if needed. */ -void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) +void close_thread_tables(THD *thd) { - bool found_old_table; prelocked_mode_type prelocked_mode= thd->prelocked_mode; DBUG_ENTER("close_thread_tables"); @@ -1132,7 +1184,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) derived tables with (sub-)statement instead of thread and destroy them at the end of its execution. */ - if (thd->derived_tables && !skip_derived) + if (thd->derived_tables) { TABLE *table, *next; /* @@ -1147,13 +1199,10 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) thd->derived_tables= 0; } - if (prelocked_mode) - { - /* - Mark all temporary tables used by this substatement as free for reuse. - */ - mark_used_tables_as_free_for_reuse(thd, thd->temporary_tables); - } + /* + Mark all temporary tables used by this statement as free for reuse. + */ + mark_temp_tables_as_free_for_reuse(thd); if (thd->locked_tables || prelocked_mode) { @@ -1217,28 +1266,8 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) if (!thd->active_transaction()) thd->transaction.xid_state.xid.null(); - if (!lock_in_use) - VOID(pthread_mutex_lock(&LOCK_open)); - - DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); - - found_old_table= 0; - while (thd->open_tables) - found_old_table|= close_thread_table(thd, &thd->open_tables); - thd->some_tables_deleted=0; - - /* Free tables to hold down open files */ - while (open_cache.records > table_cache_size && unused_tables) - VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ - check_unused(); - if (found_old_table) - { - /* Tell threads waiting for refresh that something has happened */ - broadcast_refresh(); - } - if (!lock_in_use) - VOID(pthread_mutex_unlock(&LOCK_open)); - /* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */ + if (thd->open_tables) + close_open_tables(thd); if (prelocked_mode == PRELOCKED) { @@ -1675,6 +1704,7 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) Try to locate the table in the list of thd->temporary_tables. If the table is found: + - if the table is being used by some outer statement, fail. - if the table is in thd->locked_tables, unlock it and remove it from the list of locked tables. Currently only transactional temporary tables are present in the locked_tables list. @@ -1689,24 +1719,34 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) thd->temporary_tables list, it's impossible to tell here whether we're dealing with an internal or a user temporary table. - @retval TRUE the table was not found in the list of temporary tables - of this thread - @retval FALSE the table was found and dropped successfully. + @retval 0 the table was found and dropped successfully. + @retval 1 the table was not found in the list of temporary tables + of this thread + @retval -1 the table is in use by a outer query */ -bool close_temporary_table(THD *thd, TABLE_LIST *table_list) +int drop_temporary_table(THD *thd, TABLE_LIST *table_list) { TABLE *table; + DBUG_ENTER("drop_temporary_table"); if (!(table= find_temporary_table(thd, table_list))) - return 1; + DBUG_RETURN(1); + + /* Table might be in use by some outer statement. */ + if (table->query_id && table->query_id != thd->query_id) + { + my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); + DBUG_RETURN(-1); + } + /* If LOCK TABLES list is not empty and contains this table, unlock the table and remove the table from this list. */ mysql_lock_remove(thd, thd->locked_tables, table, FALSE); close_temporary_table(thd, table, 1, 1); - return 0; + DBUG_RETURN(0); } /* @@ -2285,8 +2325,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, is always represented by only one TABLE object in THD, and it can not be cloned. Emit an error for an unsupported behaviour. */ - if (table->query_id == thd->query_id || - thd->prelocked_mode && table->query_id) + if (table->query_id) { DBUG_PRINT("error", ("query_id: %lu server_id: %u pseudo_thread_id: %lu", @@ -2296,7 +2335,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, DBUG_RETURN(0); } table->query_id= thd->query_id; - table->clear_query_id= 1; thd->thread_specific_used= TRUE; DBUG_PRINT("info",("Using temporary table")); goto reset; @@ -4306,7 +4344,6 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables) sp_remove_not_own_routines(thd->lex); for (TABLE_LIST *tmp= *tables; tmp; tmp= tmp->next_global) tmp->table= 0; - mark_used_tables_as_free_for_reuse(thd, thd->temporary_tables); close_thread_tables(thd); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index ed7e30c1fef..19a99f9d12b 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -151,6 +151,14 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) } VOID(pthread_mutex_unlock(&LOCK_open)); } + else if (tables->table) + { + /* Must be a temporary table */ + TABLE *table= tables->table; + table->file->ha_index_or_rnd_end(); + table->query_id= thd->query_id; + table->open_by_handler= 0; + } } /* @@ -282,6 +290,12 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) goto err; } + /* + If it's a temp table, don't reset table->query_id as the table is + being used by this handler. Otherwise, no meaning at all. + */ + tables->table->open_by_handler= 1; + if (! reopen) send_ok(thd); DBUG_PRINT("exit",("OK")); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 077141c4d7a..d3010e4309b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3399,7 +3399,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, it preparable for open. But let us do close_temporary_table() here just in case. */ - close_temporary_table(thd, create_table); + drop_temporary_table(thd, create_table); } } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ea6a25d9866..7d04f564cf3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -992,9 +992,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Multiple queries exits, execute them individually */ - if (thd->lock || thd->open_tables || thd->derived_tables || - thd->prelocked_mode) - close_thread_tables(thd); + close_thread_tables(thd); ulong length= (ulong)(packet_end - next_packet); log_slow_statement(thd); @@ -1331,12 +1329,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); break; } - if (thd->lock || thd->open_tables || thd->derived_tables || - thd->prelocked_mode) - { - thd->proc_info="closing tables"; - close_thread_tables(thd); /* Free tables */ - } + + thd->proc_info= "closing tables"; + /* Free tables */ + close_thread_tables(thd); + /* assume handlers auto-commit (if some doesn't - transaction handling in MySQL should be redesigned to support it; it's a big change, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6edb8494b03..e10e89be478 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1503,7 +1503,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, char path[FN_REFLEN], *alias; uint path_length; String wrong_tables; - int error; + int error= 0; int non_temp_tables_count= 0; bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; String built_query; @@ -1563,10 +1563,27 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, enum legacy_db_type frm_db_type; mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, 1); - if (!close_temporary_table(thd, table)) - { - tmp_table_deleted=1; - continue; // removed temporary table + + error= drop_temporary_table(thd, table); + + switch (error) { + case 0: + // removed temporary table + tmp_table_deleted= 1; + continue; + case -1: + // table already in use + /* + XXX: This branch should never be taken outside of SF, trigger or + prelocked mode. + + DBUG_ASSERT(thd->in_sub_stmt); + */ + error= 1; + goto err_with_placeholders; + default: + // temporary table not found + error= 0; } /* @@ -1593,7 +1610,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, built_query.append("`,"); } - error=0; table_type= table->db_type; if (!drop_temporary) { diff --git a/sql/table.h b/sql/table.h index 6554b6ed578..2bbd71b70c6 100644 --- a/sql/table.h +++ b/sql/table.h @@ -499,6 +499,24 @@ struct st_table { my_bitmap_map *bitmap_init_value; MY_BITMAP def_read_set, def_write_set, tmp_set; /* containers */ MY_BITMAP *read_set, *write_set; /* Active column sets */ + /* + The ID of the query that opened and is using this table. Has different + meanings depending on the table type. + + Temporary tables: + + table->query_id is set to thd->query_id for the duration of a statement + and is reset to 0 once it is closed by the same statement. A non-zero + table->query_id means that a statement is using the table even if it's + not the current statement (table is in use by some outer statement). + + Non-temporary tables: + + Under pre-locked or LOCK TABLES mode: query_id is set to thd->query_id + for the duration of a statement and is reset to 0 once it is closed by + the same statement. A non-zero query_id is used to control which tables + in the list of pre-opened and locked tables are actually being used. + */ query_id_t query_id; /* @@ -593,8 +611,8 @@ struct st_table { my_bool locked_by_name; my_bool fulltext_searched; my_bool no_cache; - /* To signal that we should reset query_id for tables and cols */ - my_bool clear_query_id; + /* To signal that the table is associated with a HANDLER statement */ + my_bool open_by_handler; /* To indicate that a non-null value of the auto_increment field was provided by the user or retrieved from the current record. From 2ce9194411a665f8d6f65e52a808609a900cff80 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Fri, 2 Nov 2007 02:36:12 +0300 Subject: [PATCH 85/92] A fix for Bug#32030 "DELETE does not return an error and deletes rows if error evaluating WHERE" DELETE with a subquery in WHERE clause would sometimes ignore subquery evaluation error and proceed with deletion. The fix is to check for an error after evaluation of the WHERE clause in DELETE. Addressed review comments. --- mysql-test/r/group_min_max.result | 3 +-- mysql-test/r/ps.result | 20 +++++++++++++++++++ mysql-test/t/group_min_max.test | 1 + mysql-test/t/ps.test | 33 +++++++++++++++++++++++++++++++ sql/sql_delete.cc | 11 +++++++++-- 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index f62fd662a5d..270f248ea9c 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2299,8 +2299,7 @@ Handler_read_next 0 FLUSH STATUS; DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x FROM t1) > 10000; -Warnings: -Error 1242 Subquery returns more than 1 row +ERROR 21000: Subquery returns more than 1 row SHOW STATUS LIKE 'handler_read__e%'; Variable_name Value Handler_read_key 8 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index edac68a88d6..db9f0613d7f 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -2680,4 +2680,24 @@ t1 CREATE TABLE `t1` ( KEY `c` (`c`(10)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +drop table if exists t1, t2; +Warnings: +Note 1051 Unknown table 't1' +Note 1051 Unknown table 't2' +create table t1 (a int, b int); +create table t2 like t1; +insert into t1 (a, b) values (1,1), (1,2), (1,3), (1,4), (1,5), +(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6); +insert into t2 select a, max(b) from t1 group by a; +prepare stmt from "delete from t2 where (select (select max(b) from t1 group +by a having a < 2) x from t1) > 10000"; +delete from t2 where (select (select max(b) from t1 group +by a having a < 2) x from t1) > 10000; +ERROR 21000: Subquery returns more than 1 row +execute stmt; +ERROR 21000: Subquery returns more than 1 row +execute stmt; +ERROR 21000: Subquery returns more than 1 row +deallocate prepare stmt; +drop table t1, t2; End of 5.1 tests. diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index cf25b4c61be..9d1e065797d 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -890,6 +890,7 @@ FLUSH STATUS; DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000; SHOW STATUS LIKE 'handler_read__e%'; FLUSH STATUS; +--error ER_SUBQUERY_NO_1_ROW DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x FROM t1) > 10000; SHOW STATUS LIKE 'handler_read__e%'; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index dea86bdd2fa..c528fddaf93 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -2778,4 +2778,37 @@ execute stmt; show create table t1; drop table t1; +# +# Bug #32030 DELETE does not return an error and deletes rows if error +# evaluating WHERE +# +# Test that there is an error for prepared delete just like for the normal +# one. +# + +drop table if exists t1, t2; +create table t1 (a int, b int); +create table t2 like t1; + +insert into t1 (a, b) values (1,1), (1,2), (1,3), (1,4), (1,5), + (2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6); + +insert into t2 select a, max(b) from t1 group by a; + +prepare stmt from "delete from t2 where (select (select max(b) from t1 group +by a having a < 2) x from t1) > 10000"; + +--error ER_SUBQUERY_NO_1_ROW +delete from t2 where (select (select max(b) from t1 group +by a having a < 2) x from t1) > 10000; +--error ER_SUBQUERY_NO_1_ROW +execute stmt; +--error ER_SUBQUERY_NO_1_ROW +execute stmt; + +deallocate prepare stmt; +drop table t1, t2; + + + --echo End of 5.1 tests. diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 219dc90429b..f183cb3142f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -35,6 +35,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, READ_RECORD info; bool using_limit=limit != HA_POS_ERROR; bool transactional_table, safe_update, const_cond; + bool const_cond_result; ha_rows deleted= 0; uint usable_index= MAX_KEY; SELECT_LEX *select_lex= &thd->lex->select_lex; @@ -86,6 +87,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, select_lex->no_error= thd->lex->ignore; + const_cond_result= const_cond && (!conds || conds->val_int()); + if (thd->is_error()) + { + /* Error evaluating val_int(). */ + DBUG_RETURN(TRUE); + } /* Test if the user wants to delete all rows and deletion doesn't have any side-effects (because of triggers), so we can use optimized @@ -105,7 +112,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - We should not be binlogging this statement row-based, and - there should be no delete triggers associated with the table. */ - if (!using_limit && const_cond && (!conds || conds->val_int()) && + if (!using_limit && const_cond_result && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && (thd->lex->sql_command == SQLCOM_TRUNCATE || (!thd->current_stmt_binlog_row_based && @@ -300,7 +307,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, else table->file->unlock_row(); // Row failed selection, release lock on it } - if (thd->killed && !error) + if (thd->killed || thd->is_error()) error= 1; // Aborted if (will_batch && (loc_error= table->file->end_bulk_delete())) { From b9550052455de9ffa43f44c920d5b8e30979f70a Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.(none)" <> Date: Fri, 2 Nov 2007 14:47:18 +0300 Subject: [PATCH 86/92] Cleanup the test case for Bug#32030 "DELETE does not return an error and deletes rows if error evaluating WHERE" --- mysql-test/r/ps.result | 3 --- mysql-test/t/ps.test | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index db9f0613d7f..9d0906ad5e7 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -2681,9 +2681,6 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; drop table if exists t1, t2; -Warnings: -Note 1051 Unknown table 't1' -Note 1051 Unknown table 't2' create table t1 (a int, b int); create table t2 like t1; insert into t1 (a, b) values (1,1), (1,2), (1,3), (1,4), (1,5), diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c528fddaf93..fd7caeb195e 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -2785,8 +2785,9 @@ drop table t1; # Test that there is an error for prepared delete just like for the normal # one. # - +--disable_warnings drop table if exists t1, t2; +--enable_warnings create table t1 (a int, b int); create table t2 like t1; From c0138b94f0074f7632e0b3d619e6300900497a7a Mon Sep 17 00:00:00 2001 From: "mats@kindahl-laptop.dnsalias.net" <> Date: Sat, 3 Nov 2007 01:33:48 +0100 Subject: [PATCH 87/92] BUG#31611 (Security risk with BINLOG statement): Adding check that the user executing a BINLOG statement has SUPER privileges and aborting execution of the statement with an error otherwise. --- mysql-test/r/mysqlbinlog.result | 22 ++++++++++++++++++++++ mysql-test/t/mysqlbinlog.test | 27 +++++++++++++++++++++++++++ sql/sql_binlog.cc | 6 ++++++ 3 files changed, 55 insertions(+) diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index f10ae4b4df5..287fbd7e7f3 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -328,4 +328,26 @@ drop table t1; drop table t1; End of 5.0 tests flush logs; +BUG#31611: Security risk with BINLOG statement +SET BINLOG_FORMAT=ROW; +CREATE DATABASE mysqltest1; +CREATE USER untrusted@localhost; +GRANT SELECT ON mysqltest1.* TO untrusted@localhost; +SHOW GRANTS FOR untrusted@localhost; +Grants for untrusted@localhost +GRANT USAGE ON *.* TO 'untrusted'@'localhost' +GRANT SELECT ON `mysqltest1`.* TO 'untrusted'@'localhost' +USE mysqltest1; +CREATE TABLE t1 (a INT, b CHAR(64)); +flush logs; +INSERT INTO t1 VALUES (1,USER()); +flush logs; +mysqlbinlog var/log/master-bin.000017 > var/tmp/bug31611.sql +mysql mysqltest1 -uuntrusted < var/tmp/bug31611.sql +INSERT INTO t1 VALUES (1,USER()); +ERROR 42000: INSERT command denied to user 'untrusted'@'localhost' for table 't1' +SELECT * FROM t1; +a b +1 root@localhost +DROP DATABASE mysqltest1; End of 5.1 tests diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 25bd9a402ae..8635bbfab87 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -250,4 +250,31 @@ flush logs; --exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000016 >/dev/null 2>/dev/null --exec $MYSQL_BINLOG --force-if-open $MYSQLTEST_VARDIR/log/master-bin.000016 >/dev/null 2>/dev/null +--echo BUG#31611: Security risk with BINLOG statement + +SET BINLOG_FORMAT=ROW; +CREATE DATABASE mysqltest1; +CREATE USER untrusted@localhost; +GRANT SELECT ON mysqltest1.* TO untrusted@localhost; + +SHOW GRANTS FOR untrusted@localhost; +USE mysqltest1; +CREATE TABLE t1 (a INT, b CHAR(64)); +flush logs; +INSERT INTO t1 VALUES (1,USER()); +flush logs; +echo mysqlbinlog var/log/master-bin.000017 > var/tmp/bug31611.sql; +exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000017 > $MYSQLTEST_VARDIR/tmp/bug31611.sql; +connect (unsecure,localhost,untrusted,,mysqltest1); +echo mysql mysqltest1 -uuntrusted < var/tmp/bug31611.sql; +error 1; +exec $MYSQL mysqltest1 -uuntrusted < $MYSQLTEST_VARDIR/tmp/bug31611.sql; +connection unsecure; +error ER_TABLEACCESS_DENIED_ERROR; +INSERT INTO t1 VALUES (1,USER()); + +SELECT * FROM t1; +connection default; +DROP DATABASE mysqltest1; + --echo End of 5.1 tests diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 87224b8eea0..95eea9f20fa 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -37,6 +37,12 @@ void mysql_client_binlog_statement(THD* thd) thd->lex->comment.length : 2048), thd->lex->comment.str)); + if (check_global_access(thd, SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + DBUG_VOID_RETURN; + } + /* Temporarily turn off send_ok, since different events handle this differently From 8f6a0a4c3cb8da473ca755e2da58e1e9ce02c029 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Mon, 5 Nov 2007 13:19:56 +0200 Subject: [PATCH 88/92] Bug #31974: Wrong EXPLAIN output The fix for bug 31148 is not correct. It does not have a relation to the problem described in this bug. And removing the fix will not make the bug to re-appear. Fixed the bug #31974 by removing the fix for bug 31148 and adding a test case. --- mysql-test/r/key.result | 14 ++++++++++++++ mysql-test/t/key.test | 17 +++++++++++++++++ sql/sql_select.cc | 7 ------- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 6c115435fb6..3db5e926d30 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -545,3 +545,17 @@ c1 1 1 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT, INDEX (a,b)); +INSERT INTO t1 (a, b) +VALUES +(1,1), (1,2), (1,3), (1,4), (1,5), +(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6); +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE +(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by +SELECT 1 as RES FROM t1 AS t1_outer WHERE +(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; +RES +DROP TABLE t1; diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index cd6c480407d..31d5ac5201b 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -524,3 +524,20 @@ ORDER BY ( LIMIT 1); DROP TABLE t1; + + +# +# Bug #31974: Wrong EXPLAIN output +# + +CREATE TABLE t1 (a INT, b INT, INDEX (a,b)); +INSERT INTO t1 (a, b) + VALUES + (1,1), (1,2), (1,3), (1,4), (1,5), + (2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6); +EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE + (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; +SELECT 1 as RES FROM t1 AS t1_outer WHERE + (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; + +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 338b5f0cc3f..862948e48a4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6651,14 +6651,7 @@ void JOIN::cleanup(bool full) for (tab= join_tab, end= tab+tables; tab != end; tab++) { if (tab->table) - { - if (tab->table->key_read) - { - tab->table->key_read= 0; - tab->table->file->extra(HA_EXTRA_NO_KEYREAD); - } tab->table->file->ha_index_or_rnd_end(); - } } } } From 532ad32da59b5ca22c047731ab1996f4352188d3 Mon Sep 17 00:00:00 2001 From: "tomas@whalegate.ndb.mysql.com" <> Date: Mon, 5 Nov 2007 13:33:20 +0100 Subject: [PATCH 89/92] workaround for case insensitive filesystems --- mysql-test/suite/ndb/r/ndb_multi.result | 4 ++-- mysql-test/suite/ndb/t/ndb_multi.test | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/ndb/r/ndb_multi.result b/mysql-test/suite/ndb/r/ndb_multi.result index 98c4265b833..17380b10fd7 100644 --- a/mysql-test/suite/ndb/r/ndb_multi.result +++ b/mysql-test/suite/ndb/r/ndb_multi.result @@ -132,11 +132,11 @@ master_epoch, count)) engine ndb; show tables like '%$%'; Tables_in_test (%$%) -t1$EX +t1$ex use test; show tables like '%$%'; Tables_in_test (%$%) -t1$EX +t1$ex drop table `test`.`t1$EX`; show tables like '%$%'; Tables_in_test (%$%) diff --git a/mysql-test/suite/ndb/t/ndb_multi.test b/mysql-test/suite/ndb/t/ndb_multi.test index ce7e22b3b7f..c2217b51d08 100644 --- a/mysql-test/suite/ndb/t/ndb_multi.test +++ b/mysql-test/suite/ndb/t/ndb_multi.test @@ -139,9 +139,11 @@ create table `test`.`t1$EX` # check that table shows up ok on both servers # before bugfix table would not show up on server2 +--replace_regex /EX/ex/ show tables like '%$%'; connection server2; use test; +--replace_regex /EX/ex/ show tables like '%$%'; # check cleanup From 31787d3d56880b8df5a4e432ff08f5dcf41830c6 Mon Sep 17 00:00:00 2001 From: "mats@kindahl-laptop.dnsalias.net" <> Date: Mon, 5 Nov 2007 14:24:20 +0100 Subject: [PATCH 90/92] BUG#31611 (Security risk with BINLOG statement): Incremental patch to remove redundant, but benign, my_error() call. --- sql/sql_binlog.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 95eea9f20fa..ee78c244fe4 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -38,10 +38,7 @@ void mysql_client_binlog_statement(THD* thd) thd->lex->comment.str)); if (check_global_access(thd, SUPER_ACL)) - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); DBUG_VOID_RETURN; - } /* Temporarily turn off send_ok, since different events handle this From 36e0b66638127a95545945fa612d83d844e9d9e5 Mon Sep 17 00:00:00 2001 From: "malff@lambda.hsd1.co.comcast.net." <> Date: Mon, 5 Nov 2007 16:52:04 -0700 Subject: [PATCH 91/92] fixed coding style --- sql/sql_yacc.yy | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 69cd7060778..b337f82dec3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9784,9 +9784,10 @@ literal: MYSQL_YYABORT; } } - | DATE_SYM text_literal { $$ = $2; } - | TIME_SYM text_literal { $$ = $2; } - | TIMESTAMP text_literal { $$ = $2; }; + | DATE_SYM text_literal { $$ = $2; } + | TIME_SYM text_literal { $$ = $2; } + | TIMESTAMP text_literal { $$ = $2; } + ; NUM_literal: NUM From b028dad9ce805042401c484c24c65516c0972588 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Tue, 6 Nov 2007 15:29:55 +0200 Subject: [PATCH 92/92] Bug #31974: additional commit (test case updates) loose index scan enabled for subqueries --- mysql-test/r/group_min_max.result | 4 ++-- mysql-test/r/index_merge_myisam.result | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 270f248ea9c..a3744b36e87 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2251,7 +2251,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -2 SUBQUERY t1 range NULL a 5 NULL 8 +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2); id select_type table type possible_keys key key_len ref rows Extra @@ -2268,7 +2268,7 @@ AND t1_outer1.b = t1_outer2.b; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index 1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer -2 SUBQUERY t1 range NULL a 5 NULL 8 +2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result index ebeba53fdfa..9d7d06f7f1b 100644 --- a/mysql-test/r/index_merge_myisam.result +++ b/mysql-test/r/index_merge_myisam.result @@ -286,7 +286,7 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 -2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where +2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where; Using index create table t3 like t0; insert into t3 select * from t0; alter table t3 add key9 int not null, add index i9(key9);