mirror of
https://github.com/MariaDB/server.git
synced 2025-05-02 19:25:03 +03:00
Re-applying the work initially done by Brian, and since worked upon by me previously in several separate patches to the 5.1 parent but never pushed.
WL#2952 - add simple single-table only transactions to federated. sql/ha_federated.cc: added handlerton functions for commit and rollback, added handler methods for same. sql/ha_federated.h: added member variable for transaction data (linked list of federated handlers used in transaction) and member functions for support commit and rollback. mysql-test/r/federated_transactions.result: New BitKeeper file ``mysql-test/r/federated_transactions.result'' mysql-test/t/federated_transactions.test: New BitKeeper file ``mysql-test/t/federated_transactions.test''
This commit is contained in:
parent
c4239fee21
commit
b582ea2bd4
49
mysql-test/r/federated_transactions.result
Normal file
49
mysql-test/r/federated_transactions.result
Normal file
@ -0,0 +1,49 @@
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
stop slave;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
CREATE DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
CREATE DATABASE federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(32) NOT NULL default ''
|
||||
)
|
||||
DEFAULT CHARSET=latin1 ENGINE=BerkeleyDB;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(32) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
|
||||
set autocommit=0;
|
||||
INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
|
||||
INSERT INTO federated.t1 (id, name) VALUES (2, 'fee');
|
||||
COMMIT;
|
||||
INSERT INTO federated.t1 (id, name) VALUES (3, 'fie');
|
||||
INSERT INTO federated.t1 (id, name) VALUES (4, 'fum');
|
||||
ROLLBACK;
|
||||
set autocommit=1;
|
||||
INSERT INTO federated.t1 (id, name) VALUES (5, 'foe');
|
||||
INSERT INTO federated.t1 (id, name) VALUES (6, 'fig');
|
||||
SELECT * FROM federated.t1;
|
||||
id name
|
||||
1 foo
|
||||
2 fee
|
||||
5 foe
|
||||
6 fig
|
||||
DELETE FROM federated.t1;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE IF EXISTS federated;
|
37
mysql-test/t/federated_transactions.test
Normal file
37
mysql-test/t/federated_transactions.test
Normal file
@ -0,0 +1,37 @@
|
||||
source include/federated.inc;
|
||||
|
||||
connection slave;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
#SHOW ENGINES;
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(32) NOT NULL default ''
|
||||
)
|
||||
DEFAULT CHARSET=latin1 ENGINE=BerkeleyDB;
|
||||
|
||||
connection master;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
# # correct connection, same named tables
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
eval CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(32) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
|
||||
|
||||
set autocommit=0;
|
||||
INSERT INTO federated.t1 (id, name) VALUES (1, 'foo');
|
||||
INSERT INTO federated.t1 (id, name) VALUES (2, 'fee');
|
||||
COMMIT;
|
||||
INSERT INTO federated.t1 (id, name) VALUES (3, 'fie');
|
||||
INSERT INTO federated.t1 (id, name) VALUES (4, 'fum');
|
||||
ROLLBACK;
|
||||
set autocommit=1;
|
||||
INSERT INTO federated.t1 (id, name) VALUES (5, 'foe');
|
||||
INSERT INTO federated.t1 (id, name) VALUES (6, 'fig');
|
||||
|
||||
SELECT * FROM federated.t1;
|
||||
DELETE FROM federated.t1;
|
||||
|
||||
source include/federated_cleanup.inc;
|
@ -363,9 +363,9 @@ static int federated_init= FALSE; // Variable for checking the
|
||||
// init state of hash
|
||||
|
||||
/* Static declaration for handerton */
|
||||
|
||||
static handler *federated_create_handler(TABLE *table);
|
||||
|
||||
static int federated_commit(THD *thd, bool all);
|
||||
static int federated_rollback(THD *thd, bool all);
|
||||
|
||||
/* Federated storage engine handlerton */
|
||||
|
||||
@ -381,8 +381,8 @@ handlerton federated_hton= {
|
||||
NULL, /* savepoint */
|
||||
NULL, /* rollback to savepoint */
|
||||
NULL, /* release savepoint */
|
||||
NULL, /* commit */
|
||||
NULL, /* rollback */
|
||||
federated_commit, /* commit */
|
||||
federated_rollback, /* rollback */
|
||||
NULL, /* prepare */
|
||||
NULL, /* recover */
|
||||
NULL, /* commit_by_xid */
|
||||
@ -647,8 +647,8 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
||||
|
||||
share->port= 0;
|
||||
share->socket= 0;
|
||||
DBUG_PRINT("info", ("Length %d \n", table->s->connect_string.length));
|
||||
DBUG_PRINT("info", ("String %.*s \n", table->s->connect_string.length,
|
||||
DBUG_PRINT("info", ("Length: %d", table->s->connect_string.length));
|
||||
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
|
||||
table->s->connect_string.str));
|
||||
share->scheme= my_strdup_with_length((const byte*)table->s->
|
||||
connect_string.str,
|
||||
@ -740,7 +740,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
||||
|
||||
DBUG_PRINT("info",
|
||||
("scheme %s username %s password %s \
|
||||
hostname %s port %d database %s tablename %s\n",
|
||||
hostname %s port %d database %s tablename %s",
|
||||
share->scheme, share->username, share->password,
|
||||
share->hostname, share->port, share->database,
|
||||
share->table_name));
|
||||
@ -760,7 +760,9 @@ ha_federated::ha_federated(TABLE *table_arg)
|
||||
:handler(&federated_hton, table_arg),
|
||||
mysql(0), stored_result(0), scan_flag(0),
|
||||
ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
|
||||
{}
|
||||
{
|
||||
trx_next= 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -1488,6 +1490,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
|
||||
with transactions
|
||||
*/
|
||||
mysql->reconnect= 1;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -2633,3 +2636,151 @@ bool ha_federated::get_error_message(int error, String* buf)
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
int ha_federated::external_lock(THD *thd, int lock_type)
|
||||
{
|
||||
int error= 0;
|
||||
ha_federated *trx= (ha_federated *)thd->ha_data[federated_hton.slot];
|
||||
DBUG_ENTER("ha_federated::external_lock");
|
||||
|
||||
if (lock_type != F_UNLCK)
|
||||
{
|
||||
DBUG_PRINT("info",("federated not lock F_UNLCK"));
|
||||
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
|
||||
{
|
||||
DBUG_PRINT("info",("federated autocommit"));
|
||||
/*
|
||||
This means we are doing an autocommit
|
||||
*/
|
||||
error= connection_autocommit(TRUE);
|
||||
if (error)
|
||||
{
|
||||
DBUG_PRINT("info", ("error setting autocommit TRUE: %d", error));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
trans_register_ha(thd, FALSE, &federated_hton);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info",("not autocommit"));
|
||||
if (!trx)
|
||||
{
|
||||
/*
|
||||
This is where a transaction gets its start
|
||||
*/
|
||||
error= connection_autocommit(FALSE);
|
||||
if (error)
|
||||
{
|
||||
DBUG_PRINT("info", ("error setting autocommit FALSE: %d", error));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
thd->ha_data[federated_hton.slot]= this;
|
||||
trans_register_ha(thd, TRUE, &federated_hton);
|
||||
/*
|
||||
Send a lock table to the remote end.
|
||||
We do not support this at the moment
|
||||
*/
|
||||
if (thd->options & (OPTION_TABLE_LOCK))
|
||||
{
|
||||
DBUG_PRINT("info", ("We do not support lock table yet"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ha_federated *ptr;
|
||||
for (ptr= trx; ptr; ptr= ptr->trx_next)
|
||||
if (ptr == this)
|
||||
break;
|
||||
else if (!ptr->trx_next)
|
||||
ptr->trx_next= this;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
static int federated_commit(THD *thd, bool all)
|
||||
{
|
||||
int return_val= 0;
|
||||
ha_federated *trx= (ha_federated *)thd->ha_data[federated_hton.slot];
|
||||
DBUG_ENTER("federated_commit");
|
||||
|
||||
if (all)
|
||||
{
|
||||
int error= 0;
|
||||
ha_federated *ptr, *old= NULL;
|
||||
for (ptr= trx; ptr; old= ptr, ptr= ptr->trx_next)
|
||||
{
|
||||
if (old)
|
||||
old->trx_next= NULL;
|
||||
error= ptr->connection_commit();
|
||||
if (error && !return_val);
|
||||
return_val= error;
|
||||
}
|
||||
thd->ha_data[federated_hton.slot]= NULL;
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("error val: %d", return_val));
|
||||
DBUG_RETURN(return_val);
|
||||
}
|
||||
|
||||
|
||||
static int federated_rollback(THD *thd, bool all)
|
||||
{
|
||||
int return_val= 0;
|
||||
ha_federated *trx= (ha_federated *)thd->ha_data[federated_hton.slot];
|
||||
DBUG_ENTER("federated_rollback");
|
||||
|
||||
if (all)
|
||||
{
|
||||
int error= 0;
|
||||
ha_federated *ptr, *old= NULL;
|
||||
for (ptr= trx; ptr; old= ptr, ptr= ptr->trx_next)
|
||||
{
|
||||
if (old)
|
||||
old->trx_next= NULL;
|
||||
error= ptr->connection_rollback();
|
||||
if (error && !return_val)
|
||||
return_val= error;
|
||||
}
|
||||
thd->ha_data[federated_hton.slot]= NULL;
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("error val: %d", return_val));
|
||||
DBUG_RETURN(return_val);
|
||||
}
|
||||
|
||||
int ha_federated::connection_commit()
|
||||
{
|
||||
DBUG_ENTER("ha_federated::connection_commit");
|
||||
DBUG_RETURN(execute_simple_query("COMMIT", 6));
|
||||
}
|
||||
|
||||
|
||||
int ha_federated::connection_rollback()
|
||||
{
|
||||
DBUG_ENTER("ha_federated::connection_rollback");
|
||||
DBUG_RETURN(execute_simple_query("ROLLBACK", 8));
|
||||
}
|
||||
|
||||
|
||||
int ha_federated::connection_autocommit(bool state)
|
||||
{
|
||||
const char *text;
|
||||
DBUG_ENTER("ha_federated::connection_autocommit");
|
||||
text= (state == true) ? "SET AUTOCOMMIT=1" : "SET AUTOCOMMIT=0";
|
||||
DBUG_RETURN(execute_simple_query(text, 16));
|
||||
}
|
||||
|
||||
|
||||
int ha_federated::execute_simple_query(const char *query, int len)
|
||||
{
|
||||
DBUG_ENTER("ha_federated::execute_simple_query");
|
||||
|
||||
if (mysql_real_query(mysql, query, len))
|
||||
{
|
||||
DBUG_RETURN(stash_remote_error());
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -174,11 +174,13 @@ private:
|
||||
|
||||
public:
|
||||
ha_federated(TABLE *table_arg);
|
||||
~ha_federated()
|
||||
{
|
||||
}
|
||||
~ha_federated() {}
|
||||
/* The name that will be used for display purposes */
|
||||
const char *table_type() const { return "FEDERATED"; }
|
||||
/*
|
||||
Next pointer used in transaction
|
||||
*/
|
||||
ha_federated *trx_next;
|
||||
/*
|
||||
The name of the index type that will be used for display
|
||||
don't implement this method unless you really have indexes
|
||||
@ -298,7 +300,14 @@ public:
|
||||
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
|
||||
enum thr_lock_type lock_type); //required
|
||||
virtual bool get_error_message(int error, String *buf);
|
||||
int external_lock(THD *thd, int lock_type);
|
||||
int connection_commit();
|
||||
int connection_rollback();
|
||||
bool has_transactions() { return 1; }
|
||||
int connection_autocommit(bool state);
|
||||
int execute_simple_query(const char *query, int len);
|
||||
};
|
||||
|
||||
bool federated_db_init(void);
|
||||
int federated_db_end(ha_panic_function type);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user