#At file:///data0/magnus/mysql/tmp/YqeN8qM6jS/7.1/ based on revid:magnus.blaudd@stripped
4213 magnus.blaudd@stripped 2011-05-23 [merge]
Merge 7.0 -> 7.1
modified:
mysql-test/suite/ndb/r/ndbinfo.result
mysql-test/suite/ndb/t/ndbinfo.test
sql/ha_ndbinfo.cc
sql/ha_ndbinfo.h
storage/ndb/include/ndbapi/ndb_cluster_connection.hpp
storage/ndb/src/ndbapi/NdbInfo.cpp
storage/ndb/src/ndbapi/NdbInfo.hpp
storage/ndb/src/ndbapi/NdbInfoRecAttr.hpp
storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp
storage/ndb/src/ndbapi/TransporterFacade.hpp
storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
storage/ndb/tools/ndbinfo_sql.cpp
=== modified file 'mysql-test/suite/ndb/r/ndbinfo.result'
--- a/mysql-test/suite/ndb/r/ndbinfo.result 2010-11-03 09:49:39 +0000
+++ b/mysql-test/suite/ndb/r/ndbinfo.result 2011-05-23 14:50:45 +0000
@@ -135,6 +135,7 @@ Variable_name Value
ndbinfo_database ndbinfo
ndbinfo_max_bytes 0
ndbinfo_max_rows 10
+ndbinfo_offline OFF
ndbinfo_show_hidden OFF
ndbinfo_table_prefix ndb$
ndbinfo_version NDB_VERSION_D
@@ -178,20 +179,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
@@ -218,6 +254,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;
@@ -237,3 +293,55 @@ node_id
1
2
+set @@ndbinfo_offline=1;
+ERROR HY000: Variable 'ndbinfo_offline' is a GLOBAL variable and should be set with SET GLOBAL
+
+SELECT DISTINCT(node_id) FROM ndbinfo.counters ORDER BY node_id;
+node_id
+1
+2
+
+set @@global.ndbinfo_offline=TRUE;
+select @@ndbinfo_offline;
+@@ndbinfo_offline
+1
+
+CREATE TABLE ndb$does_not_exist_in_ndb(
+ node_id int,
+ message varchar(255)
+) ENGINE = ndbinfo;
+
+CREATE VIEW view_on_table_which_does_not_exist_in_ndb AS
+ SELECT node_id, message
+ FROM ndbinfo.ndb$does_not_exist_in_ndb;
+
+SHOW CREATE TABLE ndb$does_not_exist_in_ndb;
+Table Create Table
+ndb$does_not_exist_in_ndb CREATE TABLE `ndb$does_not_exist_in_ndb` (
+ `node_id` int(11) DEFAULT NULL,
+ `message` varchar(255) DEFAULT NULL
+) ENGINE=NDBINFO DEFAULT CHARSET=latin1
+
+SELECT * FROM view_on_table_which_does_not_exist_in_ndb;
+node_id message
+Warnings:
+Note 1 'NDBINFO' has been started in offline mode since the 'NDBCLUSTER' engine is disabled or @@global.ndbinfo_offline is turned on - no rows can be returned
+SELECT * FROM ndb$does_not_exist_in_ndb;
+node_id message
+Warnings:
+Note 1 'NDBINFO' has been started in offline mode since the 'NDBCLUSTER' engine is disabled or @@global.ndbinfo_offline is turned on - no rows can be returned
+SELECT DISTINCT(node_id) FROM ndbinfo.counters ORDER BY node_id;
+node_id
+Warnings:
+Note 1 'NDBINFO' has been started in offline mode since the 'NDBCLUSTER' engine is disabled or @@global.ndbinfo_offline is turned on - no rows can be returned
+
+DROP VIEW view_on_table_which_does_not_exist_in_ndb;
+DROP TABLE ndb$does_not_exist_in_ndb;
+
+set @@global.ndbinfo_offline = FALSE;
+
+SELECT DISTINCT(node_id) FROM ndbinfo.counters ORDER BY node_id;
+node_id
+1
+2
+
=== modified file 'mysql-test/suite/ndb/t/ndbinfo.test'
--- a/mysql-test/suite/ndb/t/ndbinfo.test 2010-11-03 09:49:39 +0000
+++ b/mysql-test/suite/ndb/t/ndbinfo.test 2011-05-23 14:50:45 +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
@@ -148,4 +181,52 @@ CREATE TABLE ndb$test (node_id int AUTO_
select distinct node_id
from ndbinfo.diskpagebuffer;
+
+#
+# BUG#11885602
+# - It was allowed to CREATE TABLE which was not in NDB, but
+# creating a view on that table failed. Implement ndbinfo_offline
+# mode which allows tables to be created and opened although they
+# don't exists or have different table definition.
+# This is exactly the same behaviour as when NDBCLUSTER
+# is disabled
+#
+
+# Check ndbinfo_offline is GLOBAL variable
+--error ER_GLOBAL_VARIABLE
+set @@ndbinfo_offline=1;
+
+# Query used to check that open tables are closed
+# when offline mode is turned on and off
+let $q1 = SELECT DISTINCT(node_id) FROM ndbinfo.counters ORDER BY node_id;
+eval $q1;
+
+# Turn on ndbinfo_offline
+set @@global.ndbinfo_offline=TRUE;
+select @@ndbinfo_offline;
+
+CREATE TABLE ndb$does_not_exist_in_ndb(
+ node_id int,
+ message varchar(255)
+) ENGINE = ndbinfo;
+
+CREATE VIEW view_on_table_which_does_not_exist_in_ndb AS
+ SELECT node_id, message
+ FROM ndbinfo.ndb$does_not_exist_in_ndb;
+
+SHOW CREATE TABLE ndb$does_not_exist_in_ndb;
+
+# SELECTs return no rows in offline mode
+SELECT * FROM view_on_table_which_does_not_exist_in_ndb;
+SELECT * FROM ndb$does_not_exist_in_ndb;
+eval $q1;
+
+DROP VIEW view_on_table_which_does_not_exist_in_ndb;
+DROP TABLE ndb$does_not_exist_in_ndb;
+
+# Restore original value
+set @@global.ndbinfo_offline = FALSE;
+
+eval $q1;
+
--source ndbinfo_drop.inc
=== modified file 'sql/ha_ndbinfo.cc'
--- a/sql/ha_ndbinfo.cc 2010-11-10 14:17:13 +0000
+++ b/sql/ha_ndbinfo.cc 2011-05-23 13:45:57 +0000
@@ -56,10 +56,10 @@ static MYSQL_THDVAR_BOOL(
FALSE /* default */
);
-static char* ndbinfo_dbname = (char*)"ndbinfo";
+static char* opt_ndbinfo_dbname = (char*)"ndbinfo";
static MYSQL_SYSVAR_STR(
database, /* name */
- ndbinfo_dbname, /* var */
+ opt_ndbinfo_dbname, /* var */
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Name of the database used by ndbinfo",
NULL, /* check func. */
@@ -67,10 +67,10 @@ static MYSQL_SYSVAR_STR(
NULL /* default */
);
-static char* table_prefix = (char*)"ndb$";
+static char* opt_ndbinfo_table_prefix = (char*)"ndb$";
static MYSQL_SYSVAR_STR(
table_prefix, /* name */
- table_prefix, /* var */
+ opt_ndbinfo_table_prefix, /* var */
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Prefix to use for all virtual tables loaded from NDB",
NULL, /* check func. */
@@ -78,10 +78,10 @@ static MYSQL_SYSVAR_STR(
NULL /* default */
);
-static Uint32 version = NDB_VERSION_D;
+static Uint32 opt_ndbinfo_version = NDB_VERSION_D;
static MYSQL_SYSVAR_UINT(
version, /* name */
- version, /* var */
+ opt_ndbinfo_version, /* var */
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
"Compile version for ndbinfo",
NULL, /* check func. */
@@ -92,6 +92,45 @@ static MYSQL_SYSVAR_UINT(
0 /* block */
);
+static my_bool opt_ndbinfo_offline;
+
+static
+void
+offline_update(THD* thd, struct st_mysql_sys_var* var,
+ void* var_ptr, const void* save)
+{
+ DBUG_ENTER("offline_update");
+
+ const my_bool new_offline =
+ (*(static_cast<const my_bool*>(save)) != 0);
+ if (new_offline == opt_ndbinfo_offline)
+ {
+ // No change
+ DBUG_VOID_RETURN;
+ }
+
+ // Set offline mode, any tables opened from here on will
+ // be opened in the new mode
+ opt_ndbinfo_offline = new_offline;
+
+ // Close any open tables which may be in the old mode
+ (void)close_cached_tables(thd, NULL, false, true, false);
+
+ DBUG_VOID_RETURN;
+}
+
+static MYSQL_SYSVAR_BOOL(
+ offline, /* name */
+ opt_ndbinfo_offline, /* var */
+ PLUGIN_VAR_NOCMDOPT,
+ "Set ndbinfo in offline mode, tables and views can "
+ "be opened even if they don't exist or have different "
+ "definition in NDB. No rows will be returned.",
+ NULL, /* check func. */
+ offline_update, /* update func. */
+ 0 /* default */
+);
+
static NdbInfo* g_ndbinfo;
@@ -124,10 +163,15 @@ struct ha_ndbinfo_impl
Vector<const NdbInfoRecAttr *> m_columns;
bool m_first_use;
+ // Indicates if table has been opened in offline mode
+ // can only be reset by closing the table
+ bool m_offline;
+
ha_ndbinfo_impl() :
m_table(NULL),
m_scan_op(NULL),
- m_first_use(true)
+ m_first_use(true),
+ m_offline(false)
{
}
};
@@ -211,7 +255,7 @@ static void
generate_sql(const NdbInfo::Table* ndb_tab, BaseString& sql)
{
sql.appfmt("'CREATE TABLE `%s`.`%s%s` (",
- ndbinfo_dbname, table_prefix, ndb_tab->getName());
+ opt_ndbinfo_dbname, opt_ndbinfo_table_prefix, ndb_tab->getName());
const char* separator = "";
for (unsigned i = 0; i < ndb_tab->columns(); i++)
@@ -265,7 +309,7 @@ warn_incompatible(const NdbInfo::Table*
msg.assfmt("Table '%s%s' is defined differently in NDB, %s. The "
"SQL to regenerate is: ",
- table_prefix, ndb_tab->getName(), explanation);
+ opt_ndbinfo_table_prefix, ndb_tab->getName(), explanation);
generate_sql(ndb_tab, msg);
const MYSQL_ERROR::enum_warning_level level =
@@ -289,12 +333,18 @@ bool ha_ndbinfo::is_open(void) const
return m_impl.m_table != NULL;
}
+bool ha_ndbinfo::is_offline(void) const
+{
+ return m_impl.m_offline;
+}
+
int ha_ndbinfo::open(const char *name, int mode, uint test_if_locked)
{
DBUG_ENTER("ha_ndbinfo::open");
DBUG_PRINT("enter", ("name: %s, mode: %d", name, mode));
assert(is_closed());
+ assert(!is_offline()); // Closed table can not be offline
if (mode == O_RDWR)
{
@@ -307,9 +357,11 @@ int ha_ndbinfo::open(const char *name, i
DBUG_ASSERT(false);
}
- if (ndbcluster_is_disabled())
+ if (opt_ndbinfo_offline ||
+ ndbcluster_is_disabled())
{
- // Allow table to be opened with ndbcluster disabled
+ // Mark table as being offline and allow it to be opened
+ m_impl.m_offline = true;
DBUG_RETURN(0);
}
@@ -321,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*>(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)
{
@@ -378,7 +445,7 @@ int ha_ndbinfo::close(void)
{
DBUG_ENTER("ha_ndbinfo::close");
- if (ndbcluster_is_disabled())
+ if (is_offline())
DBUG_RETURN(0);
assert(is_open());
@@ -395,12 +462,13 @@ int ha_ndbinfo::rnd_init(bool scan)
DBUG_ENTER("ha_ndbinfo::rnd_init");
DBUG_PRINT("info", ("scan: %d", scan));
- if (ndbcluster_is_disabled())
+ if (is_offline())
{
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 1,
- "'NDBINFO' has been started "
- "in limited mode since the 'NDBCLUSTER' "
- "engine is disabled - no rows can be returned");
+ "'NDBINFO' has been started in offline mode "
+ "since the 'NDBCLUSTER' engine is disabled "
+ "or @@global.ndbinfo_offline is turned on "
+ "- no rows can be returned");
DBUG_RETURN(0);
}
@@ -412,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,
@@ -466,7 +551,7 @@ int ha_ndbinfo::rnd_end()
{
DBUG_ENTER("ha_ndbinfo::rnd_end");
- if (ndbcluster_is_disabled())
+ if (is_offline())
DBUG_RETURN(0);
assert(is_open());
@@ -486,7 +571,7 @@ int ha_ndbinfo::rnd_next(uchar *buf)
int err;
DBUG_ENTER("ha_ndbinfo::rnd_next");
- if (ndbcluster_is_disabled())
+ if (is_offline())
DBUG_RETURN(HA_ERR_END_OF_FILE);
assert(is_open());
@@ -546,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);
@@ -617,7 +702,7 @@ ndbinfo_find_files(handlerton *hton, THD
List_iterator<LEX_STRING> it(*files);
while ((dir_name=it++))
{
- if (strcmp(dir_name->str, ndbinfo_dbname))
+ if (strcmp(dir_name->str, opt_ndbinfo_dbname))
continue;
DBUG_PRINT("info", ("Hiding own databse '%s'", dir_name->str));
@@ -628,7 +713,7 @@ ndbinfo_find_files(handlerton *hton, THD
}
DBUG_ASSERT(db);
- if (strcmp(db, ndbinfo_dbname))
+ if (strcmp(db, opt_ndbinfo_dbname))
DBUG_RETURN(0); // Only hide files in "our" db
/* Hide all files that start with "our" prefix */
@@ -636,7 +721,7 @@ ndbinfo_find_files(handlerton *hton, THD
List_iterator<LEX_STRING> it(*files);
while ((file_name=it++))
{
- if (is_prefix(file_name->str, table_prefix))
+ if (is_prefix(file_name->str, opt_ndbinfo_table_prefix))
{
DBUG_PRINT("info", ("Hiding '%s'", file_name->str));
it.remove();
@@ -668,11 +753,11 @@ int ndbinfo_init(void *plugin)
char prefix[FN_REFLEN];
build_table_filename(prefix, sizeof(prefix) - 1,
- ndbinfo_dbname, table_prefix, "", 0);
+ opt_ndbinfo_dbname, opt_ndbinfo_table_prefix, "", 0);
DBUG_PRINT("info", ("prefix: '%s'", prefix));
assert(g_ndb_cluster_connection);
g_ndbinfo = new NdbInfo(g_ndb_cluster_connection, prefix,
- ndbinfo_dbname, table_prefix);
+ opt_ndbinfo_dbname, opt_ndbinfo_table_prefix);
if (!g_ndbinfo)
{
sql_print_error("Failed to create NdbInfo");
@@ -712,6 +797,7 @@ struct st_mysql_sys_var* ndbinfo_system_
MYSQL_SYSVAR(database),
MYSQL_SYSVAR(table_prefix),
MYSQL_SYSVAR(version),
+ MYSQL_SYSVAR(offline),
NULL
};
=== modified file 'sql/ha_ndbinfo.h'
--- a/sql/ha_ndbinfo.h 2011-02-01 14:58:21 +0000
+++ b/sql/ha_ndbinfo.h 2011-05-23 11:57:55 +0000
@@ -83,6 +83,8 @@ private:
bool is_open(void) const;
bool is_closed(void) const { return ! is_open(); };
+ bool is_offline(void) const;
+
struct ha_ndbinfo_impl& m_impl;
};
=== modified file 'storage/ndb/include/ndbapi/ndb_cluster_connection.hpp'
--- a/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp 2011-02-04 18:34:09 +0000
+++ b/storage/ndb/include/ndbapi/ndb_cluster_connection.hpp 2011-05-23 14:50:45 +0000
@@ -192,6 +192,7 @@ public:
unsigned max_nodegroup();
unsigned node_id();
unsigned get_connect_count() const;
+ unsigned get_min_db_version() const;
void init_get_next_node(Ndb_cluster_connection_node_iter &iter);
unsigned int get_next_node(Ndb_cluster_connection_node_iter &iter);
=== modified file 'storage/ndb/src/ndbapi/NdbInfo.cpp'
--- a/storage/ndb/src/ndbapi/NdbInfo.cpp 2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/ndbapi/NdbInfo.cpp 2011-05-23 14:05:08 +0000
@@ -23,6 +23,7 @@ NdbInfo::NdbInfo(class Ndb_cluster_conne
const char* prefix, const char* dbname,
const char* table_prefix) :
m_connect_count(connection->get_connect_count()),
+ m_min_db_version(0),
m_connection(connection),
m_tables_table(NULL), m_columns_table(NULL),
m_prefix(prefix),
@@ -270,7 +271,9 @@ bool NdbInfo::load_tables()
}
// After sucessfull load of the tables, set connect count
+ // and the min db version of cluster
m_connect_count = m_connection->get_connect_count();
+ m_min_db_version = m_connection->get_min_db_version();
return true;
}
@@ -328,12 +331,14 @@ void NdbInfo::flush_tables()
bool
NdbInfo::check_tables()
{
- if (m_connection->get_connect_count() != m_connect_count)
+ if (unlikely(m_connection->get_connect_count() != m_connect_count ||
+ m_connection->get_min_db_version() != m_min_db_version))
{
- // Connect count has changed -> flush the cached table definitions
+ // Connect count or min db version of cluster has changed
+ // -> flush the cached table definitions
flush_tables();
}
- if (m_tables.entries() <= NUM_HARDCODED_TABLES)
+ if (unlikely(m_tables.entries() <= NUM_HARDCODED_TABLES))
{
// Global table cache is not loaded yet or has been
// flushed, try to load it
=== modified file 'storage/ndb/src/ndbapi/NdbInfo.hpp'
--- a/storage/ndb/src/ndbapi/NdbInfo.hpp 2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/ndbapi/NdbInfo.hpp 2011-05-23 14:05:08 +0000
@@ -89,8 +89,6 @@ public:
bool init(void);
~NdbInfo();
- void flush_tables();
-
int openTable(const char* table_name, const Table**);
int openTable(Uint32 tableId, const Table**);
void closeTable(const Table* table);
@@ -103,6 +101,7 @@ public:
private:
static const size_t NUM_HARDCODED_TABLES = 2;
unsigned m_connect_count;
+ unsigned m_min_db_version;
class Ndb_cluster_connection* m_connection;
pthread_mutex_t m_mutex;
HashMap<BaseString, Table, BaseString_get_key> m_tables;
@@ -119,6 +118,7 @@ private:
bool load_hardcoded_tables(void);
bool load_tables();
bool check_tables();
+ void flush_tables();
BaseString mysql_table_name(const char* table_name) const;
=== 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
=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.hpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp 2011-02-24 07:47:22 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp 2011-05-23 14:05:08 +0000
@@ -303,6 +303,12 @@ unsigned Ndb_cluster_connection_impl::ge
}
inline
+unsigned Ndb_cluster_connection_impl::get_min_db_version() const
+{
+ return m_transporter_facade->getMinDbNodeVersion();
+}
+
+inline
bool
TransporterFacade::get_node_alive(NodeId n) const {
if (theClusterMgr)
=== modified file 'storage/ndb/src/ndbapi/ndb_cluster_connection.cpp'
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp 2011-04-15 17:56:38 +0000
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp 2011-05-23 14:50:45 +0000
@@ -332,6 +332,11 @@ unsigned Ndb_cluster_connection::get_con
return m_impl.get_connect_count();
}
+unsigned Ndb_cluster_connection::get_min_db_version() const
+{
+ return m_impl.get_min_db_version();
+}
+
int Ndb_cluster_connection::get_latest_error() const
{
return m_impl.m_latest_error;
=== modified file 'storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp'
--- a/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp 2011-02-04 17:52:38 +0000
+++ b/storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp 2011-05-23 14:05:08 +0000
@@ -67,6 +67,7 @@ class Ndb_cluster_connection_impl : publ
Uint32 get_next_alive_node(Ndb_cluster_connection_node_iter &iter);
inline unsigned get_connect_count() const;
+ inline unsigned get_min_db_version() const;
public:
inline Uint64 *get_latest_trans_gci() { return &m_latest_trans_gci; }
=== modified file 'storage/ndb/tools/ndbinfo_sql.cpp'
--- a/storage/ndb/tools/ndbinfo_sql.cpp 2011-04-12 13:59:32 +0000
+++ b/storage/ndb/tools/ndbinfo_sql.cpp 2011-05-23 14:50:45 +0000
@@ -327,6 +327,12 @@ int main(int argc, char** argv){
sql.assfmt("CREATE DATABASE IF NOT EXISTS `%s`", opt_ndbinfo_db);
print_conditional_sql(sql);
+ printf("# Set NDBINFO in offline mode during (re)create of tables\n");
+ printf("# and views to avoid errors caused by no such table or\n");
+ printf("# different table definition in NDB\n");
+ sql.assfmt("SET @@global.ndbinfo_offline=TRUE");
+ print_conditional_sql(sql);
+
printf("# Drop any old views in %s\n", opt_ndbinfo_db);
for (size_t i = 0; i < num_views; i++)
{
@@ -430,6 +436,10 @@ int main(int argc, char** argv){
print_conditional_sql(sql);
}
+ printf("# Finally turn off offline mode\n");
+ sql.assfmt("SET @@global.ndbinfo_offline=FALSE");
+ print_conditional_sql(sql);
+
return 0;
}
No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.1 branch (magnus.blaudd:4213) | magnus.blaudd | 23 May |