From: magnus.blaudd Date: May 23 2011 1:45pm Subject: bzr commit into mysql-5.1-telco-7.0 branch (magnus.blaudd:4402) Bug#12581895 List-Archive: http://lists.mysql.com/commits/137874 X-Bug: 12581895 Message-Id: <20110523134603.11AAC134078@pilot> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7167198838414076767==" --===============7167198838414076767== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/msvensson/mysql/bug11885602/7.0/ based on revid:magnus.blaudd@stripped 4402 magnus.blaudd@stripped 2011-05-23 Bug#12581895 - ndbinfo should support opening tables with more or differently named columns - Add support for opening a table with more fields than exist in NDBINFO, all fields not sent by NDB will be set to NULL - Add check to prevent opening a table with fields which are NOT NULL - Extend NdbInfoRecAttr with isNULL() modified: mysql-test/suite/ndb/r/ndbinfo.result mysql-test/suite/ndb/t/ndbinfo.test sql/ha_ndbinfo.cc storage/ndb/src/ndbapi/NdbInfoRecAttr.hpp storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp === modified file 'mysql-test/suite/ndb/r/ndbinfo.result' --- a/mysql-test/suite/ndb/r/ndbinfo.result 2011-05-23 11:57:55 +0000 +++ b/mysql-test/suite/ndb/r/ndbinfo.result 2011-05-23 13:45:57 +0000 @@ -180,20 +180,55 @@ node_id != 0 1 Warnings: Warning 40001 Table 'ndb$test' is defined differently in NDB, there are more columns available. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' - -## 2) Column does not exist in NDB -> error, with warning DROP TABLE ndb$test; + +## 2) Column does not exist in NDB -> allowed, with warning, non existing +## column(s) return NULL +## 2a) Extra column at end CREATE TABLE ndb$test (node_id int, non_existing int) ENGINE = ndbinfo; -SELECT * FROM ndb$test; -ERROR HY000: Got error 40001 'Incompatible table definitions' from NDBINFO -SHOW WARNINGS; -Level Code Message +SELECT DISTINCT node_id, non_existing FROM ndb$test; +node_id non_existing +1 NULL +2 NULL +Warnings: Error 40001 Table 'ndb$test' is defined differently in NDB, column 'non_existing' does not exist. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' -Error 1296 Got error 40001 'Incompatible table definitions' from NDBINFO +Warning 40001 Table 'ndb$test' is defined differently in NDB, there are more columns available. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' +DROP TABLE ndb$test; + +## 2b) Extra column(s) in middle +CREATE TABLE ndb$test ( + node_id int unsigned, + non_existing int unsigned, + block_number int unsigned, + block_instance int unsigned, + counter int unsigned, + counter2 bigint unsigned +) ENGINE = ndbinfo; +SELECT DISTINCT node_id, non_existing, block_number FROM ndb$test; +node_id non_existing block_number +1 NULL 249 +2 NULL 249 +Warnings: +Error 40001 Table 'ndb$test' is defined differently in NDB, column 'non_existing' does not exist. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' +DROP TABLE ndb$test; + +## 2c) Extra column first +CREATE TABLE ndb$test (non_existing int, node_id int) ENGINE = ndbinfo; +SELECT DISTINCT node_id, non_existing FROM ndb$test; +node_id non_existing +1 NULL +2 NULL +Warnings: +Error 40001 Table 'ndb$test' is defined differently in NDB, column 'non_existing' does not exist. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' +Warning 40001 Table 'ndb$test' is defined differently in NDB, there are more columns available. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' +SELECT DISTINCT non_existing, node_id FROM ndb$test; +non_existing node_id +NULL 1 +NULL 2 +DROP TABLE ndb$test; ## 3) Incompatible column type -> error, with warning ## 3a) int instead of bigint -DROP TABLE ndb$test; CREATE TABLE ndb$test (counter2 int) ENGINE = ndbinfo; SELECT * FROM ndb$test; ERROR HY000: Got error 40001 'Incompatible table definitions' from NDBINFO @@ -220,6 +255,26 @@ Level Code Message Error 40001 Table 'ndb$test' is defined differently in NDB, column 'node_id' is not compatible. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' Error 1296 Got error 40001 'Incompatible table definitions' from NDBINFO DROP TABLE ndb$test; +## 3d) column which is NOT NULL +CREATE TABLE ndb$test (node_id int unsigned NOT NULL) ENGINE = ndbinfo; +SELECT * FROM ndb$test; +ERROR HY000: Got error 40001 'Incompatible table definitions' from NDBINFO +SHOW WARNINGS; +Level Code Message +Error 40001 Table 'ndb$test' is defined differently in NDB, column 'node_id' is NOT NULL. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' +Error 1296 Got error 40001 'Incompatible table definitions' from NDBINFO +DROP TABLE ndb$test; +## 3e) non existing column which is NOT NULL +CREATE TABLE ndb$test ( + block_number int unsigned, + non_existing int NOT NULL) ENGINE = ndbinfo; +SELECT * FROM ndb$test; +ERROR HY000: Got error 40001 'Incompatible table definitions' from NDBINFO +SHOW WARNINGS; +Level Code Message +Error 40001 Table 'ndb$test' is defined differently in NDB, column 'non_existing' is NOT NULL. The SQL to regenerate is: 'CREATE TABLE `ndbinfo`.`ndb$test` (`node_id` INT UNSIGNED, `block_number` INT UNSIGNED, `block_instance` INT UNSIGNED, `counter` INT UNSIGNED, `counter2` BIGINT UNSIGNED) ENGINE=NDBINFO' +Error 1296 Got error 40001 'Incompatible table definitions' from NDBINFO +DROP TABLE ndb$test; ## 4) Table with primary key/indexes not supported CREATE TABLE ndb$test (node_id int, block_number int PRIMARY KEY) ENGINE = ndbinfo; === modified file 'mysql-test/suite/ndb/t/ndbinfo.test' --- a/mysql-test/suite/ndb/t/ndbinfo.test 2011-05-23 11:57:55 +0000 +++ b/mysql-test/suite/ndb/t/ndbinfo.test 2011-05-23 13:45:57 +0000 @@ -98,17 +98,35 @@ SELECT count(*) >= 20 FROM blocks; DROP TABLE ndb$test; CREATE TABLE ndb$test (node_id int unsigned) ENGINE = ndbinfo; SELECT node_id != 0 FROM ndb$test LIMIT 1; - -## 2) Column does not exist in NDB -> error, with warning DROP TABLE ndb$test; + +## 2) Column does not exist in NDB -> allowed, with warning, non existing +## column(s) return NULL +## 2a) Extra column at end CREATE TABLE ndb$test (node_id int, non_existing int) ENGINE = ndbinfo; ---error ER_GET_ERRMSG -SELECT * FROM ndb$test; -SHOW WARNINGS; +SELECT DISTINCT node_id, non_existing FROM ndb$test; +DROP TABLE ndb$test; + +## 2b) Extra column(s) in middle +CREATE TABLE ndb$test ( + node_id int unsigned, + non_existing int unsigned, + block_number int unsigned, + block_instance int unsigned, + counter int unsigned, + counter2 bigint unsigned +) ENGINE = ndbinfo; +SELECT DISTINCT node_id, non_existing, block_number FROM ndb$test; +DROP TABLE ndb$test; + +## 2c) Extra column first +CREATE TABLE ndb$test (non_existing int, node_id int) ENGINE = ndbinfo; +SELECT DISTINCT node_id, non_existing FROM ndb$test; +SELECT DISTINCT non_existing, node_id FROM ndb$test; +DROP TABLE ndb$test; ## 3) Incompatible column type -> error, with warning ## 3a) int instead of bigint -DROP TABLE ndb$test; CREATE TABLE ndb$test (counter2 int) ENGINE = ndbinfo; --error ER_GET_ERRMSG SELECT * FROM ndb$test; @@ -126,6 +144,21 @@ CREATE TABLE ndb$test (node_id varchar(2 SELECT * FROM ndb$test; SHOW WARNINGS; DROP TABLE ndb$test; +## 3d) column which is NOT NULL +CREATE TABLE ndb$test (node_id int unsigned NOT NULL) ENGINE = ndbinfo; +--error ER_GET_ERRMSG +SELECT * FROM ndb$test; +SHOW WARNINGS; +DROP TABLE ndb$test; +## 3e) non existing column which is NOT NULL +CREATE TABLE ndb$test ( + block_number int unsigned, + non_existing int NOT NULL) ENGINE = ndbinfo; +--error ER_GET_ERRMSG +SELECT * FROM ndb$test; +SHOW WARNINGS; +DROP TABLE ndb$test; + ## 4) Table with primary key/indexes not supported --error ER_TOO_MANY_KEYS === modified file 'sql/ha_ndbinfo.cc' --- a/sql/ha_ndbinfo.cc 2011-05-23 12:09:04 +0000 +++ b/sql/ha_ndbinfo.cc 2011-05-23 13:45:57 +0000 @@ -373,21 +373,36 @@ int ha_ndbinfo::open(const char *name, i DBUG_RETURN(err2mysql(err)); } + /* + Check table def. to detect incompatible differences which should + return an error. Differences which only generate a warning + is checked on first use + */ DBUG_PRINT("info", ("Comparing MySQL's table def against NDB")); const NdbInfo::Table* ndb_tab = m_impl.m_table; for (uint i = 0; i < table->s->fields; i++) { const Field* field = table->field[i]; - const NdbInfo::Column* col = ndb_tab->getColumn(field->field_name); - if (!col) + + // Check if field is NULLable + if (const_cast(field)->real_maybe_null() == false) { - // The column didn't exist + // Only NULLable fields supported warn_incompatible(ndb_tab, true, - "column '%s' does not exist", + "column '%s' is NOT NULL", field->field_name); DBUG_RETURN(ERR_INCOMPAT_TABLE_DEF); } + // Check if column exist in NDB + const NdbInfo::Column* col = ndb_tab->getColumn(field->field_name); + if (!col) + { + // The column didn't exist + continue; + } + + // Check compatible field and column type bool compatible = false; switch(col->m_type) { @@ -465,13 +480,30 @@ int ha_ndbinfo::rnd_init(bool scan) m_impl.m_first_use = false; /* - Due to different code paths in MySQL Server - for prepared statement protocol, some warnings - from 'handler::open' are lost and need to be - deffered to first use instead + Check table def. and generate warnings for incompatibilites + which is allowed but should generate a warning. + (Done this late due to different code paths in MySQL Server for + prepared statement protocol, where warnings from 'handler::open' + are lost). */ + uint fields_found_in_ndb = 0; const NdbInfo::Table* ndb_tab = m_impl.m_table; - if (table->s->fields < ndb_tab->columns()) + for (uint i = 0; i < table->s->fields; i++) + { + const Field* field = table->field[i]; + const NdbInfo::Column* col = ndb_tab->getColumn(field->field_name); + if (!col) + { + // The column didn't exist + warn_incompatible(ndb_tab, true, + "column '%s' does not exist", + field->field_name); + continue; + } + fields_found_in_ndb++; + } + + if (fields_found_in_ndb < ndb_tab->columns()) { // There are more columns available in NDB warn_incompatible(ndb_tab, false, @@ -599,7 +631,7 @@ ha_ndbinfo::unpack_record(uchar *dst_row { Field *field = table->field[i]; const NdbInfoRecAttr* record = m_impl.m_columns[i]; - if (m_impl.m_columns[i]) + if (record && !record->isNULL()) { field->set_notnull(); field->move_field_offset(dst_offset); === modified file 'storage/ndb/src/ndbapi/NdbInfoRecAttr.hpp' --- a/storage/ndb/src/ndbapi/NdbInfoRecAttr.hpp 2011-02-02 00:40:07 +0000 +++ b/storage/ndb/src/ndbapi/NdbInfoRecAttr.hpp 2011-05-23 13:45:57 +0000 @@ -46,13 +46,18 @@ public: return m_len; } + bool isNULL() const { + return !m_defined; + } + protected: friend class NdbInfoScanOperation; - NdbInfoRecAttr() : m_data(NULL), m_len(0) {}; + NdbInfoRecAttr() : m_data(NULL), m_len(0), m_defined(false) {}; ~NdbInfoRecAttr() {}; private: const char* m_data; Uint32 m_len; + bool m_defined; }; #endif === modified file 'storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp' --- a/storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp 2011-02-02 00:40:07 +0000 +++ b/storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp 2011-05-23 13:45:57 +0000 @@ -418,34 +418,35 @@ NdbInfoScanOperation::execDBINFO_TRANSID m_rows_received++; DBUG_PRINT("info", ("rows received: %d", m_rows_received)); - const Uint32* start = signal->ptr[0].p; - const Uint32* end = start + signal->ptr[0].sz; - - DBUG_PRINT("info", ("start: %p, end: %p", start, end)); - for (unsigned col = 0; col < m_table->columns(); col++) + // Reset all recattr values before reading the new row + for (unsigned i = 0; i < m_recAttrs.size(); i++) { + if (m_recAttrs[i]) + m_recAttrs[i]->m_defined = false; + } - // Read attribute header - const AttributeHeader ah(*start); - const Uint32 len = ah.getByteSize(); + // Read attributes from long signal section + AttributeHeader* attr = (AttributeHeader*)signal->ptr[0].p; + AttributeHeader* last = (AttributeHeader*)(signal->ptr[0].p + + signal->ptr[0].sz); + while (attr < last) + { + const Uint32 col = attr->getAttributeId(); + const Uint32 len = attr->getByteSize(); DBUG_PRINT("info", ("col: %u, len: %u", col, len)); - - // Step past attribute header - start += ah.getHeaderSize(); - - NdbInfoRecAttr* attr = m_recAttrs[col]; - if (attr) + if (col < m_recAttrs.size()) { - // Update NdbInfoRecAttr pointer and length - attr->m_data = (const char*)start; - attr->m_len = len; + NdbInfoRecAttr* rec_attr = m_recAttrs[col]; + if (rec_attr) + { + // Update NdbInfoRecAttr pointer, length and defined flag + rec_attr->m_data = (const char*)attr->getDataPtr(); + rec_attr->m_len = len; + rec_attr->m_defined = true; + } } - // Step to next attribute header - start += ah.getDataSize(); - - // No reading beyond end of signal size - assert(start <= end); + attr = attr->getNext(); } DBUG_RETURN(false); // Don't wait more, process this row --===============7167198838414076767== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/magnus.blaudd@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: magnus.blaudd@stripped\ # gh0ten733aj3k3xg # target_branch: file:///home/msvensson/mysql/bug11885602/7.0/ # testament_sha1: 220da1a1feaf2c83debf296a9fa4ee3aaf17e211 # timestamp: 2011-05-23 15:46:03 +0200 # base_revision_id: magnus.blaudd@stripped\ # 25vipsdesx79yl92 # # Begin bundle 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 --===============7167198838414076767==--