mirror of
https://github.com/MariaDB/server.git
synced 2025-06-25 06:22:03 +03:00
Merge fixes
This commit is contained in:
@ -93,6 +93,7 @@ kostja@oak.local
|
||||
lenz@kallisto.mysql.com
|
||||
lenz@mysql.com
|
||||
magnus@neptunus.(none)
|
||||
magnus@shellback.(none)
|
||||
marko@hundin.mysql.fi
|
||||
miguel@hegel.(none)
|
||||
miguel@hegel.br
|
||||
|
@ -241,6 +241,7 @@ enum ha_base_keytype {
|
||||
#define HA_CREATE_TMP_TABLE 4
|
||||
#define HA_CREATE_CHECKSUM 8
|
||||
#define HA_CREATE_DELAY_KEY_WRITE 64
|
||||
#define HA_CREATE_FROM_ENGINE 128
|
||||
|
||||
/* Bits in flag to _status */
|
||||
|
||||
@ -287,7 +288,7 @@ enum ha_base_keytype {
|
||||
#define HA_ERR_ROW_IS_REFERENCED 152 /* Cannot delete a parent row */
|
||||
#define HA_ERR_NO_SAVEPOINT 153 /* No savepoint with that name */
|
||||
#define HA_ERR_NON_UNIQUE_BLOCK_SIZE 154 /* Non unique key block size */
|
||||
#define HA_ERR_OLD_METADATA 155 /* The frm file on disk is old */
|
||||
#define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */
|
||||
#define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */
|
||||
#define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */
|
||||
|
||||
|
@ -520,6 +520,7 @@ if [ x$SOURCE_DIST = x1 ] ; then
|
||||
CHARSETSDIR="$BASEDIR/sql/share/charsets"
|
||||
INSTALL_DB="./install_test_db"
|
||||
MYSQL_FIX_SYSTEM_TABLES="$BASEDIR/scripts/mysql_fix_privilege_tables"
|
||||
NDB_TOOLS_DIR="$BASEDIR/ndb/tools"
|
||||
else
|
||||
if test -x "$BASEDIR/libexec/mysqld"
|
||||
then
|
||||
@ -539,6 +540,7 @@ else
|
||||
MYSQL="$CLIENT_BINDIR/mysql"
|
||||
INSTALL_DB="./install_test_db --bin"
|
||||
MYSQL_FIX_SYSTEM_TABLES="$CLIENT_BINDIR/mysql_fix_privilege_tables"
|
||||
NDB_TOOLS_DIR="$CLIENT_BINDIR"
|
||||
if test -d "$BASEDIR/share/mysql/english"
|
||||
then
|
||||
LANGUAGE="$BASEDIR/share/mysql/english/"
|
||||
@ -586,6 +588,7 @@ MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYS
|
||||
MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
|
||||
MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
|
||||
export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR
|
||||
export NDB_TOOLS_DIR
|
||||
|
||||
MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \
|
||||
--user=$DBUSER --password=$DBPASSWD --silent -v --skip-safemalloc \
|
||||
@ -1595,10 +1598,13 @@ then
|
||||
fi
|
||||
./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT $NDBCLUSTER_OPTS --diskless --initial --data-dir=$MYSQL_TEST_DIR/var || exit 1
|
||||
USE_NDBCLUSTER="$USE_NDBCLUSTER --ndb-connectstring=\"host=localhost:$NDBCLUSTER_PORT\""
|
||||
NDB_CONNECTSTRING="localhost:$NDBCLUSTER_PORT"
|
||||
else
|
||||
USE_NDBCLUSTER="$USE_NDBCLUSTER --ndb-connectstring=\"$USE_RUNNING_NDBCLUSTER\""
|
||||
NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER"
|
||||
echo "Using ndbcluster at $USE_NDBCLUSTER"
|
||||
fi
|
||||
export NDB_CONNECTSTRING
|
||||
fi
|
||||
|
||||
start_manager
|
||||
|
@ -1,4 +1,4 @@
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t9;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
flush status;
|
||||
create table t1(
|
||||
id int not null primary key,
|
||||
@ -94,8 +94,6 @@ ERROR 42S01: Table 't3' already exists
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 1
|
||||
SHOW TABLES FROM test;
|
||||
Tables_in_test
|
||||
create table IF NOT EXISTS t3(
|
||||
id int not null primary key,
|
||||
id2 int not null,
|
||||
@ -119,6 +117,162 @@ Variable_name Value
|
||||
Handler_discover 2
|
||||
drop table t3;
|
||||
flush status;
|
||||
create table t7(
|
||||
id int not null primary key,
|
||||
name char(255)
|
||||
) engine=ndb;
|
||||
create table t6(
|
||||
id int not null primary key,
|
||||
name char(255)
|
||||
) engine=MyISAM;
|
||||
insert into t7 values (1, "Explorer");
|
||||
insert into t6 values (2, "MyISAM table");
|
||||
select * from t7;
|
||||
id name
|
||||
1 Explorer
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 0
|
||||
flush tables;
|
||||
show tables from test;
|
||||
Tables_in_test
|
||||
t6
|
||||
t7
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 1
|
||||
flush tables;
|
||||
show table status;
|
||||
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||
t6 MyISAM 9 Fixed 1 260 # # # 0 NULL # # NULL # NULL
|
||||
t7 ndbcluster 9 Fixed 1 0 # # # 0 NULL # # NULL # NULL
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 2
|
||||
drop table t6, t7;
|
||||
flush status;
|
||||
create table t4(
|
||||
id int not null primary key,
|
||||
name char(27)
|
||||
) engine=ndb;
|
||||
insert into t4 values (1, "Automatic");
|
||||
select * from t4;
|
||||
id name
|
||||
1 Automatic
|
||||
select * from t4;
|
||||
ERROR 42S02: Table 'test.t4' doesn't exist
|
||||
select * from t4;
|
||||
ERROR 42S02: Table 'test.t4' doesn't exist
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 0
|
||||
drop table t4;
|
||||
flush status;
|
||||
create table t4(
|
||||
id int not null primary key,
|
||||
id2 int,
|
||||
name char(27)
|
||||
) engine=ndb;
|
||||
insert into t4 values (1, 76, "Automatic2");
|
||||
select * from t4;
|
||||
id id2 name
|
||||
1 76 Automatic2
|
||||
flush tables;
|
||||
SHOW TABLES;
|
||||
Tables_in_test
|
||||
select * from t4;
|
||||
ERROR 42S02: Table 'test.t4' doesn't exist
|
||||
flush status;
|
||||
create table t1(id int) engine=ndbcluster;
|
||||
create table t2(id int, b char(255)) engine=myisam;
|
||||
create table t3(id int, c char(255)) engine=ndbcluster;
|
||||
create table t4(id int) engine=myisam;
|
||||
create table t5(id int, d char(56)) engine=ndbcluster;
|
||||
create table t6(id int) engine=ndbcluster;
|
||||
create table t7(id int) engine=ndbcluster;
|
||||
create table t8(id int, e char(34)) engine=myisam;
|
||||
create table t9(id int) engine=myisam;
|
||||
insert into t2 values (2, "myisam table 2");
|
||||
insert into t3 values (3, "ndb table 3");
|
||||
insert into t5 values (5, "ndb table 5");
|
||||
insert into t6 values (6);
|
||||
insert into t8 values (8, "myisam table 8");
|
||||
insert into t9 values (9);
|
||||
SHOW TABLES;
|
||||
Tables_in_test
|
||||
t1
|
||||
t2
|
||||
t4
|
||||
t8
|
||||
t9
|
||||
t7
|
||||
t6
|
||||
select * from t6;
|
||||
id
|
||||
6
|
||||
select * from t7;
|
||||
id
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 2
|
||||
drop table t1, t2, t4, t6, t7, t8, t9;
|
||||
flush status;
|
||||
create table t1(id int) engine=ndbcluster;
|
||||
create table t2(id int, b char(255)) engine=myisam;
|
||||
create table t3(id int, c char(255)) engine=ndbcluster;
|
||||
create table t4(id int) engine=myisam;
|
||||
create table t5(id int, d char(56)) engine=ndbcluster;
|
||||
create table t6(id int) engine=ndbcluster;
|
||||
create table t7(id int) engine=ndbcluster;
|
||||
create table t8(id int, e char(34)) engine=myisam;
|
||||
create table t9(id int) engine=myisam;
|
||||
insert into t2 values (2, "myisam table 2");
|
||||
insert into t3 values (3, "ndb table 3");
|
||||
insert into t5 values (5, "ndb table 5");
|
||||
insert into t6 values (6);
|
||||
insert into t8 values (8, "myisam table 8");
|
||||
insert into t9 values (9);
|
||||
SHOW TABLES LIKE 't6';
|
||||
Tables_in_test (t6)
|
||||
t6
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 1
|
||||
create table t3(a int);
|
||||
ERROR 42S01: Table 't3' already exists
|
||||
create table t5(a int);
|
||||
ERROR 42S01: Table 't5' already exists
|
||||
SHOW TABLES LIKE 't%';
|
||||
Tables_in_test (t%)
|
||||
t1
|
||||
t2
|
||||
t4
|
||||
t6
|
||||
t8
|
||||
t9
|
||||
t7
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 2
|
||||
drop table t1, t2, t4, t6, t7, t8, t9;
|
||||
flush status;
|
||||
create table t1(id int) engine=ndbcluster;
|
||||
create table t2(id int, b char(255)) engine=ndbcluster;
|
||||
create table t3(id int, c char(255)) engine=ndbcluster;
|
||||
create table t4(id int) engine=myisam;
|
||||
insert into t1 values (1);
|
||||
insert into t2 values (2, "table 2");
|
||||
insert into t3 values (3, "ndb table 3");
|
||||
insert into t4 values (4);
|
||||
flush tables;
|
||||
select * from t1, t2, t3, t4;
|
||||
id id b id c id
|
||||
1 2 table 2 3 ndb table 3 4
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 3
|
||||
drop table t1, t2, t3, t4;
|
||||
flush status;
|
||||
show status like 'handler_discover%';
|
||||
Variable_name Value
|
||||
Handler_discover 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
-- source include/have_ndb.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t9;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
--enable_warnings
|
||||
|
||||
################################################
|
||||
@ -122,7 +122,6 @@ create table t3(
|
||||
# IF NOT EXISTS wasn't specified
|
||||
|
||||
show status like 'handler_discover%';
|
||||
SHOW TABLES FROM test;
|
||||
|
||||
# now it should be discovered
|
||||
create table IF NOT EXISTS t3(
|
||||
@ -145,38 +144,226 @@ show status like 'handler_discover%';
|
||||
|
||||
drop table t3;
|
||||
|
||||
#######################################################
|
||||
# Test that a table that already exists as frm file
|
||||
# but not in NDB can be deleted from disk.
|
||||
##################################################
|
||||
# Test that a table that already exists in NDB
|
||||
# is discovered when SHOW TABLES
|
||||
# is used
|
||||
#
|
||||
|
||||
# Manual test
|
||||
#flush status;
|
||||
#
|
||||
#create table t4(
|
||||
# id int not null primary key,
|
||||
# name char(27)
|
||||
#) engine=ndb;
|
||||
#insert into t4 values (1, "Automatic");
|
||||
#select * from t4;
|
||||
flush status;
|
||||
|
||||
create table t7(
|
||||
id int not null primary key,
|
||||
name char(255)
|
||||
) engine=ndb;
|
||||
create table t6(
|
||||
id int not null primary key,
|
||||
name char(255)
|
||||
) engine=MyISAM;
|
||||
insert into t7 values (1, "Explorer");
|
||||
insert into t6 values (2, "MyISAM table");
|
||||
select * from t7;
|
||||
show status like 'handler_discover%';
|
||||
|
||||
# Remove the frm file from disk
|
||||
flush tables;
|
||||
system rm var/master-data/test/t7.frm ;
|
||||
|
||||
show tables from test;
|
||||
show status like 'handler_discover%';
|
||||
|
||||
# Remove the frm file from disk again
|
||||
flush tables;
|
||||
system rm var/master-data/test/t7.frm ;
|
||||
|
||||
--replace_column 7 # 8 # 9 # 12 # 13 # 15 #
|
||||
show table status;
|
||||
show status like 'handler_discover%';
|
||||
|
||||
drop table t6, t7;
|
||||
|
||||
|
||||
#######################################################
|
||||
# Test that a table that has been dropped from NDB
|
||||
# but still exists on disk, get a consistent error message
|
||||
# saying "No such table existed"
|
||||
#
|
||||
|
||||
flush status;
|
||||
|
||||
create table t4(
|
||||
id int not null primary key,
|
||||
name char(27)
|
||||
) engine=ndb;
|
||||
insert into t4 values (1, "Automatic");
|
||||
select * from t4;
|
||||
|
||||
# Remove the table from NDB
|
||||
#system drop_tab -c "$NDB_CONNECTSTRING2" -d test t4 > /dev/null ;
|
||||
#system drop_tab -c "host=localhost:2200;nodeid=5" -d test t4 > /dev/null ;
|
||||
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ;
|
||||
|
||||
#
|
||||
#--error 1296
|
||||
#select * from t4;
|
||||
# Test that correct error is returned
|
||||
--error 1146
|
||||
select * from t4;
|
||||
--error 1146
|
||||
select * from t4;
|
||||
|
||||
show status like 'handler_discover%';
|
||||
drop table t4;
|
||||
|
||||
|
||||
#######################################################
|
||||
# Test that a table that has been dropped from NDB
|
||||
# but still exists on disk is deleted from disk
|
||||
# when SHOW TABLES is called
|
||||
#
|
||||
#flush table t4;
|
||||
#--error 1016
|
||||
#select * from t4;
|
||||
|
||||
flush status;
|
||||
|
||||
create table t4(
|
||||
id int not null primary key,
|
||||
id2 int,
|
||||
name char(27)
|
||||
) engine=ndb;
|
||||
insert into t4 values (1, 76, "Automatic2");
|
||||
select * from t4;
|
||||
flush tables;
|
||||
|
||||
# Remove the table from NDB
|
||||
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ;
|
||||
|
||||
SHOW TABLES;
|
||||
|
||||
--error 1146
|
||||
select * from t4;
|
||||
|
||||
#######################################################
|
||||
# Test SHOW TABLES ability to detect new and delete old
|
||||
# tables. Test all at once using many tables
|
||||
#
|
||||
#show status like 'handler_discover%';
|
||||
#drop table t4;
|
||||
#flush tables;
|
||||
#show tables;
|
||||
#--error 1146
|
||||
#select * from t4;
|
||||
|
||||
flush status;
|
||||
|
||||
# Create tables
|
||||
create table t1(id int) engine=ndbcluster;
|
||||
create table t2(id int, b char(255)) engine=myisam;
|
||||
create table t3(id int, c char(255)) engine=ndbcluster;
|
||||
create table t4(id int) engine=myisam;
|
||||
create table t5(id int, d char(56)) engine=ndbcluster;
|
||||
create table t6(id int) engine=ndbcluster;
|
||||
create table t7(id int) engine=ndbcluster;
|
||||
create table t8(id int, e char(34)) engine=myisam;
|
||||
create table t9(id int) engine=myisam;
|
||||
|
||||
# Populate tables
|
||||
insert into t2 values (2, "myisam table 2");
|
||||
insert into t3 values (3, "ndb table 3");
|
||||
insert into t5 values (5, "ndb table 5");
|
||||
insert into t6 values (6);
|
||||
insert into t8 values (8, "myisam table 8");
|
||||
insert into t9 values (9);
|
||||
|
||||
# Remove t3, t5 from NDB
|
||||
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t3 > /dev/null ;
|
||||
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t5 > /dev/null ;
|
||||
# Remove t6, t7 from disk
|
||||
system rm var/master-data/test/t6.frm > /dev/null ;
|
||||
system rm var/master-data/test/t7.frm > /dev/null ;
|
||||
|
||||
SHOW TABLES;
|
||||
|
||||
select * from t6;
|
||||
select * from t7;
|
||||
|
||||
show status like 'handler_discover%';
|
||||
|
||||
drop table t1, t2, t4, t6, t7, t8, t9;
|
||||
|
||||
#######################################################
|
||||
# Test SHOW TABLES LIKE ability to detect new and delete old
|
||||
# tables. Test all at once using many tables.
|
||||
#
|
||||
|
||||
flush status;
|
||||
|
||||
# Create tables
|
||||
create table t1(id int) engine=ndbcluster;
|
||||
create table t2(id int, b char(255)) engine=myisam;
|
||||
create table t3(id int, c char(255)) engine=ndbcluster;
|
||||
create table t4(id int) engine=myisam;
|
||||
create table t5(id int, d char(56)) engine=ndbcluster;
|
||||
create table t6(id int) engine=ndbcluster;
|
||||
create table t7(id int) engine=ndbcluster;
|
||||
create table t8(id int, e char(34)) engine=myisam;
|
||||
create table t9(id int) engine=myisam;
|
||||
|
||||
# Populate tables
|
||||
insert into t2 values (2, "myisam table 2");
|
||||
insert into t3 values (3, "ndb table 3");
|
||||
insert into t5 values (5, "ndb table 5");
|
||||
insert into t6 values (6);
|
||||
insert into t8 values (8, "myisam table 8");
|
||||
insert into t9 values (9);
|
||||
|
||||
# Remove t3, t5 from NDB
|
||||
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t3 > /dev/null ;
|
||||
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t5 > /dev/null ;
|
||||
# Remove t6, t7 from disk
|
||||
system rm var/master-data/test/t6.frm > /dev/null ;
|
||||
system rm var/master-data/test/t7.frm > /dev/null ;
|
||||
|
||||
|
||||
SHOW TABLES LIKE 't6';
|
||||
|
||||
show status like 'handler_discover%';
|
||||
|
||||
# Check that t3 or t5 can't be created
|
||||
# frm files for these tables is stilll on disk
|
||||
--error 1050
|
||||
create table t3(a int);
|
||||
--error 1050
|
||||
create table t5(a int);
|
||||
|
||||
SHOW TABLES LIKE 't%';
|
||||
|
||||
show status like 'handler_discover%';
|
||||
|
||||
drop table t1, t2, t4, t6, t7, t8, t9;
|
||||
|
||||
|
||||
|
||||
######################################################
|
||||
# Test that several tables can be discovered when
|
||||
# one statement access several table at once.
|
||||
#
|
||||
|
||||
flush status;
|
||||
|
||||
# Create tables
|
||||
create table t1(id int) engine=ndbcluster;
|
||||
create table t2(id int, b char(255)) engine=ndbcluster;
|
||||
create table t3(id int, c char(255)) engine=ndbcluster;
|
||||
create table t4(id int) engine=myisam;
|
||||
|
||||
# Populate tables
|
||||
insert into t1 values (1);
|
||||
insert into t2 values (2, "table 2");
|
||||
insert into t3 values (3, "ndb table 3");
|
||||
insert into t4 values (4);
|
||||
|
||||
# Remove t1, t2, t3 from disk
|
||||
system rm var/master-data/test/t1.frm > /dev/null ;
|
||||
system rm var/master-data/test/t2.frm > /dev/null ;
|
||||
system rm var/master-data/test/t3.frm > /dev/null ;
|
||||
flush tables;
|
||||
|
||||
# Select from the table which only exists in NDB.
|
||||
select * from t1, t2, t3, t4;
|
||||
|
||||
# 3 table should have been discovered
|
||||
show status like 'handler_discover%';
|
||||
|
||||
drop table t1, t2, t3, t4;
|
||||
|
||||
|
||||
#########################################################
|
||||
@ -241,7 +428,6 @@ show status like 'handler_discover%';
|
||||
drop table t6;
|
||||
|
||||
######################################################
|
||||
# Simple test to show use of discover on startup
|
||||
# Note! This should always be the last step in this
|
||||
# file, the table t9 will be used and dropped
|
||||
# by ndb_autodiscover2
|
||||
@ -259,9 +445,7 @@ system rm var/master-data/test/t9.frm ;
|
||||
|
||||
# Now leave test case, when ndb_autodiscover2 will run, this
|
||||
# MySQL Server will have been restarted because it has a
|
||||
# ndb_autodiscover2-master.opt file. And thus the table should
|
||||
# have been discovered by the "discover on startup" function.
|
||||
# ndb_autodiscover2-master.opt file.
|
||||
|
||||
|
||||
|
||||
#TODO
|
||||
#SLECT * FROM t1, t2, t4;
|
||||
#handler discover 3;
|
||||
|
@ -1,14 +1,16 @@
|
||||
-- source include/have_ndb.inc
|
||||
|
||||
#
|
||||
# Simple test to show use of discover on startup
|
||||
# Simple test to show use of discover when the server has been restarted
|
||||
# The previous step has simply removed the frm file
|
||||
# from disk, but left the table in NDB
|
||||
#
|
||||
--sleep 3;
|
||||
select * from t9 order by a;
|
||||
|
||||
# handler_discover should be zero
|
||||
# handler_discover should be 1
|
||||
show status like 'handler_discover%';
|
||||
|
||||
drop table t9;
|
||||
|
||||
|
||||
|
@ -1087,8 +1087,6 @@ public:
|
||||
|
||||
int waitUntilReady(int timeout = 60);
|
||||
|
||||
void connected(Uint32 block_reference);
|
||||
|
||||
/** @} *********************************************************************/
|
||||
|
||||
/**
|
||||
@ -1447,6 +1445,9 @@ private:
|
||||
void setup(Ndb_cluster_connection *ndb_cluster_connection,
|
||||
const char* aCatalogName, const char* aSchemaName);
|
||||
|
||||
void connected(Uint32 block_reference);
|
||||
|
||||
|
||||
NdbConnection* startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId);
|
||||
|
||||
// Connect the connection object to the Database.
|
||||
|
@ -868,6 +868,8 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
|
||||
const int noerrcodes,
|
||||
const int temporaryMask)
|
||||
{
|
||||
DBUG_ENTER("NdbDictInterface::dictSignal");
|
||||
DBUG_PRINT("enter", ("useMasterNodeId: %d", useMasterNodeId));
|
||||
for(Uint32 i = 0; i<RETRIES; i++){
|
||||
//if (useMasterNodeId == 0)
|
||||
m_buffer.clear();
|
||||
@ -887,7 +889,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
|
||||
if(aNodeId == 0){
|
||||
m_error.code = 4009;
|
||||
m_transporter->unlock_mutex();
|
||||
return -1;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
{
|
||||
int r;
|
||||
@ -923,7 +925,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
|
||||
|
||||
if(m_waiter.m_state == NO_WAIT && m_error.code == 0){
|
||||
// Normal return
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -946,9 +948,9 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
|
||||
continue;
|
||||
}
|
||||
|
||||
return -1;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
return -1;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@ -942,6 +942,8 @@ TransporterFacade::isConnected(NodeId aNodeId){
|
||||
NodeId
|
||||
TransporterFacade::get_an_alive_node()
|
||||
{
|
||||
DBUG_ENTER("TransporterFacade::get_an_alive_node");
|
||||
DBUG_PRINT("enter", ("theStartNodeId: %d", theStartNodeId));
|
||||
#ifdef VM_TRACE
|
||||
const char* p = NdbEnv_GetEnv("NDB_ALIVE_NODE_ID", (char*)0, 0);
|
||||
if (p != 0 && *p != 0)
|
||||
@ -950,17 +952,19 @@ TransporterFacade::get_an_alive_node()
|
||||
NodeId i;
|
||||
for (i = theStartNodeId; i < MAX_NDB_NODES; i++) {
|
||||
if (get_node_alive(i)){
|
||||
DBUG_PRINT("info", ("Node %d is alive", i));
|
||||
theStartNodeId = ((i + 1) % MAX_NDB_NODES);
|
||||
return i;
|
||||
DBUG_RETURN(i);
|
||||
}
|
||||
}
|
||||
for (i = 1; i < theStartNodeId; i++) {
|
||||
if (get_node_alive(i)){
|
||||
DBUG_PRINT("info", ("Node %d is alive", i));
|
||||
theStartNodeId = ((i + 1) % MAX_NDB_NODES);
|
||||
return i;
|
||||
DBUG_RETURN(i);
|
||||
}
|
||||
}
|
||||
return (NodeId)0;
|
||||
DBUG_RETURN((NodeId)0);
|
||||
}
|
||||
|
||||
TransporterFacade::ThreadData::ThreadData(Uint32 size){
|
||||
|
@ -67,6 +67,9 @@ void Ndb_cluster_connection::connect_thread()
|
||||
printf("Ndb_cluster_connection::connect_thread error\n");
|
||||
DBUG_ASSERT(false);
|
||||
g_run_connect_thread= 0;
|
||||
} else {
|
||||
// Wait before making a new connect attempt
|
||||
NdbSleep_SecSleep(1);
|
||||
}
|
||||
} while (g_run_connect_thread);
|
||||
if (m_connect_callback)
|
||||
|
@ -125,47 +125,4 @@ int writefrm(const char *name, const void *frmdata, uint len)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Try to discover table from handler and
|
||||
if found, write the frm file to disk.
|
||||
|
||||
RETURN VALUES:
|
||||
0 : Table existed in handler and created
|
||||
on disk if so requested
|
||||
1 : Table does not exist
|
||||
>1 : error
|
||||
|
||||
*/
|
||||
|
||||
int create_table_from_handler(const char *db,
|
||||
const char *name,
|
||||
bool create_if_found)
|
||||
{
|
||||
int error= 0;
|
||||
const void* frmblob = NULL;
|
||||
char path[FN_REFLEN];
|
||||
uint frmlen = 0;
|
||||
DBUG_ENTER("create_table_from_handler");
|
||||
DBUG_PRINT("enter", ("create_if_found: %d", create_if_found));
|
||||
|
||||
if (ha_discover(db, name, &frmblob, &frmlen))
|
||||
DBUG_RETURN(1); // Table does not exist
|
||||
|
||||
// Table exists in handler
|
||||
if (create_if_found)
|
||||
{
|
||||
(void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS);
|
||||
// Save the frm file
|
||||
error = writefrm(path, frmblob, frmlen);
|
||||
}
|
||||
|
||||
if (frmblob)
|
||||
my_free((char*) frmblob,MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
int table_exists_in_handler(const char *db,
|
||||
const char *name)
|
||||
{
|
||||
return (create_table_from_handler(db, name, false) == 0);
|
||||
}
|
||||
|
@ -32,9 +32,6 @@
|
||||
#include <ndbapi/NdbApi.hpp>
|
||||
#include <ndbapi/NdbScanFilter.hpp>
|
||||
|
||||
#define USE_DISCOVER_ON_STARTUP
|
||||
//#define USE_NDB_POOL
|
||||
|
||||
// Default value for parallelism
|
||||
static const int parallelism= 240;
|
||||
|
||||
@ -48,11 +45,13 @@ static const ha_rows autoincrement_prefetch= 32;
|
||||
// connectstring to cluster if given by mysqld
|
||||
const char *ndbcluster_connectstring= 0;
|
||||
|
||||
static const char *ha_ndb_ext=".ndb";
|
||||
|
||||
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8
|
||||
|
||||
|
||||
#define ERR_PRINT(err) \
|
||||
DBUG_PRINT("error", ("Error: %d message: %s", err.code, err.message))
|
||||
DBUG_PRINT("error", ("%d message: %s", err.code, err.message))
|
||||
|
||||
#define ERR_RETURN(err) \
|
||||
{ \
|
||||
@ -107,7 +106,9 @@ static const err_code_mapping err_map[]=
|
||||
{ 893, HA_ERR_FOUND_DUPP_UNIQUE },
|
||||
{ 721, HA_ERR_TABLE_EXIST },
|
||||
{ 4244, HA_ERR_TABLE_EXIST },
|
||||
{ 241, HA_ERR_OLD_METADATA },
|
||||
|
||||
{ 709, HA_ERR_NO_SUCH_TABLE },
|
||||
{ 284, HA_ERR_NO_SUCH_TABLE },
|
||||
|
||||
{ 266, HA_ERR_LOCK_WAIT_TIMEOUT },
|
||||
{ 274, HA_ERR_LOCK_WAIT_TIMEOUT },
|
||||
@ -286,6 +287,7 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
|
||||
NDBDICT *dict= m_ndb->getDictionary();
|
||||
DBUG_PRINT("info", ("invalidateTable %s", m_tabname));
|
||||
dict->invalidateTable(m_tabname);
|
||||
table->version=0L; /* Free when thread is ready */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -326,7 +328,8 @@ bool ha_ndbcluster::get_error_message(int error,
|
||||
|
||||
/*
|
||||
Check if type is supported by NDB.
|
||||
TODO Use this once, not in every operation
|
||||
TODO Use this once in open(), not in every operation
|
||||
|
||||
*/
|
||||
|
||||
static inline bool ndb_supported_type(enum_field_types type)
|
||||
@ -671,7 +674,7 @@ int ha_ndbcluster::get_metadata(const char *path)
|
||||
memcmp(pack_data, tab->getFrmData(), pack_length)));
|
||||
DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
|
||||
DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
|
||||
error= HA_ERR_OLD_METADATA;
|
||||
error= 3;
|
||||
invalidating_ndb_table= false;
|
||||
}
|
||||
}
|
||||
@ -2660,7 +2663,7 @@ int ha_ndbcluster::reset()
|
||||
|
||||
|
||||
const char **ha_ndbcluster::bas_ext() const
|
||||
{ static const char *ext[1]= { NullS }; return ext; }
|
||||
{ static const char *ext[]= { ".ndb", NullS }; return ext; }
|
||||
|
||||
|
||||
/*
|
||||
@ -2857,18 +2860,26 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
|
||||
}
|
||||
m_table= NULL;
|
||||
m_table_info= NULL;
|
||||
if (m_active_trans)
|
||||
DBUG_PRINT("warning", ("m_active_trans != NULL"));
|
||||
/*
|
||||
This is the place to make sure this handler instance
|
||||
no longer are connected to the active transaction.
|
||||
|
||||
And since the handler is no longer part of the transaction
|
||||
it can't have open cursors, ops or blobs pending.
|
||||
*/
|
||||
m_active_trans= NULL;
|
||||
|
||||
if (m_active_cursor)
|
||||
DBUG_PRINT("warning", ("m_active_cursor != NULL"));
|
||||
m_active_cursor= NULL;
|
||||
|
||||
if (blobs_pending)
|
||||
DBUG_PRINT("warning", ("blobs_pending != 0"));
|
||||
blobs_pending= 0;
|
||||
|
||||
if (ops_pending)
|
||||
DBUG_PRINT("warning", ("ops_pending != 0L"));
|
||||
m_active_trans= NULL;
|
||||
m_active_cursor= NULL;
|
||||
ops_pending= 0;
|
||||
blobs_pending= 0;
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -3179,6 +3190,7 @@ int ha_ndbcluster::create(const char *name,
|
||||
const void *data, *pack_data;
|
||||
const char **key_names= form->keynames.type_names;
|
||||
char name2[FN_HEADLEN];
|
||||
bool create_from_engine= (info->table_options & HA_CREATE_FROM_ENGINE);
|
||||
|
||||
DBUG_ENTER("create");
|
||||
DBUG_PRINT("enter", ("name: %s", name));
|
||||
@ -3186,6 +3198,17 @@ int ha_ndbcluster::create(const char *name,
|
||||
set_dbname(name2);
|
||||
set_tabname(name2);
|
||||
|
||||
if (create_from_engine)
|
||||
{
|
||||
/*
|
||||
Table alreay exists in NDB and frm file has been created by
|
||||
caller.
|
||||
Do Ndb specific stuff, such as create a .ndb file
|
||||
*/
|
||||
my_errno= write_ndb_file();
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
|
||||
DBUG_PRINT("table", ("name: %s", m_tabname));
|
||||
tab.setName(m_tabname);
|
||||
tab.setLogging(!(info->options & HA_LEX_CREATE_TMP_TABLE));
|
||||
@ -3225,16 +3248,12 @@ int ha_ndbcluster::create(const char *name,
|
||||
tab.addColumn(col);
|
||||
}
|
||||
|
||||
my_errno= 0;
|
||||
if (check_ndb_connection())
|
||||
{
|
||||
my_errno= HA_ERR_NO_CONNECTION;
|
||||
if ((my_errno= check_ndb_connection()))
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
|
||||
// Create the table in NDB
|
||||
NDBDICT *dict= m_ndb->getDictionary();
|
||||
if (dict->createTable(tab))
|
||||
if (dict->createTable(tab) != 0)
|
||||
{
|
||||
const NdbError err= dict->getNdbError();
|
||||
ERR_PRINT(err);
|
||||
@ -3247,6 +3266,9 @@ int ha_ndbcluster::create(const char *name,
|
||||
// Create secondary indexes
|
||||
my_errno= build_index_list(form, ILBP_CREATE);
|
||||
|
||||
if (!my_errno)
|
||||
my_errno= write_ndb_file();
|
||||
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
|
||||
@ -3323,14 +3345,16 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
|
||||
set_tabname(from);
|
||||
set_tabname(to, new_tabname);
|
||||
|
||||
if (check_ndb_connection()) {
|
||||
my_errno= HA_ERR_NO_CONNECTION;
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
if (check_ndb_connection())
|
||||
DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION);
|
||||
|
||||
|
||||
int result= alter_table_name(m_tabname, new_tabname);
|
||||
if (result == 0)
|
||||
{
|
||||
set_tabname(to);
|
||||
handler::rename_table(from, to);
|
||||
}
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
@ -3375,6 +3399,8 @@ int ha_ndbcluster::delete_table(const char *name)
|
||||
|
||||
if (check_ndb_connection())
|
||||
DBUG_RETURN(HA_ERR_NO_CONNECTION);
|
||||
|
||||
handler::delete_table(name);
|
||||
DBUG_RETURN(drop_table());
|
||||
}
|
||||
|
||||
@ -3570,13 +3596,7 @@ Thd_ndb* ha_ndbcluster::seize_thd_ndb()
|
||||
Thd_ndb *thd_ndb;
|
||||
DBUG_ENTER("seize_thd_ndb");
|
||||
|
||||
#ifdef USE_NDB_POOL
|
||||
// Seize from pool
|
||||
ndb= Ndb::seize();
|
||||
xxxxxxxxxxxxxx error
|
||||
#else
|
||||
thd_ndb= new Thd_ndb();
|
||||
#endif
|
||||
thd_ndb->ndb->getDictionary()->set_local_table_data_size(sizeof(Ndb_table_local_info));
|
||||
if (thd_ndb->ndb->init(max_transactions) != 0)
|
||||
{
|
||||
@ -3597,46 +3617,45 @@ Thd_ndb* ha_ndbcluster::seize_thd_ndb()
|
||||
void ha_ndbcluster::release_thd_ndb(Thd_ndb* thd_ndb)
|
||||
{
|
||||
DBUG_ENTER("release_thd_ndb");
|
||||
#ifdef USE_NDB_POOL
|
||||
// Release to pool
|
||||
Ndb::release(ndb);
|
||||
xxxxxxxxxxxx error
|
||||
#else
|
||||
delete thd_ndb;
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
If this thread already has a Ndb object allocated
|
||||
If this thread already has a Thd_ndb object allocated
|
||||
in current THD, reuse it. Otherwise
|
||||
seize a Ndb object, assign it to current THD and use it.
|
||||
|
||||
Having a Ndb object also means that a connection to
|
||||
NDB cluster has been opened. The connection is
|
||||
checked.
|
||||
seize a Thd_ndb object, assign it to current THD and use it.
|
||||
|
||||
*/
|
||||
|
||||
int ha_ndbcluster::check_ndb_connection()
|
||||
Ndb* check_ndb_in_thd(THD* thd)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
DBUG_ENTER("check_ndb_in_thd");
|
||||
Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
|
||||
DBUG_ENTER("check_ndb_connection");
|
||||
|
||||
if (!thd_ndb)
|
||||
{
|
||||
thd_ndb= seize_thd_ndb();
|
||||
if (!thd_ndb)
|
||||
DBUG_RETURN(2);
|
||||
if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb()))
|
||||
DBUG_RETURN(NULL);
|
||||
thd->transaction.thd_ndb= thd_ndb;
|
||||
}
|
||||
m_ndb= thd_ndb->ndb;
|
||||
DBUG_RETURN(thd_ndb->ndb);
|
||||
}
|
||||
|
||||
|
||||
int ha_ndbcluster::check_ndb_connection()
|
||||
{
|
||||
THD* thd= current_thd;
|
||||
DBUG_ENTER("check_ndb_connection");
|
||||
|
||||
if (!(m_ndb= check_ndb_in_thd(thd)))
|
||||
DBUG_RETURN(HA_ERR_NO_CONNECTION);
|
||||
m_ndb->setDatabaseName(m_dbname);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
void ndbcluster_close_connection(THD *thd)
|
||||
{
|
||||
Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
|
||||
@ -3654,28 +3673,29 @@ void ndbcluster_close_connection(THD *thd)
|
||||
Try to discover one table from NDB
|
||||
*/
|
||||
|
||||
int ndbcluster_discover(const char *dbname, const char *name,
|
||||
int ndbcluster_discover(THD* thd, const char *db, const char *name,
|
||||
const void** frmblob, uint* frmlen)
|
||||
{
|
||||
uint len;
|
||||
const void* data;
|
||||
const NDBTAB* tab;
|
||||
Ndb* ndb;
|
||||
DBUG_ENTER("ndbcluster_discover");
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", dbname, name));
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
|
||||
|
||||
Ndb ndb(g_ndb_cluster_connection, dbname);
|
||||
ndb.getDictionary()->set_local_table_data_size(sizeof(Ndb_table_local_info));
|
||||
if (!(ndb= check_ndb_in_thd(thd)))
|
||||
DBUG_RETURN(HA_ERR_NO_CONNECTION);
|
||||
ndb->setDatabaseName(db);
|
||||
|
||||
if (ndb.init())
|
||||
ERR_RETURN(ndb.getNdbError());
|
||||
|
||||
if (ndb.waitUntilReady(0))
|
||||
ERR_RETURN(ndb.getNdbError());
|
||||
|
||||
if (!(tab= ndb.getDictionary()->getTable(name)))
|
||||
NDBDICT* dict= ndb->getDictionary();
|
||||
dict->set_local_table_data_size(sizeof(Ndb_table_local_info));
|
||||
dict->invalidateTable(name);
|
||||
if (!(tab= dict->getTable(name)))
|
||||
{
|
||||
DBUG_PRINT("info", ("Table %s not found", name));
|
||||
DBUG_RETURN(1);
|
||||
const NdbError err= dict->getNdbError();
|
||||
if (err.code == 709)
|
||||
DBUG_RETURN(1);
|
||||
ERR_RETURN(err);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("Found table %s", tab->getName()));
|
||||
@ -3697,41 +3717,196 @@ int ndbcluster_discover(const char *dbname, const char *name,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_DISCOVER_ON_STARTUP
|
||||
/*
|
||||
Dicover tables from NDB Cluster
|
||||
- fetch a list of tables from NDB
|
||||
- store the frm file for each table on disk
|
||||
- if the table has an attached frm file
|
||||
- if the database of the table exists
|
||||
*/
|
||||
Check if a table exists in NDB
|
||||
|
||||
int ndb_discover_tables()
|
||||
*/
|
||||
|
||||
int ndbcluster_table_exists(THD* thd, const char *db, const char *name)
|
||||
{
|
||||
uint len;
|
||||
const void* data;
|
||||
const NDBTAB* tab;
|
||||
Ndb* ndb;
|
||||
DBUG_ENTER("ndbcluster_table_exists");
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
|
||||
|
||||
if (!(ndb= check_ndb_in_thd(thd)))
|
||||
DBUG_RETURN(HA_ERR_NO_CONNECTION);
|
||||
ndb->setDatabaseName(db);
|
||||
|
||||
NDBDICT* dict= ndb->getDictionary();
|
||||
dict->set_local_table_data_size(sizeof(Ndb_table_local_info));
|
||||
dict->invalidateTable(name);
|
||||
if (!(tab= dict->getTable(name)))
|
||||
{
|
||||
const NdbError err= dict->getNdbError();
|
||||
if (err.code == 709)
|
||||
DBUG_RETURN(0);
|
||||
ERR_RETURN(err);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("Found table %s", tab->getName()));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" byte* tables_get_key(const char *entry, uint *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
{
|
||||
*length= strlen(entry);
|
||||
return (byte*) entry;
|
||||
}
|
||||
|
||||
|
||||
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
|
||||
const char *wild, bool dir, List<char> *files)
|
||||
{
|
||||
uint i;
|
||||
Ndb* ndb;
|
||||
char name[FN_REFLEN];
|
||||
HASH ndb_tables, ok_tables;
|
||||
NdbDictionary::Dictionary::List list;
|
||||
NdbDictionary::Dictionary* dict;
|
||||
char path[FN_REFLEN];
|
||||
DBUG_ENTER("ndb_discover_tables");
|
||||
DBUG_ENTER("ndbcluster_find_files");
|
||||
DBUG_PRINT("enter", ("db: %s", db));
|
||||
|
||||
/* List tables in NDB Cluster kernel */
|
||||
dict= g_ndb->getDictionary();
|
||||
if (!(ndb= check_ndb_in_thd(thd)))
|
||||
DBUG_RETURN(HA_ERR_NO_CONNECTION);
|
||||
|
||||
if (dir)
|
||||
DBUG_RETURN(0); // Discover of databases not yet supported
|
||||
|
||||
// List tables in NDB
|
||||
NDBDICT *dict= ndb->getDictionary();
|
||||
if (dict->listObjects(list,
|
||||
NdbDictionary::Object::UserTable) != 0)
|
||||
ERR_RETURN(dict->getNdbError());
|
||||
|
||||
if (hash_init(&ndb_tables, system_charset_info,list.count,0,0,
|
||||
(hash_get_key)tables_get_key,0,0))
|
||||
{
|
||||
DBUG_PRINT("error", ("Failed to init HASH ndb_tables"));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
if (hash_init(&ok_tables, system_charset_info,32,0,0,
|
||||
(hash_get_key)tables_get_key,0,0))
|
||||
{
|
||||
DBUG_PRINT("error", ("Failed to init HASH ok_tables"));
|
||||
hash_free(&ndb_tables);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
for (i= 0 ; i < list.count ; i++)
|
||||
{
|
||||
NdbDictionary::Dictionary::List::Element& t= list.elements[i];
|
||||
DBUG_PRINT("info", ("Found %s/%s in NDB", t.database, t.name));
|
||||
|
||||
DBUG_PRINT("discover", ("%d: %s/%s", t.id, t.database, t.name));
|
||||
if (create_table_from_handler(t.database, t.name, true))
|
||||
DBUG_PRINT("info", ("Could not discover %s/%s", t.database, t.name));
|
||||
// Apply wildcard to list of tables in NDB
|
||||
if (wild)
|
||||
{
|
||||
if (lower_case_table_names)
|
||||
{
|
||||
if (wild_case_compare(files_charset_info, t.name, wild))
|
||||
continue;
|
||||
}
|
||||
else if (wild_compare(t.name,wild,0))
|
||||
continue;
|
||||
}
|
||||
DBUG_PRINT("info", ("Inserting %s into ndb_tables hash", t.name));
|
||||
my_hash_insert(&ndb_tables, (byte*)thd->strdup(t.name));
|
||||
}
|
||||
|
||||
char *file_name;
|
||||
List_iterator<char> it(*files);
|
||||
List<char> delete_list;
|
||||
while ((file_name=it++))
|
||||
{
|
||||
DBUG_PRINT("info", ("%s", file_name));
|
||||
if (hash_search(&ndb_tables, file_name, strlen(file_name)))
|
||||
{
|
||||
DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name));
|
||||
// File existed in NDB and as frm file, put in ok_tables list
|
||||
my_hash_insert(&ok_tables, (byte*)file_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// File is not in NDB, check for .ndb file with this name
|
||||
(void)strxnmov(name, FN_REFLEN,
|
||||
mysql_data_home,"/",db,"/",file_name,ha_ndb_ext,NullS);
|
||||
DBUG_PRINT("info", ("Check access for %s", name));
|
||||
if (access(name, F_OK))
|
||||
{
|
||||
DBUG_PRINT("info", ("%s did not exist on disk", name));
|
||||
// .ndb file did not exist on disk, another table type
|
||||
continue;
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("%s existed on disk", name));
|
||||
// The .ndb file exists on disk, but it's not in list of tables in ndb
|
||||
// Verify that handler agrees table is gone.
|
||||
if (ndbcluster_table_exists(thd, db, file_name) == 0)
|
||||
{
|
||||
DBUG_PRINT("info", ("NDB says %s does not exists", file_name));
|
||||
it.remove();
|
||||
// Put in list of tables to remove from disk
|
||||
delete_list.push_back(thd->strdup(file_name));
|
||||
}
|
||||
}
|
||||
|
||||
// Check for new files to discover
|
||||
DBUG_PRINT("info", ("Checking for new files to discover"));
|
||||
List<char> create_list;
|
||||
for (i= 0 ; i < ndb_tables.records ; i++)
|
||||
{
|
||||
file_name= hash_element(&ndb_tables, i);
|
||||
if (!hash_search(&ok_tables, file_name, strlen(file_name)))
|
||||
{
|
||||
DBUG_PRINT("info", ("%s must be discovered", file_name));
|
||||
// File is in list of ndb tables and not in ok_tables
|
||||
// This table need to be created
|
||||
create_list.push_back(thd->strdup(file_name));
|
||||
}
|
||||
}
|
||||
|
||||
// Lock mutex before deleting and creating frm files
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
|
||||
if (!global_read_lock)
|
||||
{
|
||||
// Delete old files
|
||||
List_iterator_fast<char> it3(delete_list);
|
||||
while ((file_name=it3++))
|
||||
{
|
||||
DBUG_PRINT("info", ("Remove table %s/%s",db, file_name ));
|
||||
// Delete the table and all related files
|
||||
TABLE_LIST table_list;
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
table_list.db= (char*) db;
|
||||
table_list.real_name=(char*)file_name;
|
||||
(void)mysql_rm_table_part2(thd, &table_list,
|
||||
/* if_exists */ true,
|
||||
/* drop_temporary */ false,
|
||||
/* dont_log_query*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
// Create new files
|
||||
List_iterator_fast<char> it2(create_list);
|
||||
while ((file_name=it2++))
|
||||
{
|
||||
DBUG_PRINT("info", ("Table %s need discovery", name));
|
||||
ha_create_table_from_engine(thd, db, file_name, true);
|
||||
files->push_back(thd->strdup(file_name));
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
hash_free(&ok_tables);
|
||||
hash_free(&ndb_tables);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@ -3786,7 +3961,7 @@ bool ndbcluster_init()
|
||||
|
||||
ndbcluster_inited= 1;
|
||||
#ifdef USE_DISCOVER_ON_STARTUP
|
||||
if (res == 0 && ndb_discover_tables() != 0)
|
||||
if (ndb_discover_tables() != 0)
|
||||
DBUG_RETURN(TRUE);
|
||||
#endif
|
||||
DBUG_RETURN(false);
|
||||
@ -3802,7 +3977,6 @@ bool ndbcluster_init()
|
||||
bool ndbcluster_end()
|
||||
{
|
||||
DBUG_ENTER("ndbcluster_end");
|
||||
|
||||
if(g_ndb)
|
||||
delete g_ndb;
|
||||
g_ndb= NULL;
|
||||
@ -3812,9 +3986,6 @@ bool ndbcluster_end()
|
||||
if (!ndbcluster_inited)
|
||||
DBUG_RETURN(0);
|
||||
hash_free(&ndbcluster_open_tables);
|
||||
#ifdef USE_NDB_POOL
|
||||
ndb_pool_release();
|
||||
#endif
|
||||
pthread_mutex_destroy(&ndbcluster_mutex);
|
||||
ndbcluster_inited= 0;
|
||||
DBUG_RETURN(0);
|
||||
@ -4173,4 +4344,30 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
Create a .ndb file to serve as a placeholder indicating
|
||||
that the table with this name is a ndb table
|
||||
*/
|
||||
|
||||
int ha_ndbcluster::write_ndb_file()
|
||||
{
|
||||
File file;
|
||||
bool error=1;
|
||||
char path[FN_REFLEN];
|
||||
|
||||
DBUG_ENTER("write_ndb_file");
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", m_dbname, m_tabname));
|
||||
|
||||
(void)strxnmov(path, FN_REFLEN,
|
||||
mysql_data_home,"/",m_dbname,"/",m_tabname,ha_ndb_ext,NullS);
|
||||
|
||||
if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
|
||||
{
|
||||
// It's an empty file
|
||||
error=0;
|
||||
my_close(file,MYF(0));
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
#endif /* HAVE_NDBCLUSTER_DB */
|
||||
|
@ -226,6 +226,8 @@ class ha_ndbcluster: public handler
|
||||
int ndb_err(NdbConnection*);
|
||||
bool uses_blob_value(bool all_fields);
|
||||
|
||||
int write_ndb_file();
|
||||
|
||||
private:
|
||||
int check_ndb_connection();
|
||||
|
||||
@ -276,8 +278,11 @@ int ndbcluster_rollback(THD *thd, void* ndb_transaction);
|
||||
|
||||
void ndbcluster_close_connection(THD *thd);
|
||||
|
||||
int ndbcluster_discover(const char* dbname, const char* name,
|
||||
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
|
||||
const void** frmblob, uint* frmlen);
|
||||
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
|
||||
const char *wild, bool dir, List<char> *files);
|
||||
int ndbcluster_table_exists(THD* thd, const char *db, const char *name);
|
||||
int ndbcluster_drop_database(const char* path);
|
||||
|
||||
void ndbcluster_print_error(int error, const NdbOperation *error_op);
|
||||
|
129
sql/handler.cc
129
sql/handler.cc
@ -1119,6 +1119,16 @@ void handler::print_error(int error, myf errflag)
|
||||
case HA_ERR_NO_REFERENCED_ROW:
|
||||
textno=ER_NO_REFERENCED_ROW;
|
||||
break;
|
||||
case HA_ERR_NO_SUCH_TABLE:
|
||||
{
|
||||
char *db;
|
||||
char buff[FN_REFLEN];
|
||||
uint length=dirname_part(buff,table->path);
|
||||
buff[length-1]=0;
|
||||
db=buff+dirname_length(buff);
|
||||
my_error(ER_NO_SUCH_TABLE,MYF(0),db,table->table_name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* The error was "unknown" to this function.
|
||||
@ -1265,6 +1275,71 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
|
||||
DBUG_RETURN(error != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
Try to discover table from engine and
|
||||
if found, write the frm file to disk.
|
||||
|
||||
RETURN VALUES:
|
||||
0 : Table existed in engine and created
|
||||
on disk if so requested
|
||||
1 : Table does not exist
|
||||
>1 : error
|
||||
|
||||
*/
|
||||
|
||||
int ha_create_table_from_engine(THD* thd,
|
||||
const char *db,
|
||||
const char *name,
|
||||
bool create_if_found)
|
||||
{
|
||||
int error= 0;
|
||||
const void* frmblob = NULL;
|
||||
uint frmlen = 0;
|
||||
char path[FN_REFLEN];
|
||||
HA_CREATE_INFO create_info;
|
||||
TABLE table;
|
||||
DBUG_ENTER("ha_create_table_from_engine");
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
|
||||
DBUG_PRINT("enter", ("create_if_found: %d", create_if_found));
|
||||
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
|
||||
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
|
||||
DBUG_RETURN(error);
|
||||
|
||||
// Table exists in handler
|
||||
if (create_if_found)
|
||||
{
|
||||
(void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS);
|
||||
// Save the frm file
|
||||
if ((error = writefrm(path, frmblob, frmlen)))
|
||||
goto err_end;
|
||||
|
||||
if (openfrm(path,"",0,(uint) READ_ALL, 0, &table))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
update_create_info_from_table(&create_info, &table);
|
||||
create_info.table_options|= HA_CREATE_FROM_ENGINE;
|
||||
|
||||
if (lower_case_table_names == 2 &&
|
||||
!(table.file->table_flags() & HA_FILE_BASED))
|
||||
{
|
||||
/* Ensure that handler gets name in lower case */
|
||||
strmov(path, name);
|
||||
my_casedn_str(files_charset_info, path);
|
||||
name= path;
|
||||
}
|
||||
|
||||
error=table.file->create(path,&table,&create_info);
|
||||
VOID(closefrm(&table));
|
||||
}
|
||||
|
||||
err_end:
|
||||
if (frmblob)
|
||||
my_free((char*) frmblob,MYF(0));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
|
||||
{
|
||||
char buff[FN_REFLEN];
|
||||
@ -1372,15 +1447,15 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache,
|
||||
Try to discover one table from handler(s)
|
||||
*/
|
||||
|
||||
int ha_discover(const char* dbname, const char* name,
|
||||
const void** frmblob, uint* frmlen)
|
||||
int ha_discover(THD* thd, const char* db, const char* name,
|
||||
const void** frmblob, uint* frmlen)
|
||||
{
|
||||
int error= 1; // Table does not exist in any handler
|
||||
DBUG_ENTER("ha_discover");
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", dbname, name));
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
|
||||
#ifdef HAVE_NDBCLUSTER_DB
|
||||
if (have_ndbcluster == SHOW_OPTION_YES)
|
||||
error= ndbcluster_discover(dbname, name, frmblob, frmlen);
|
||||
error= ndbcluster_discover(thd, db, name, frmblob, frmlen);
|
||||
#endif
|
||||
if (!error)
|
||||
statistic_increment(ha_discover_count,&LOCK_status);
|
||||
@ -1388,6 +1463,52 @@ int ha_discover(const char* dbname, const char* name,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Call this function in order to give the handler the possiblity
|
||||
to ask engine if there are any new tables that should be written to disk
|
||||
or any dropped tables that need to be removed from disk
|
||||
*/
|
||||
|
||||
int
|
||||
ha_find_files(THD *thd,const char *db,const char *path,
|
||||
const char *wild, bool dir, List<char> *files)
|
||||
{
|
||||
int error= 0;
|
||||
DBUG_ENTER("ha_find_files");
|
||||
DBUG_PRINT("enter", ("db: %s, path: %s, wild: %s, dir: %d",
|
||||
db, path, wild, dir));
|
||||
#ifdef HAVE_NDBCLUSTER_DB
|
||||
if (have_ndbcluster == SHOW_OPTION_YES)
|
||||
error= ndbcluster_find_files(thd, db, path, wild, dir, files);
|
||||
#endif
|
||||
DBUG_RETURN(error);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Ask handler if the table exists in engine
|
||||
|
||||
RETURN
|
||||
0 Table does not exist
|
||||
1 Table exists
|
||||
# Error code
|
||||
|
||||
*/
|
||||
int ha_table_exists(THD* thd, const char* db, const char* name)
|
||||
{
|
||||
int error= 2;
|
||||
DBUG_ENTER("ha_table_exists");
|
||||
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
|
||||
#ifdef HAVE_NDBCLUSTER_DB
|
||||
if (have_ndbcluster == SHOW_OPTION_YES)
|
||||
error= ndbcluster_table_exists(thd, db, name);
|
||||
#endif
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Read first row between two ranges.
|
||||
Store ranges for future calls to read_range_next
|
||||
|
@ -540,6 +540,8 @@ void ha_close_connection(THD* thd);
|
||||
enum db_type ha_checktype(enum db_type database_type);
|
||||
int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
|
||||
bool update_create_info);
|
||||
int ha_create_table_from_engine(THD* thd, const char *db, const char *name,
|
||||
bool create_if_found);
|
||||
int ha_delete_table(enum db_type db_type, const char *path);
|
||||
void ha_drop_database(char* path);
|
||||
int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
|
||||
@ -561,5 +563,10 @@ bool ha_flush_logs(void);
|
||||
int ha_enable_transaction(THD *thd, bool on);
|
||||
int ha_change_key_cache(KEY_CACHE *old_key_cache,
|
||||
KEY_CACHE *new_key_cache);
|
||||
int ha_discover(const char* dbname, const char* name,
|
||||
int ha_discover(THD* thd, const char* dbname, const char* name,
|
||||
const void** frmblob, uint* frmlen);
|
||||
int ha_find_files(THD *thd,const char *db,const char *path,
|
||||
const char *wild, bool dir,List<char>* files);
|
||||
int ha_table_exists(THD* thd, const char* db, const char* name);
|
||||
|
||||
|
||||
|
@ -1003,8 +1003,6 @@ int openfrm(const char *name,const char *alias,uint filestat,uint prgflag,
|
||||
uint ha_open_flags, TABLE *outparam);
|
||||
int readfrm(const char *name, const void** data, uint* length);
|
||||
int writefrm(const char* name, const void* data, uint len);
|
||||
int create_table_from_handler(const char *db, const char *name,
|
||||
bool create_if_found);
|
||||
int closefrm(TABLE *table);
|
||||
db_type get_table_type(const char *name);
|
||||
int read_string(File file, gptr *to, uint length);
|
||||
|
@ -1343,7 +1343,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
*/
|
||||
if (discover_retry_count++ != 0)
|
||||
goto err;
|
||||
if (create_table_from_handler(db, name, true) != 0)
|
||||
if (ha_create_table_from_engine(thd, db, name, true) != 0)
|
||||
goto err;
|
||||
|
||||
thd->clear_error(); // Clear error message
|
||||
|
@ -374,6 +374,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
|
||||
|
||||
if (wild && !wild[0])
|
||||
wild=0;
|
||||
|
||||
bzero((char*) &table_list,sizeof(table_list));
|
||||
|
||||
if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
|
||||
@ -445,6 +446,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
|
||||
}
|
||||
DBUG_PRINT("info",("found: %d files", files->elements));
|
||||
my_dirend(dirp);
|
||||
|
||||
VOID(ha_find_files(thd,db,path,wild,dir,files));
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS);
|
||||
(void) unpack_filename(path,path);
|
||||
}
|
||||
if (drop_temporary || access(path,F_OK))
|
||||
if (drop_temporary ||
|
||||
(access(path,F_OK) && ha_create_table_from_engine(thd,db,alias,true)))
|
||||
{
|
||||
if (if_exists)
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
@ -1243,8 +1244,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
{
|
||||
bool create_if_not_exists =
|
||||
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
|
||||
if (!create_table_from_handler(db, table_name,
|
||||
create_if_not_exists))
|
||||
if (!ha_create_table_from_engine(thd, db, table_name,
|
||||
create_if_not_exists))
|
||||
{
|
||||
DBUG_PRINT("info", ("Table already existed in handler"));
|
||||
|
||||
|
@ -705,6 +705,14 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
||||
outparam->crashed=((err == HA_ERR_CRASHED_ON_USAGE) &&
|
||||
outparam->file->auto_repair() &&
|
||||
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
|
||||
|
||||
if (err==HA_ERR_NO_SUCH_TABLE)
|
||||
{
|
||||
/* The table did not exists in storage engine, use same error message
|
||||
as if the .frm file didn't exist */
|
||||
error= 1;
|
||||
my_errno= ENOENT;
|
||||
}
|
||||
goto err_not_open; /* purecov: inspected */
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user