From 18fb82c1790fe50279fc25d83adac5f09162229a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 Feb 2006 19:11:11 +0100 Subject: [PATCH] ndb - rbr blobs works now (or again) mysql-test/t/disabled.def: ndb_blob.test works again, sort of storage/ndb/include/ndbapi/NdbBlob.hpp: better getNull & replace+tinyblob forward-patch from 5.0 storage/ndb/src/ndbapi/NdbBlob.cpp: better getNull & replace+tinyblob forward-patch from 5.0 storage/ndb/test/ndbapi/test_event.cpp: getEvent()->getTable() sql/ha_ndbcluster.cc: return more error codes from blob calls sql/ha_ndbcluster_binlog.cc: return more error codes from blob calls storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp: return more error codes from blob calls storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp: copy and invalidate blob tables as part of main table. TODO: do not cache blob tables storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp: copy and invalidate blob tables as part of main table. TODO: do not cache blob tables --- mysql-test/r/rpl_ndb_blob.result | 126 ++++++++++++++++++ mysql-test/t/disabled.def | 1 - mysql-test/t/rpl_ndb_blob.test | 93 +++++++++++++ sql/ha_ndbcluster.cc | 84 ++++++------ sql/ha_ndbcluster_binlog.cc | 14 ++ storage/ndb/include/ndbapi/NdbBlob.hpp | 28 ++-- storage/ndb/src/ndbapi/NdbBlob.cpp | 39 +++++- storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp | 24 +++- storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp | 2 +- .../ndb/src/ndbapi/NdbEventOperationImpl.cpp | 12 +- storage/ndb/test/ndbapi/test_event.cpp | 2 +- 11 files changed, 358 insertions(+), 67 deletions(-) create mode 100644 mysql-test/r/rpl_ndb_blob.result create mode 100644 mysql-test/t/rpl_ndb_blob.test diff --git a/mysql-test/r/rpl_ndb_blob.result b/mysql-test/r/rpl_ndb_blob.result new file mode 100644 index 00000000000..031b489f7da --- /dev/null +++ b/mysql-test/r/rpl_ndb_blob.result @@ -0,0 +1,126 @@ +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; +create table t1 ( +a int not null primary key, +b text not null +) engine=ndb; +insert into t1 values(1, repeat('abc',10)); +insert into t1 values(2, repeat('def',200)); +insert into t1 values(3, repeat('ghi',3000)); +select 'M', a, sha1(b) from t1 +order by a; +M a sha1(b) +M 1 8a6c4cf7cf97e66c487c3e3b717e9ae13623d07d +M 2 0ccd08c0fa6ad6a4382b27b1d36586d6ceb4fffa +M 3 75e7b3299e0b776aeac2a4d1542d5b3c0ba2e05e +select 'S', a, sha1(b) from t1 +order by a; +S a sha1(b) +S 1 8a6c4cf7cf97e66c487c3e3b717e9ae13623d07d +S 2 0ccd08c0fa6ad6a4382b27b1d36586d6ceb4fffa +S 3 75e7b3299e0b776aeac2a4d1542d5b3c0ba2e05e +drop table t1; +create table t1 ( +a int not null primary key, +b text not null, +c int, +d longblob, +e tinyblob +) engine=ndbcluster; +insert into t1 values ( +0, repeat(@s2,454), 100, repeat(@s2,345), NULL); +insert into t1 values ( +1, repeat(@s0,504), NULL, repeat(@s1,732), repeat(@s1,1)); +insert into t1 values ( +2, '', 102, '', repeat(@s2,1)); +insert into t1 values ( +3, repeat(@s0,545), 103, repeat(@s2,788), repeat(@s0,1)); +insert into t1 values ( +4, repeat(@s1,38), 104, repeat(@s0,260), repeat(@s0,1)); +insert into t1 values ( +5, repeat(@s2,12), 105, repeat(@s2,40), repeat(@s1,1)); +insert into t1 values ( +6, repeat(@s1,242), 106, NULL, repeat(@s1,1)); +insert into t1 values ( +7, repeat(@s1,30), 107, repeat(@s0,161), ''); +insert into t1 values ( +8, repeat(@s1,719), 108, repeat(@s2,104), NULL); +insert into t1 values ( +9, repeat(@s2,427), NULL, NULL, NULL); +select 'M', a, sha1(b), c, sha1(d), sha1(e) +from t1 order by a; +M a sha1(b) c sha1(d) sha1(e) +M 0 9538f61e649383c0d1054de2a2f0171188129f33 100 2b6515f29c20b8e9e17cc597527e516c0de8d612 NULL +M 1 dcb9a12ca86e718ff2564be041b7c1b3ff5ea559 NULL f23e7439d9a73c3954979b85a7ef6ef35faf4e9d abfe8ae5212b22d023aa6de84beeb1344ac5668a +M 2 da39a3ee5e6b4b0d3255bfef95601890afd80709 102 da39a3ee5e6b4b0d3255bfef95601890afd80709 33deebe47470a40e960834bffa4cdc66790845a6 +M 3 ec8e06d9ac4695d6a898b519ba840590263a9bff 103 278629ad080c3c4377978c006c2e54d0992e43cc 700915801f853603510aeb67b331866d996fdbda +M 4 0392fa8c425d293c79291f0f34779d1101d13fcb 104 5084b602c7203e0e9590a163415ac605da17ac32 700915801f853603510aeb67b331866d996fdbda +M 5 0f9653f0c7a69cd1c617792d546582e974a7a24d 105 566588a04ff26d05160d61c83435292bfda2978e abfe8ae5212b22d023aa6de84beeb1344ac5668a +M 6 a37e8b0ff4fc13a42be02cdecb36186436959bae 106 NULL abfe8ae5212b22d023aa6de84beeb1344ac5668a +M 7 a6bae0cfe6b45ff8c3c12d2ce577a1cd3931190f 107 39ee712b4b9e47f2cf3ba7c9790b2bf0d8f378e8 da39a3ee5e6b4b0d3255bfef95601890afd80709 +M 8 e139adcb7b2974ee7ff227fd405709e5cb7c896c 108 ba8073b0e1a281d4111bd2d82c7722b01574c00b NULL +M 9 1fc5168fe4be566b17b658d94e7813f0b5032cdb NULL NULL NULL +select 'S', a, sha1(b), c, sha1(d), sha1(e) +from t1 order by a; +S a sha1(b) c sha1(d) sha1(e) +S 0 9538f61e649383c0d1054de2a2f0171188129f33 100 2b6515f29c20b8e9e17cc597527e516c0de8d612 NULL +S 1 dcb9a12ca86e718ff2564be041b7c1b3ff5ea559 NULL f23e7439d9a73c3954979b85a7ef6ef35faf4e9d abfe8ae5212b22d023aa6de84beeb1344ac5668a +S 2 da39a3ee5e6b4b0d3255bfef95601890afd80709 102 da39a3ee5e6b4b0d3255bfef95601890afd80709 33deebe47470a40e960834bffa4cdc66790845a6 +S 3 ec8e06d9ac4695d6a898b519ba840590263a9bff 103 278629ad080c3c4377978c006c2e54d0992e43cc 700915801f853603510aeb67b331866d996fdbda +S 4 0392fa8c425d293c79291f0f34779d1101d13fcb 104 5084b602c7203e0e9590a163415ac605da17ac32 700915801f853603510aeb67b331866d996fdbda +S 5 0f9653f0c7a69cd1c617792d546582e974a7a24d 105 566588a04ff26d05160d61c83435292bfda2978e abfe8ae5212b22d023aa6de84beeb1344ac5668a +S 6 a37e8b0ff4fc13a42be02cdecb36186436959bae 106 NULL abfe8ae5212b22d023aa6de84beeb1344ac5668a +S 7 a6bae0cfe6b45ff8c3c12d2ce577a1cd3931190f 107 39ee712b4b9e47f2cf3ba7c9790b2bf0d8f378e8 da39a3ee5e6b4b0d3255bfef95601890afd80709 +S 8 e139adcb7b2974ee7ff227fd405709e5cb7c896c 108 ba8073b0e1a281d4111bd2d82c7722b01574c00b NULL +S 9 1fc5168fe4be566b17b658d94e7813f0b5032cdb NULL NULL NULL +drop table t1; +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 239 use `test`; create table t1 ( +a int not null primary key, +b text not null +) engine=ndb +master-bin.000001 239 Query 1 303 BEGIN +master-bin.000001 303 Table_map 1 65 cluster_replication.apply_status +master-bin.000001 368 Write_rows 1 107 +master-bin.000001 410 Table_map 1 147 test.t1 +master-bin.000001 450 Write_rows 1 818 +master-bin.000001 1121 Write_rows 1 9853 +master-bin.000001 10156 Query 1 10221 COMMIT +master-bin.000001 10221 Query 1 10285 BEGIN +master-bin.000001 10285 Table_map 1 65 cluster_replication.apply_status +master-bin.000001 10350 Write_rows 1 107 +master-bin.000001 10392 Query 1 10457 COMMIT +master-bin.000001 10457 Query 1 10533 use `test`; drop table t1 +master-bin.000001 10533 Query 1 10708 use `test`; create table t1 ( +a int not null primary key, +b text not null, +c int, +d longblob, +e tinyblob +) engine=ndbcluster +master-bin.000001 10708 Query 1 10772 BEGIN +master-bin.000001 10772 Table_map 1 65 cluster_replication.apply_status +master-bin.000001 10837 Write_rows 1 107 +master-bin.000001 10879 Table_map 1 150 test.t1 +master-bin.000001 10922 Write_rows 1 48934 +master-bin.000001 59706 Write_rows 1 124436 +master-bin.000001 135208 Write_rows 1 124542 +master-bin.000001 135314 Write_rows 1 205961 +master-bin.000001 216733 Write_rows 1 224245 +master-bin.000001 235017 Write_rows 1 227523 +master-bin.000001 238295 Write_rows 1 242391 +master-bin.000001 253163 Write_rows 1 254087 +master-bin.000001 264859 Write_rows 1 304335 +master-bin.000001 315107 Write_rows 1 330427 +master-bin.000001 341199 Query 1 341264 COMMIT +master-bin.000001 341264 Query 1 341328 BEGIN +master-bin.000001 341328 Table_map 1 65 cluster_replication.apply_status +master-bin.000001 341393 Write_rows 1 107 +master-bin.000001 341435 Query 1 341500 COMMIT +master-bin.000001 341500 Query 1 341576 use `test`; drop table t1 diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index dbb66e8e5cc..fd49bc21ae7 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -28,7 +28,6 @@ rpl_sp : Bug #16456 #ndb_dd_disk2memory : Bug #16466 ndb_autodiscover : Needs to be fixed w.r.t binlog ndb_autodiscover2 : Needs to be fixed w.r.t binlog -ndb_blob : BLOB replication causes core in master1 (Pekka will fix) #ndb_alter_table_row : sometimes wrong error 1015!=1046 ndb_gis : garbled msgs from corrupt THD* ndb_binlog_ddl_multi : Bug #17038 diff --git a/mysql-test/t/rpl_ndb_blob.test b/mysql-test/t/rpl_ndb_blob.test new file mode 100644 index 00000000000..c31b629b9f8 --- /dev/null +++ b/mysql-test/t/rpl_ndb_blob.test @@ -0,0 +1,93 @@ +--source include/have_ndb.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# +# basic test of blob replication for NDB +# + +# easy test + +--connection master +create table t1 ( + a int not null primary key, + b text not null +) engine=ndb; + +insert into t1 values(1, repeat('abc',10)); +insert into t1 values(2, repeat('def',200)); +insert into t1 values(3, repeat('ghi',3000)); + +select 'M', a, sha1(b) from t1 +order by a; + +--sync_slave_with_master +--sleep 5 +--connection slave +select 'S', a, sha1(b) from t1 +order by a; + +--connection master +drop table t1; +--sync_slave_with_master + +# hard test + +--connection master +create table t1 ( + a int not null primary key, + b text not null, + c int, + d longblob, + e tinyblob +) engine=ndbcluster; + +--disable_query_log +# length 61 +set @s0 = 'rggurloniukyehuxdbfkkyzlceixzrehqhvxvxbpwizzvjzpucqmzrhzxzfau'; +set @s1 = 'ykyymbzqgqlcjhlhmyqelfoaaohvtbekvifukdtnvcrrjveevfakxarxexomz'; +set @s2 = 'dbnfqyzgtqxalcrwtfsqabknvtfcbpoonxsjiqvmhnfikxxhcgoexlkoezvah'; +--enable_query_log + +insert into t1 values ( + 0, repeat(@s2,454), 100, repeat(@s2,345), NULL); +insert into t1 values ( + 1, repeat(@s0,504), NULL, repeat(@s1,732), repeat(@s1,1)); +insert into t1 values ( + 2, '', 102, '', repeat(@s2,1)); +insert into t1 values ( + 3, repeat(@s0,545), 103, repeat(@s2,788), repeat(@s0,1)); +insert into t1 values ( + 4, repeat(@s1,38), 104, repeat(@s0,260), repeat(@s0,1)); +insert into t1 values ( + 5, repeat(@s2,12), 105, repeat(@s2,40), repeat(@s1,1)); +insert into t1 values ( + 6, repeat(@s1,242), 106, NULL, repeat(@s1,1)); +insert into t1 values ( + 7, repeat(@s1,30), 107, repeat(@s0,161), ''); +insert into t1 values ( + 8, repeat(@s1,719), 108, repeat(@s2,104), NULL); +insert into t1 values ( + 9, repeat(@s2,427), NULL, NULL, NULL); + +select 'M', a, sha1(b), c, sha1(d), sha1(e) +from t1 order by a; + +--sync_slave_with_master +--sleep 5 +--connection slave +select 'S', a, sha1(b), c, sha1(d), sha1(e) +from t1 order by a; + +--connection master +drop table t1; +--sync_slave_with_master + +# +# view the binlog +# + +--connection master +let $VERSION=`select version()`; +--replace_result $VERSION VERSION +show binlog events; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 4451577dd06..ca2def31e99 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -840,51 +840,51 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, { Field *field= table->field[i]; NdbValue value= value_array[i]; - if (value.ptr != NULL && (field->flags & BLOB_FLAG)) + if (! (field->flags & BLOB_FLAG)) + continue; + if (value.blob == NULL) { - Field_blob *field_blob= (Field_blob *)field; - NdbBlob *ndb_blob= value.blob; - int isNull; - ndb_blob->getDefined(isNull); - if (isNull == 0) { // XXX -1 should be allowed only for events - Uint64 blob_len= 0; - if (ndb_blob->getLength(blob_len) != 0) - DBUG_RETURN(-1); - // Align to Uint64 - uint32 blob_size= blob_len; - if (blob_size % 8 != 0) - blob_size+= 8 - blob_size % 8; - if (loop == 1) - { - char *buf= buffer + offset; - uint32 len= 0xffffffff; // Max uint32 - DBUG_PRINT("info", ("read blob ptr=%p len=%u", - buf, (uint) blob_len)); - if (ndb_blob->readData(buf, len) != 0) - DBUG_RETURN(-1); - DBUG_PRINT("info", ("blob field %d offset=%u len=%u [ptrdiff=%d]", - i, offset, len, (int)ptrdiff)); - DBUG_ASSERT(len == blob_len); - // Ugly hack assumes only ptr needs to be changed - field_blob->ptr+= ptrdiff; - field_blob->set_ptr(len, buf); - field_blob->ptr-= ptrdiff; - } - offset+= blob_size; - } - else + DBUG_PRINT("info",("[%u] skipped", i)); + continue; + } + Field_blob *field_blob= (Field_blob *)field; + NdbBlob *ndb_blob= value.blob; + int isNull; + if (ndb_blob->getNull(isNull) != 0) + ERR_RETURN(ndb_blob->getNdbError()); + if (isNull == 0) { + Uint64 len64= 0; + if (ndb_blob->getLength(len64) != 0) + ERR_RETURN(ndb_blob->getNdbError()); + // Align to Uint64 + uint32 size= len64; + if (size % 8 != 0) + size+= 8 - size % 8; + if (loop == 1) { - if (loop == 1) - { - // have to set length even in this case - char *buf= buffer + offset; - uint32 len= 0; - field_blob->ptr+= ptrdiff; - field_blob->set_ptr(len, buf); - field_blob->ptr-= ptrdiff; - DBUG_PRINT("info", ("blob field %d isNull=%d", i, isNull)); - } + char *buf= buffer + offset; + uint32 len= 0xffffffff; // Max uint32 + if (ndb_blob->readData(buf, len) != 0) + ERR_RETURN(ndb_blob->getNdbError()); + DBUG_PRINT("info", ("[%u] offset=%u buf=%p len=%u [ptrdiff=%d]", + i, offset, buf, len, (int)ptrdiff)); + DBUG_ASSERT(len == len64); + // Ugly hack assumes only ptr needs to be changed + field_blob->ptr+= ptrdiff; + field_blob->set_ptr(len, buf); + field_blob->ptr-= ptrdiff; } + offset+= size; + } + else if (loop == 1) // undefined or null + { + // have to set length even in this case + char *buf= buffer + offset; // or maybe NULL + uint32 len= 0; + field_blob->ptr+= ptrdiff; + field_blob->set_ptr(len, buf); + field_blob->ptr-= ptrdiff; + DBUG_PRINT("info", ("[%u] isNull=%d", i, isNull)); } } if (loop == 0 && offset > buffer_size) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 5ce5fa79d89..b772ace24ea 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -2084,6 +2084,20 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, DBUG_PRINT("info", ("%s blob", col_name)); attr0.blob= op->getBlobHandle(col_name); attr1.blob= op->getPreBlobHandle(col_name); + if (attr0.blob == NULL || attr1.blob == NULL) + { + sql_print_error("NDB Binlog: Creating NdbEventOperation" + " blob field %u handles failed (code=%d) for %s", + j, op->getNdbError().code, event_name); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_GET_ERRMSG, ER(ER_GET_ERRMSG), + op->getNdbError().code, + op->getNdbError().message, + "NDB"); + ndb->dropEventOperation(op); + pthread_mutex_unlock(&injector_mutex); + DBUG_RETURN(-1); + } } } else diff --git a/storage/ndb/include/ndbapi/NdbBlob.hpp b/storage/ndb/include/ndbapi/NdbBlob.hpp index 5d6022862b8..92265b4feef 100644 --- a/storage/ndb/include/ndbapi/NdbBlob.hpp +++ b/storage/ndb/include/ndbapi/NdbBlob.hpp @@ -76,8 +76,8 @@ class NdbEventOperationImpl; * handle can be read after next event on main table has been retrieved. * The data is available immediately. See NdbEventOperation. * - * NdbBlob methods return -1 on error and 0 on success, and use output - * parameters when necessary. + * Non-void NdbBlob methods return -1 on error and 0 on success. Output + * parameters are used when necessary. * * Operation types: * - insertTuple must use setValue if blob column is non-nullable @@ -116,6 +116,11 @@ public: * Get the state of a NdbBlob object. */ State getState(); + /** + * Returns -1 for normal statement based blob and 0/1 for event + * operation post/pre data blob. Always succeeds. + */ + void getVersion(int& version); /** * Inline blob header. */ @@ -150,16 +155,15 @@ public: * then the callback is invoked. */ int setActiveHook(ActiveHook* activeHook, void* arg); - /** - * Check if blob value is defined (NULL or not). Used as first call - * on event based blob. The argument is set to -1 for not defined. - * Unlike getNull() this does not cause error on the handle. - */ +#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED int getDefined(int& isNull); - /** - * Check if blob is null. - */ int getNull(bool& isNull); +#endif + /** + * Return -1, 0, 1 if blob is undefined, non-null, or null. For + * non-event blob, undefined causes a state error. + */ + int getNull(int& isNull); /** * Set blob to NULL. */ @@ -208,8 +212,8 @@ public: */ static int getBlobEventName(char* bename, Ndb* anNdb, const char* eventName, const char* columnName); /** - * Return error object. The error may be blob specific (below) or may - * be copied from a failed implicit operation. + * Return error object. The error may be blob specific or may be + * copied from a failed implicit operation. */ const NdbError& getNdbError() const; /** diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp index 349ec6f4a7b..695781bddb9 100644 --- a/storage/ndb/src/ndbapi/NdbBlob.cpp +++ b/storage/ndb/src/ndbapi/NdbBlob.cpp @@ -31,7 +31,21 @@ */ static const bool g_ndb_blob_ok_to_read_index_table = false; -// state (inline) +// get state + +NdbBlob::State +NdbBlob::getState() +{ + return theState; +} + +void +NdbBlob::getVersion(int& version) +{ + version = theEventBlobVersion; +} + +// set state (inline) inline void NdbBlob::setState(State newState) @@ -608,7 +622,7 @@ NdbBlob::setActiveHook(ActiveHook activeHook, void* arg) // misc operations int -NdbBlob::getDefined(int& isNull) +NdbBlob::getDefined(int& isNull) // deprecated { DBUG_ENTER("NdbBlob::getDefined"); if (theState == Prepared && theSetFlag) { @@ -620,7 +634,7 @@ NdbBlob::getDefined(int& isNull) } int -NdbBlob::getNull(bool& isNull) +NdbBlob::getNull(bool& isNull) // deprecated { DBUG_ENTER("NdbBlob::getNull"); if (theState == Prepared && theSetFlag) { @@ -635,6 +649,23 @@ NdbBlob::getNull(bool& isNull) DBUG_RETURN(0); } +int +NdbBlob::getNull(int& isNull) +{ + DBUG_ENTER("NdbBlob::getNull"); + if (theState == Prepared && theSetFlag) { + isNull = (theSetBuf == NULL); + DBUG_RETURN(0); + } + isNull = theNullFlag; + if (isNull == -1 && theEventBlobVersion == -1) { + setErrorCode(NdbBlobImpl::ErrState); + DBUG_RETURN(-1); + } + DBUG_PRINT("info", ("isNull=%d", isNull)); + DBUG_RETURN(0); +} + int NdbBlob::setNull() { @@ -1085,6 +1116,8 @@ NdbBlob::deletePartsUnknown(Uint32 part) { DBUG_ENTER("NdbBlob::deletePartsUnknown"); DBUG_PRINT("info", ("part=%u count=all", part)); + if (thePartSize == 0) // tinyblob + DBUG_RETURN(0); static const unsigned maxbat = 256; static const unsigned minbat = 1; unsigned bat = minbat; diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 75760fb4019..31234d683d7 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -87,7 +87,12 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col) m_arrayType = col.m_arrayType; m_storageType = col.m_storageType; m_keyInfoPos = col.m_keyInfoPos; - m_blobTable = col.m_blobTable; + if (col.m_blobTable == NULL) + m_blobTable = NULL; + else { + m_blobTable = new NdbTableImpl(); + m_blobTable->assign(*col.m_blobTable); + } m_column_no = col.m_column_no; // Do not copy m_facade !! @@ -2747,14 +2752,25 @@ NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl) } int -NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl) +NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl, bool lock) { const char * internalTableName = impl.m_internalName.c_str(); + if (lock) + m_globalHash->lock(); + if (impl.m_noOfBlobs != 0) { + for (uint i = 0; i < impl.m_columns.size(); i++) { + NdbColumnImpl& c = *impl.m_columns[i]; + if (! c.getBlobType() || c.getPartSize() == 0) + continue; + assert(c.m_blobTable != NULL); + removeCachedObject(*c.m_blobTable, false); + } + } m_localHash.drop(internalTableName); - m_globalHash->lock(); m_globalHash->release(&impl); - m_globalHash->unlock(); + if (lock) + m_globalHash->unlock(); return 0; } diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 6b20625bcdc..1685c3122a3 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -545,7 +545,7 @@ public: int dropTable(NdbTableImpl &); int dropBlobTables(NdbTableImpl &); int invalidateObject(NdbTableImpl &); - int removeCachedObject(NdbTableImpl &); + int removeCachedObject(NdbTableImpl &, bool lock = true); int createIndex(NdbIndexImpl &ix); int dropIndex(const char * indexName, diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 0a9993e33a1..82bfb8e2228 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -342,15 +342,18 @@ NdbEventOperationImpl::getBlobHandle(const NdbColumnImpl *tAttrInfo, int n) tBlobOp = tBlobOp->m_next; } - DBUG_PRINT("info", ("%s op %s", tBlobOp ? " reuse" : " create", bename)); + DBUG_PRINT("info", ("%s blob event op for %s", + tBlobOp ? " reuse" : " create", bename)); // create blob event op if not found if (tBlobOp == NULL) { // to hide blob op it is linked under main op, not under m_ndb NdbEventOperation* tmp = m_ndb->theEventBuffer->createEventOperation(bename, m_error); - if (tmp == NULL) + if (tmp == NULL) { + m_error.code = m_ndb->theEventBuffer->m_error.code; DBUG_RETURN(NULL); + } tBlobOp = &tmp->m_impl; // pointer to main table op @@ -367,11 +370,14 @@ NdbEventOperationImpl::getBlobHandle(const NdbColumnImpl *tAttrInfo, int n) } tBlob = m_ndb->getNdbBlob(); - if (tBlob == NULL) + if (tBlob == NULL) { + m_error.code = m_ndb->getNdbError().code; DBUG_RETURN(NULL); + } // calls getValue on inline and blob part if (tBlob->atPrepare(this, tBlobOp, tAttrInfo, n) == -1) { + m_error.code = tBlob->getNdbError().code; m_ndb->releaseNdbBlob(tBlob); DBUG_RETURN(NULL); } diff --git a/storage/ndb/test/ndbapi/test_event.cpp b/storage/ndb/test/ndbapi/test_event.cpp index a09f6d7c9c8..03bca8f71b2 100644 --- a/storage/ndb/test/ndbapi/test_event.cpp +++ b/storage/ndb/test/ndbapi/test_event.cpp @@ -990,7 +990,7 @@ static int copy_events(Ndb *ndb) while ((pOp= ndb->nextEvent())) { char buf[1024]; - sprintf(buf, "%s_SHADOW", pOp->getTable()->getName()); + sprintf(buf, "%s_SHADOW", pOp->getEvent()->getTable()->getName()); const NdbDictionary::Table *table= dict->getTable(buf); if (table == 0)