From 87460ec76a30a8070f8cebbdf6c93be208e3f969 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 29 Jun 2006 20:55:21 +0200 Subject: [PATCH 1/4] Bug #19202 Incorrect errorhandling in select count(*) wrt temporary error --- sql/ha_ndbcluster.cc | 89 ++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index ffd5932a5c1..11fdd33fad9 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -270,6 +270,7 @@ void ha_ndbcluster::records_update() { Ndb *ndb= get_ndb(); Uint64 rows; + ndb->setDatabaseName(m_dbname); if(ndb_get_table_statistics(ndb, m_tabname, &rows, 0) == 0){ info->records= rows; } @@ -2876,6 +2877,7 @@ void ha_ndbcluster::info(uint flag) DBUG_VOID_RETURN; Ndb *ndb= get_ndb(); Uint64 rows= 100; + ndb->setDatabaseName(m_dbname); if (current_thd->variables.ndb_use_exact_count) ndb_get_table_statistics(ndb, m_tabname, &rows, 0); records= rows; @@ -5228,34 +5230,53 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, { DBUG_ENTER("ndb_get_table_statistics"); DBUG_PRINT("enter", ("table: %s", table)); - NdbConnection* pTrans= ndb->startTransaction(); - do + NdbConnection* pTrans; + NdbError error; + int retries= 10; + int retry_sleep= 30 * 1000; /* 30 milliseconds */ + + do { - if (pTrans == NULL) - break; - - NdbScanOperation* pOp= pTrans->getNdbScanOperation(table); - if (pOp == NULL) - break; - - NdbResultSet* rs= pOp->readTuples(NdbOperation::LM_CommittedRead); - if (rs == 0) - break; - - int check= pOp->interpret_exit_last_row(); - if (check == -1) - break; - Uint64 rows, commits; + Uint64 sum_rows= 0; + Uint64 sum_commits= 0; + NdbScanOperation*pOp; + NdbResultSet *rs; + int check; + + if ((pTrans= ndb->startTransaction()) == NULL) + { + error= ndb->getNdbError(); + goto retry; + } + + if ((pOp= pTrans->getNdbScanOperation(table)) == NULL) + { + error= pTrans->getNdbError(); + goto retry; + } + + if ((rs= pOp->readTuples(NdbOperation::LM_CommittedRead)) == 0) + { + error= pOp->getNdbError(); + goto retry; + } + + if (pOp->interpret_exit_last_row() == -1) + { + error= pOp->getNdbError(); + goto retry; + } + pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows); pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits); - check= pTrans->execute(NoCommit, AbortOnError, TRUE); - if (check == -1) - break; + if (pTrans->execute(NoCommit, AbortOnError, TRUE) == -1) + { + error= pTrans->getNdbError(); + goto retry; + } - Uint64 sum_rows= 0; - Uint64 sum_commits= 0; while((check= rs->nextResult(TRUE, TRUE)) == 0) { sum_rows+= rows; @@ -5263,7 +5284,10 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, } if (check == -1) - break; + { + error= pOp->getNdbError(); + goto retry; + } rs->close(TRUE); @@ -5274,11 +5298,22 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, * commit_count= sum_commits; DBUG_PRINT("exit", ("records: %u commits: %u", sum_rows, sum_commits)); DBUG_RETURN(0); - } while(0); - ndb->closeTransaction(pTrans); - DBUG_PRINT("exit", ("failed")); - DBUG_RETURN(-1); +retry: + if (pTrans) + { + ndb->closeTransaction(pTrans); + pTrans= NULL; + } + if (error.status == NdbError::TemporaryError && retries--) + { + my_sleep(retry_sleep); + continue; + } + break; + } while(1); + DBUG_PRINT("exit", ("failed, error %u(%s)", error.code, error.message)); + ERR_RETURN(error); } /* From 5d67b0520306f9bca7ecc1eb9d9c35497354cc1b Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 29 Jun 2006 22:11:29 +0200 Subject: [PATCH 2/4] corrected merge error --- sql/ha_ndbcluster.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 7f433f06cf9..e4ff39797ca 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5846,8 +5846,11 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, { Uint64 rows, commits, mem; Uint32 size; + Uint32 count= 0; Uint64 sum_rows= 0; Uint64 sum_commits= 0; + Uint64 sum_row_size= 0; + Uint64 sum_mem= 0; NdbScanOperation*pOp; NdbResultSet *rs; int check; From 9f542ef0f4f79d0814cbe4668c6cca3c0f4ad649 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Fri, 30 Jun 2006 16:25:07 +0200 Subject: [PATCH 3/4] adopted ndb handler code for tables without primary key and with unique index - added missing retrieval of hidden primary key --- sql/ha_ndbcluster.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 11fdd33fad9..e442d5991fa 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1364,6 +1364,12 @@ int ha_ndbcluster::unique_index_read(const byte *key, m_value[i].ptr= NULL; } } + if (table->primary_key == MAX_KEY) + { + DBUG_PRINT("info", ("Getting hidden key")); + if (get_ndb_value(op, NULL, i, NULL)) + ERR_RETURN(op->getNdbError()); + } if (execute_no_commit_ie(this,trans) != 0) { From 98874725e073dfed67e4e372ad33d64c60db4901 Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Tue, 4 Jul 2006 11:43:06 +0200 Subject: [PATCH 4/4] Bug #20784 Uninitialized memory in update on table with PK not on first column - partial backport of code from 5.1, do cot compare_record for engines that do not read all columns during update --- sql/ha_ndbcluster.cc | 3 ++- sql/handler.h | 1 + sql/sql_update.cc | 25 ++++++++++++++++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index e4ff39797ca..280b23fc73f 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4575,7 +4575,8 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg): HA_NO_PREFIX_CHAR_KEYS | HA_NEED_READ_RANGE_BUFFER | HA_CAN_GEOMETRY | - HA_CAN_BIT_FIELD), + HA_CAN_BIT_FIELD | + HA_PARTIAL_COLUMN_READ), m_share(0), m_use_write(FALSE), m_ignore_dup_key(FALSE), diff --git a/sql/handler.h b/sql/handler.h index 31aac075a5e..aada647e071 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -57,6 +57,7 @@ see mi_rsame/heap_rsame/myrg_rsame */ #define HA_READ_RND_SAME (1 << 0) +#define HA_PARTIAL_COLUMN_READ (1 << 1) /* read may not return all columns */ #define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */ #define HA_REC_NOT_IN_SEQ (1 << 3) /* ha_info don't return recnumber; It returns a position to ha_r_rnd */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c2b7624c9e7..5237b3a1c05 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -120,6 +120,7 @@ int mysql_update(THD *thd, bool using_limit= limit != HA_POS_ERROR; bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table; + bool can_compare_record; int res; int error; uint used_index= MAX_KEY; @@ -433,6 +434,13 @@ int mysql_update(THD *thd, (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); + /* + We can use compare_record() to optimize away updates if + the table handler is returning all columns + */ + can_compare_record= !(table->file->table_flags() & + HA_PARTIAL_COLUMN_READ); + while (!(error=info.read_record(&info)) && !thd->killed) { if (!(select && select->skip_record())) @@ -445,7 +453,7 @@ int mysql_update(THD *thd, found++; - if (compare_record(table, query_id)) + if (!can_compare_record || compare_record(table, query_id)) { if ((res= table_list->view_check_option(thd, ignore)) != VIEW_CHECK_OK) @@ -1248,8 +1256,15 @@ bool multi_update::send_data(List ¬_used_values) uint offset= cur_table->shared; table->file->position(table->record[0]); + /* + We can use compare_record() to optimize away updates if + the table handler is returning all columns + */ if (table == table_to_update) { + bool can_compare_record; + can_compare_record= !(table->file->table_flags() & + HA_PARTIAL_COLUMN_READ); table->status|= STATUS_UPDATED; store_record(table,record[1]); if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset], @@ -1259,7 +1274,7 @@ bool multi_update::send_data(List ¬_used_values) DBUG_RETURN(1); found++; - if (compare_record(table, thd->query_id)) + if (!can_compare_record || compare_record(table, thd->query_id)) { int error; if ((error= cur_table->view_check_option(thd, ignore)) != @@ -1376,6 +1391,7 @@ int multi_update::do_updates(bool from_send_error) for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) { byte *ref_pos; + bool can_compare_record; table = cur_table->table; if (table == table_to_update) @@ -1402,6 +1418,9 @@ int multi_update::do_updates(bool from_send_error) if ((local_error = tmp_table->file->ha_rnd_init(1))) goto err; + can_compare_record= !(table->file->table_flags() & + HA_PARTIAL_COLUMN_READ); + ref_pos= (byte*) tmp_table->field[0]->ptr; for (;;) { @@ -1431,7 +1450,7 @@ int multi_update::do_updates(bool from_send_error) TRG_ACTION_BEFORE, TRUE)) goto err2; - if (compare_record(table, thd->query_id)) + if (!can_compare_record || compare_record(table, thd->query_id)) { if ((local_error=table->file->update_row(table->record[1], table->record[0])))