mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Added federatedx storage engine
Fixed compiler warnings client/mysqladmin.cc: Fixed compiler warning extra/yassl/taocrypt/src/twofish.cpp: Fixed compiler warning libmysqld/Makefile.am: Use federatedx instead of federated (Should actually be removed) mysql-test/mysql-test-run.pl: Fixed warning mysql-test/valgrind.supp: Removed warning found on 64 bit machine
This commit is contained in:
parent
664fa25e0e
commit
49b519ca0b
34 changed files with 5662 additions and 54 deletions
|
@ -1043,7 +1043,7 @@ static int drop_db(MYSQL *mysql, const char *db)
|
|||
printf("Do you really want to drop the '%s' database [y/N] ",db);
|
||||
fflush(stdout);
|
||||
if (fgets(buf,sizeof(buf)-1,stdin) == 0 ||
|
||||
(*buf != 'y') && (*buf != 'Y'))
|
||||
((*buf != 'y') && (*buf != 'Y')))
|
||||
{
|
||||
puts("\nOK, aborting database drop!");
|
||||
return -1;
|
||||
|
|
|
@ -55,6 +55,7 @@ void Twofish::Process(byte* out, const byte* in, word32 sz)
|
|||
in += BLOCK_SIZE;
|
||||
}
|
||||
else if (mode_ == CBC)
|
||||
{
|
||||
if (dir_ == ENCRYPTION)
|
||||
while (blocks--) {
|
||||
r_[0] ^= *(word32*)in;
|
||||
|
@ -82,6 +83,7 @@ void Twofish::Process(byte* out, const byte* in, word32 sz)
|
|||
out += BLOCK_SIZE;
|
||||
in += BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DO_TWOFISH_ASM
|
||||
|
|
|
@ -124,7 +124,7 @@ handler.o: handler.cc
|
|||
# found to append fileslists that collected by configure
|
||||
# to the sources list
|
||||
|
||||
ha_federated.o:ha_federated.cc
|
||||
ha_federatedx.o:ha_federatedx.cc
|
||||
$(CXXCOMPILE) $(LM_CFLAGS) -c $<
|
||||
|
||||
ha_heap.o:ha_heap.cc
|
||||
|
|
|
@ -127,7 +127,6 @@ my $path_config_file; # The generated config file, var/my.cnf
|
|||
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
|
||||
|
||||
my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts";
|
||||
my $opt_suites;
|
||||
|
||||
our $opt_usage;
|
||||
our $opt_list_options;
|
||||
|
|
|
@ -9,4 +9,5 @@
|
|||
# Do not use any TAB characters for whitespace.
|
||||
#
|
||||
##############################################################################
|
||||
federated_transactions : Bug#29523 Transactions do not work
|
||||
federated_server : needs fixup
|
||||
|
||||
|
|
|
@ -47,9 +47,10 @@ CREATE TABLE federated.t1 (
|
|||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
|
||||
SELECT * FROM federated.t1;
|
||||
ERROR HY000: The foreign data source you are trying to reference does not exist. Data source error: error: 1146 'Table 'federated.t3' doesn't exist'
|
||||
DROP TABLE federated.t1;
|
||||
ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'root' hostname: '127.0.0.1'
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`group` int NOT NULL default 0,
|
||||
|
@ -59,9 +60,10 @@ CREATE TABLE federated.t1 (
|
|||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
|
||||
SELECT * FROM federated.t1;
|
||||
ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES)
|
||||
DROP TABLE federated.t1;
|
||||
ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'user' hostname: '127.0.0.1'
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`group` int NOT NULL default 0,
|
||||
|
@ -1944,15 +1946,7 @@ Bug#18287 create federated table always times out, error 1159 ' '
|
|||
|
||||
Test that self-references work
|
||||
|
||||
create table federated.t1 (a int primary key);
|
||||
create table federated.t2 (a int primary key)
|
||||
ENGINE=FEDERATED
|
||||
connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
|
||||
insert into federated.t1 (a) values (1);
|
||||
select * from federated.t2;
|
||||
a
|
||||
1
|
||||
drop table federated.t1, federated.t2;
|
||||
fix LOCK_open before reenabling test for Bug#18287
|
||||
CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8;
|
||||
CREATE TABLE federated.t1 (a INT PRIMARY KEY)
|
||||
ENGINE=FEDERATED
|
||||
|
@ -1960,13 +1954,11 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'
|
|||
DEFAULT CHARSET=utf8;
|
||||
SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED";
|
||||
transactions
|
||||
NO
|
||||
YES
|
||||
INSERT INTO federated.t1 VALUES (1);
|
||||
SET autocommit=0;
|
||||
INSERT INTO federated.t1 VALUES (2);
|
||||
ROLLBACK;
|
||||
Warnings:
|
||||
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
SET autocommit=1;
|
||||
SELECT * FROM federated.t1;
|
||||
a
|
||||
|
@ -2157,6 +2149,6 @@ End of 5.1 tests
|
|||
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT;
|
||||
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
|
|
|
@ -57,6 +57,7 @@ CREATE TABLE federated.t1 (
|
|||
|
||||
# test non-existant table
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
--error ER_CANT_CREATE_FEDERATED_TABLE
|
||||
eval CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`group` int NOT NULL default 0,
|
||||
|
@ -66,12 +67,11 @@ eval CREATE TABLE federated.t1 (
|
|||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3';
|
||||
--error ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
|
||||
SELECT * FROM federated.t1;
|
||||
DROP TABLE federated.t1;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
|
||||
# test bad user/password
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
--error ER_CANT_CREATE_FEDERATED_TABLE
|
||||
eval CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`group` int NOT NULL default 0,
|
||||
|
@ -81,9 +81,7 @@ eval CREATE TABLE federated.t1 (
|
|||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1';
|
||||
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
|
||||
SELECT * FROM federated.t1;
|
||||
DROP TABLE federated.t1;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
|
||||
# # correct connection, same named tables
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
|
@ -1806,6 +1804,8 @@ drop table federated.t1;
|
|||
--echo
|
||||
--echo Test that self-references work
|
||||
--echo
|
||||
--echo fix LOCK_open before reenabling test for Bug#18287
|
||||
--disable_parsing
|
||||
connection slave;
|
||||
create table federated.t1 (a int primary key);
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
|
@ -1815,7 +1815,7 @@ eval create table federated.t2 (a int primary key)
|
|||
insert into federated.t1 (a) values (1);
|
||||
select * from federated.t2;
|
||||
drop table federated.t1, federated.t2;
|
||||
|
||||
--enable_parsing
|
||||
#
|
||||
# BUG#29875 Disable support for transactions
|
||||
#
|
||||
|
|
|
@ -34,6 +34,6 @@ id name
|
|||
DROP TABLE federated.t1;
|
||||
DROP TABLE federated.archive_table;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
|
|
|
@ -25,6 +25,6 @@ foo bar
|
|||
DROP TABLE federated.t1;
|
||||
DROP TABLE federated.bug_13118_table;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
|
|
|
@ -48,6 +48,6 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT;
|
|||
DROP TABLE federated.t1;
|
||||
SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
connection master;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
|
||||
connection slave;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
--enable_warnings
|
||||
|
|
|
@ -20,6 +20,6 @@ a b
|
|||
drop table federated.t1;
|
||||
drop table federated.t1;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
|
|
|
@ -178,8 +178,8 @@ INSERT INTO db_bogus.t1 VALUES ('2','this is bogus');
|
|||
create server 's1' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'db_legitimate',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
USER 'test_fed',
|
||||
PASSWORD 'foo',
|
||||
PORT SLAVE_PORT,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
# Slow test, don't run during staging part
|
||||
-- source include/not_staging.inc
|
||||
-- source include/big_test.inc
|
||||
-- source federated.inc
|
||||
|
||||
connection slave;
|
||||
|
@ -182,13 +183,17 @@ CREATE TABLE db_bogus.t1 (
|
|||
;
|
||||
INSERT INTO db_bogus.t1 VALUES ('2','this is bogus');
|
||||
|
||||
connection slave;
|
||||
create user test_fed@localhost identified by 'foo';
|
||||
grant all on db_legitimate.* to test_fed@localhost;
|
||||
|
||||
connection master;
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
eval create server 's1' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'db_legitimate',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
USER 'test_fed',
|
||||
PASSWORD 'foo',
|
||||
PORT $SLAVE_MYPORT,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
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:
|
||||
|
|
|
@ -880,3 +880,17 @@
|
|||
fun:nptl_pthread_exit_hack_handler
|
||||
fun:start_thread
|
||||
}
|
||||
|
||||
#
|
||||
# Problem with glibc and gethostbyaddr_r
|
||||
#
|
||||
|
||||
{
|
||||
libc_res_nsend: Conditional jump or move depends on uninitialised value
|
||||
Memcheck:Cond
|
||||
fun: __libc_res_nsend
|
||||
fun: __libc_res_nquery
|
||||
obj: /lib64/libnss_dns-*so)
|
||||
obj: /lib64/libnss_dns-*so)
|
||||
fun: gethostbyaddr_r
|
||||
}
|
||||
|
|
7
storage/federated/README
Normal file
7
storage/federated/README
Normal file
|
@ -0,0 +1,7 @@
|
|||
The files in this directory are not used by MariaDB
|
||||
|
||||
MariaDB uses the new federated storage engine that can be found in the
|
||||
federatedx directory.
|
||||
|
||||
This directory is only kept around to make it easy to merge code from the
|
||||
MySQL source repositories that uses the old and disabled federated code.
|
11
storage/federatedx/AUTHORS
Normal file
11
storage/federatedx/AUTHORS
Normal file
|
@ -0,0 +1,11 @@
|
|||
FederatedX
|
||||
|
||||
Patrick Galbraith <patg@patg.net> - Federated
|
||||
|
||||
Pluggable Storage Engine Skeleton setup
|
||||
|
||||
Brian Aker <brian@mysql.com> | <brian@tangent.org> - Original Design
|
||||
Calvin Sun - Windows Support
|
||||
Brian Miezejewski - Bug fixes
|
||||
Antony T Curtis - Help in inital development, transactions and various help
|
||||
Michael Widenius - Bug fixes and some simple early optimizations
|
3
storage/federatedx/CMakeFiles.txt
Normal file
3
storage/federatedx/CMakeFiles.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(FEDERATED_SOURCES ha_federatedx.cc)
|
||||
MYSQL_STORAGE_ENGINE(FEDERATED)
|
18
storage/federatedx/ChangeLog
Normal file
18
storage/federatedx/ChangeLog
Normal file
|
@ -0,0 +1,18 @@
|
|||
0.2 - Thu March 8 00:00:00 EST 2008
|
||||
|
||||
- Fixed bug #30051 "CREATE TABLE does not connect and check existence of remote table"
|
||||
Modified "real_connect" to take a share and create flag to in order to not rely
|
||||
on any settings that are later instantiated and/or set by get_share
|
||||
Also, put logic in the code to not attempt this if a localhost. There's an annoying
|
||||
functionality that if federated tries to connect to itself during creater table, you
|
||||
get 1159 error (timeout) - only when local. This prevents having this functionality
|
||||
and is probably part of the reason it was removed.
|
||||
|
||||
0.1 - Thu Feb 1 00:00:00 EST 2008
|
||||
|
||||
- This is the FederatedX Storage Engine,
|
||||
first release.
|
||||
- Added documentation
|
||||
- Added simple test and README file to explain
|
||||
how to run the test
|
||||
- Added FAQ
|
40
storage/federatedx/FAQ
Normal file
40
storage/federatedx/FAQ
Normal file
|
@ -0,0 +1,40 @@
|
|||
Q. What is the FederatedX pluggable storage engine?
|
||||
|
||||
A. It is a fork of the Federated Storage Engine that Brian Aker and I
|
||||
(Patrick Galbraith) developed originally . It is a storage engine that
|
||||
uses a client connection to a remote MySQL data source as its data
|
||||
source instead of a local file on disk.
|
||||
|
||||
Q. Why did you fork from Federated?
|
||||
|
||||
A. To enhance the storage engine independently of the
|
||||
MySQL Server release schedule. Many people have been
|
||||
mentioning their dissatisfaction with the limitations
|
||||
of Federated. I think the engine is a great concept and
|
||||
have a sense of obligation to continue to improve it.
|
||||
There are some patches already that are in dire need
|
||||
of being applied and tested.
|
||||
|
||||
Q. What do you plan to do with FederatedX?
|
||||
|
||||
A. Many things need addressing:
|
||||
|
||||
- Outstanding bugs
|
||||
- How do deal with huge result sets
|
||||
- Pushdown conditions (being able to pass things like LIMIT
|
||||
to the remote connection to keep from returning huge
|
||||
result sets).
|
||||
- Better transactional support
|
||||
- Other connection mechanisms (ODBC, JDBC, native drivers
|
||||
of other RDBMSs)
|
||||
|
||||
Q. What FederatedX is and is not?
|
||||
|
||||
A. FederatedX is not yet a complete "federated" solution in
|
||||
the sense that other venders have developed (IBM, etc). It
|
||||
is essentially a networked storage engine. It is my hope
|
||||
to make it a real federated solution.
|
||||
|
||||
Q. In which MySQL distributions/forks/branches can I find FederateX
|
||||
|
||||
A. MariaDB (http://www.mariadb.com)
|
64
storage/federatedx/Makefile.am
Normal file
64
storage/federatedx/Makefile.am
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Used to build Makefile.in
|
||||
|
||||
MYSQLDATAdir = $(localstatedir)
|
||||
MYSQLSHAREdir = $(pkgdatadir)
|
||||
MYSQLBASEdir= $(prefix)
|
||||
MYSQLLIBdir= $(pkglibdir)
|
||||
pkgplugindir = $(pkglibdir)/plugin
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/regex \
|
||||
-I$(top_srcdir)/sql \
|
||||
-I$(srcdir)
|
||||
WRAPLIBS=
|
||||
|
||||
LDADD =
|
||||
|
||||
DEFS = @DEFS@
|
||||
|
||||
noinst_HEADERS = ha_federatedx.h federatedx_probes.h
|
||||
|
||||
EXTRA_LTLIBRARIES = ha_federatedx.la
|
||||
pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@
|
||||
ha_federatedx_la_LDFLAGS = -module -rpath $(pkgplugindir)
|
||||
ha_federatedx_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||
ha_federatedx_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||
ha_federatedx_la_SOURCES = ha_federatedx.cc
|
||||
|
||||
|
||||
EXTRA_LIBRARIES = libfederatedx.a
|
||||
noinst_LIBRARIES = @plugin_federated_static_target@
|
||||
libfederatedx_a_CXXFLAGS = $(AM_CFLAGS)
|
||||
libfederatedx_a_CFLAGS = $(AM_CFLAGS)
|
||||
libfederatedx_a_SOURCES= ha_federatedx.cc federatedx_txn.cc \
|
||||
federatedx_io.cc federatedx_io_null.cc \
|
||||
federatedx_io_mysql.cc
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt plug.in ha_federatedx.h \
|
||||
federatedx_probes.d
|
||||
|
||||
ha_federatedx_la_SOURCES = ha_federatedx.cc federatedx_txn.cc \
|
||||
federatedx_io.cc federatedx_io_null.cc \
|
||||
federatedx_io_mysql.cc $(top_srcdir)/mysys/string.c
|
||||
ha_federatedx_la_LIBADD =
|
||||
|
||||
#DTRACE = @DTRACE@
|
||||
#DTRACEFLAGS = @DTRACEFLAGS@
|
||||
#DTRACEFILES = .libs/libfederatedx_engine_la-ha_federatedx.o
|
||||
|
||||
# #if HAVE_DTRACE
|
||||
# # libfederatedx_engine_la_LIBADD += federatedx_probes.o
|
||||
# #endif
|
||||
|
||||
# federatedx_probes.h: federatedx_probes.d
|
||||
# $(DTRACE) $(DTRACEFLAGS) -h -s federatedx_probes.d
|
||||
# mv federatedx_probes.h federatedx_probes.h.bak
|
||||
# sed "s/#include <unistd.h>//g" federatedx_probes.h.bak > federatedx_probes.h
|
||||
# rm federatedx_probes.h.bak
|
||||
|
||||
#federatedx_probes.o:
|
||||
# $(DTRACE) $(DTRACEFLAGS) -G -s federatedx_probes.d $(DTRACEFILES)
|
||||
|
||||
# End
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
33
storage/federatedx/README
Normal file
33
storage/federatedx/README
Normal file
|
@ -0,0 +1,33 @@
|
|||
This is the FederatedX Storage Engine, developed as an external storage engine.
|
||||
|
||||
NOTE:
|
||||
|
||||
The following is only relevant if you use it for MySQL. MariaDB already comes
|
||||
with the latest version of FederatedX.
|
||||
|
||||
To install, grab a copy of the mysql source code and run this:
|
||||
|
||||
./configure --with-mysql=/path/to/src/mysql-5.x --libdir=/usr/local/lib/mysql/
|
||||
|
||||
make install
|
||||
|
||||
And then inside of MySQL:
|
||||
|
||||
mysql> INSTALL PLUGIN federatedx SONAME 'libfederatedx_engine.so';
|
||||
|
||||
mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="mysql://root@host/schema/table"
|
||||
|
||||
or
|
||||
|
||||
mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="server" CHARSET=latin1;
|
||||
|
||||
You will probably need to edit the Makefile.am in the src/ tree if you want
|
||||
to build on anything other then Linux (and the Makefile assumes that the
|
||||
server was not compiled for debug). The reason for the two possible
|
||||
configure lines is that libdir is dependent on where MySQL was installed. If
|
||||
you run the "INSTALL PLUGIN ..." and you get a file not found, check that
|
||||
your configured this directory correctly.
|
||||
|
||||
For Solaris you can enable DTrace probes by adding to configure
|
||||
--enable-dtrace
|
||||
|
23
storage/federatedx/README.windows
Normal file
23
storage/federatedx/README.windows
Normal file
|
@ -0,0 +1,23 @@
|
|||
The following files are changed in order to build a new engine on Windows:
|
||||
|
||||
- Update win\configure.js with
|
||||
case "WITH_FEDERATEDX_STORAGE_ENGINE":
|
||||
to make sure it will pass WITH_FEDERATEDX_STORAGE_ENGINE in.
|
||||
|
||||
- Update CMakeFiles.txt under mysql root:
|
||||
IF(WITH_FEDERATEDX_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-D WITH_FEDERATEDX_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs
|
||||
"${mysql_plugin_defs},builtin_skeleton_plugin")
|
||||
ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
|
||||
|
||||
and,
|
||||
|
||||
IF(WITH_FEDERATEDX_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/skeleton/src)
|
||||
ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
|
||||
|
||||
- Update CMakeFiles.txt under sql:
|
||||
IF(WITH_FEDERATEDX_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld skeleton)
|
||||
ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE)
|
30
storage/federatedx/TODO
Normal file
30
storage/federatedx/TODO
Normal file
|
@ -0,0 +1,30 @@
|
|||
Features
|
||||
|
||||
* Add Pushdown conditions
|
||||
* Add other network driver interfaces
|
||||
* Handle large result sets
|
||||
* Auto-discovery of tables on foreign data sources
|
||||
|
||||
Bugs (http://bugs.mysql.com)
|
||||
|
||||
20026 2006-05-23 FEDERATED lacks support for auto_increment_increment and auto_increment_offset
|
||||
20724 2006-06-27 FEDERATED does not honour SET INSERT_ID
|
||||
28269 2007-05-06 Any FEDERATED engine fails to quote reserved words for field names
|
||||
25509 2007-01-10 Federated: Failure with non-ASCII characters
|
||||
26697 2007-02-27 Every query to a federated table results in a full scan of MyISAM table.
|
||||
21360 2006-07-31 Microsoft Windows (Windows/Linux) mysqldump error on federated tables
|
||||
34189 2008-01-31 Any ALTER TABLE t1 ENGINE=FEDERATED CONNECTION='connectionString' on MyISAM fails
|
||||
31757 2007-10-22 Any Federated tables break replication Antony Curtis
|
||||
33953 2008-01-21 Any mysqld dies on search federated table using nullable index with < or <= operator
|
||||
34015 2008-01-23 Linux Problems with float fields using federated tables
|
||||
21583 2006-08-11 Linux (Linux) Federated table returns broken strings.
|
||||
33702 2008-01-05 Accessing a federated table with a non existing server returns random error code
|
||||
25512 2007-01-10 Federated: CREATE failures
|
||||
32426 2007-11-16 Any FEDERATED query returns corrupt results for ORDER BY on a TEXT field
|
||||
25510 2007-01-10 Federated: double trigger activation
|
||||
33250 2007-12-14 SELECT * FROM really_big_federated_table eats lots of virtual memory (OOM)
|
||||
14874 2005-11-11 Error 2013: Lost connection to MySQL server with Federated table
|
||||
25508 2007-01-10 Federated: Failure to Remove Partitioning
|
||||
27180 2007-03-15 #1030 - Got error 1 from storage engine with big tables
|
||||
33947 2008-01-20 Any Join on Federated tables with Unique index and IS NOT NULL crashes server
|
||||
30051 (fixed) CREATE TABLE does not connect and check existence of remote table
|
103
storage/federatedx/federatedx_io.cc
Normal file
103
storage/federatedx/federatedx_io.cc
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Copyright (c) 2007, Antony T Curtis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Neither the name of FederatedX nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*#define MYSQL_SERVER 1*/
|
||||
#include "mysql_priv.h"
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
#include "ha_federatedx.h"
|
||||
|
||||
#include "m_string.h"
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
typedef federatedx_io *(*instantiate_io_type)(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server);
|
||||
struct io_schemes_st
|
||||
{
|
||||
const char *scheme;
|
||||
instantiate_io_type instantiate;
|
||||
};
|
||||
|
||||
|
||||
static const io_schemes_st federated_io_schemes[] =
|
||||
{
|
||||
{ "mysql", &instantiate_io_mysql },
|
||||
{ "null", instantiate_io_null } /* must be last element */
|
||||
};
|
||||
|
||||
const uint federated_io_schemes_count= array_elements(federated_io_schemes);
|
||||
|
||||
federatedx_io::federatedx_io(FEDERATEDX_SERVER *aserver)
|
||||
: server(aserver), owner_ptr(0), txn_next(0), idle_next(0),
|
||||
active(FALSE), busy(FALSE), readonly(TRUE)
|
||||
{
|
||||
DBUG_ENTER("federatedx_io::federatedx_io");
|
||||
DBUG_ASSERT(server);
|
||||
|
||||
safe_mutex_assert_owner(&server->mutex);
|
||||
server->io_count++;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
federatedx_io::~federatedx_io()
|
||||
{
|
||||
DBUG_ENTER("federatedx_io::~federatedx_io");
|
||||
|
||||
server->io_count--;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_io::handles_scheme(const char *scheme)
|
||||
{
|
||||
const io_schemes_st *ptr = federated_io_schemes;
|
||||
const io_schemes_st *end = ptr + array_elements(federated_io_schemes);
|
||||
while (ptr != end && strcasecmp(scheme, ptr->scheme))
|
||||
++ptr;
|
||||
return ptr != end;
|
||||
}
|
||||
|
||||
|
||||
federatedx_io *federatedx_io::construct(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server)
|
||||
{
|
||||
const io_schemes_st *ptr = federated_io_schemes;
|
||||
const io_schemes_st *end = ptr + (array_elements(federated_io_schemes) - 1);
|
||||
while (ptr != end && strcasecmp(server->scheme, ptr->scheme))
|
||||
++ptr;
|
||||
return ptr->instantiate(server_root, server);
|
||||
}
|
||||
|
||||
|
592
storage/federatedx/federatedx_io_mysql.cc
Normal file
592
storage/federatedx/federatedx_io_mysql.cc
Normal file
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
Copyright (c) 2007, Antony T Curtis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Neither the name of FederatedX nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*#define MYSQL_SERVER 1*/
|
||||
#include "mysql_priv.h"
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
#include "ha_federatedx.h"
|
||||
|
||||
#include "m_string.h"
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
|
||||
#define SAVEPOINT_REALIZED 1
|
||||
#define SAVEPOINT_RESTRICT 2
|
||||
#define SAVEPOINT_EMITTED 4
|
||||
|
||||
|
||||
typedef struct federatedx_savepoint
|
||||
{
|
||||
ulong level;
|
||||
uint flags;
|
||||
} SAVEPT;
|
||||
|
||||
|
||||
class federatedx_io_mysql :public federatedx_io
|
||||
{
|
||||
MYSQL mysql; /* MySQL connection */
|
||||
DYNAMIC_ARRAY savepoints;
|
||||
bool requested_autocommit;
|
||||
bool actual_autocommit;
|
||||
|
||||
int actual_query(const char *buffer, uint length);
|
||||
bool test_all_restrict() const;
|
||||
public:
|
||||
federatedx_io_mysql(FEDERATEDX_SERVER *);
|
||||
~federatedx_io_mysql();
|
||||
|
||||
int simple_query(const char *fmt, ...);
|
||||
int query(const char *buffer, uint length);
|
||||
virtual FEDERATEDX_IO_RESULT *store_result();
|
||||
|
||||
virtual size_t max_query_size() const;
|
||||
|
||||
virtual my_ulonglong affected_rows() const;
|
||||
virtual my_ulonglong last_insert_id() const;
|
||||
|
||||
virtual int error_code();
|
||||
virtual const char *error_str();
|
||||
|
||||
void reset();
|
||||
int commit();
|
||||
int rollback();
|
||||
|
||||
int savepoint_set(ulong sp);
|
||||
ulong savepoint_release(ulong sp);
|
||||
ulong savepoint_rollback(ulong sp);
|
||||
void savepoint_restrict(ulong sp);
|
||||
|
||||
ulong last_savepoint() const;
|
||||
ulong actual_savepoint() const;
|
||||
bool is_autocommit() const;
|
||||
|
||||
bool table_metadata(ha_statistics *stats, const char *table_name,
|
||||
uint table_name_length, uint flag);
|
||||
|
||||
/* resultset operations */
|
||||
|
||||
virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column);
|
||||
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column) const;
|
||||
};
|
||||
|
||||
|
||||
federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server)
|
||||
{
|
||||
return new (server_root) federatedx_io_mysql(server);
|
||||
}
|
||||
|
||||
|
||||
federatedx_io_mysql::federatedx_io_mysql(FEDERATEDX_SERVER *aserver)
|
||||
: federatedx_io(aserver),
|
||||
requested_autocommit(TRUE), actual_autocommit(TRUE)
|
||||
{
|
||||
DBUG_ENTER("federatedx_io_mysql::federatedx_io_mysql");
|
||||
|
||||
bzero(&mysql, sizeof(MYSQL));
|
||||
bzero(&savepoints, sizeof(DYNAMIC_ARRAY));
|
||||
|
||||
my_init_dynamic_array(&savepoints, sizeof(SAVEPT), 16, 16);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
federatedx_io_mysql::~federatedx_io_mysql()
|
||||
{
|
||||
DBUG_ENTER("federatedx_io_mysql::~federatedx_io_mysql");
|
||||
|
||||
mysql_close(&mysql);
|
||||
delete_dynamic(&savepoints);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void federatedx_io_mysql::reset()
|
||||
{
|
||||
reset_dynamic(&savepoints);
|
||||
set_active(FALSE);
|
||||
|
||||
requested_autocommit= TRUE;
|
||||
mysql.reconnect= 1;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_mysql::commit()
|
||||
{
|
||||
int error= 0;
|
||||
DBUG_ENTER("federatedx_io_mysql::commit");
|
||||
|
||||
if (!actual_autocommit && (error= actual_query("COMMIT", 6)))
|
||||
rollback();
|
||||
|
||||
reset();
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
int federatedx_io_mysql::rollback()
|
||||
{
|
||||
int error= 0;
|
||||
DBUG_ENTER("federatedx_io_mysql::rollback");
|
||||
|
||||
if (!actual_autocommit)
|
||||
error= actual_query("ROLLBACK", 8);
|
||||
else
|
||||
error= ER_WARNING_NOT_COMPLETE_ROLLBACK;
|
||||
|
||||
reset();
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_mysql::last_savepoint() const
|
||||
{
|
||||
SAVEPT *savept= NULL;
|
||||
DBUG_ENTER("federatedx_io_mysql::last_savepoint");
|
||||
|
||||
if (savepoints.elements)
|
||||
savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
|
||||
|
||||
DBUG_RETURN(savept ? savept->level : 0);
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_mysql::actual_savepoint() const
|
||||
{
|
||||
SAVEPT *savept= NULL;
|
||||
uint index= savepoints.elements;
|
||||
DBUG_ENTER("federatedx_io_mysql::last_savepoint");
|
||||
|
||||
while (index)
|
||||
{
|
||||
savept= dynamic_element(&savepoints, --index, SAVEPT *);
|
||||
if (savept->flags & SAVEPOINT_REALIZED)
|
||||
break;
|
||||
savept= NULL;
|
||||
}
|
||||
|
||||
DBUG_RETURN(savept ? savept->level : 0);
|
||||
}
|
||||
|
||||
bool federatedx_io_mysql::is_autocommit() const
|
||||
{
|
||||
return actual_autocommit;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_mysql::savepoint_set(ulong sp)
|
||||
{
|
||||
int error;
|
||||
SAVEPT savept;
|
||||
DBUG_ENTER("federatedx_io_mysql::savepoint_set");
|
||||
DBUG_PRINT("info",("savepoint=%lu", sp));
|
||||
DBUG_ASSERT(sp > last_savepoint());
|
||||
|
||||
savept.level= sp;
|
||||
savept.flags= 0;
|
||||
|
||||
if ((error= insert_dynamic(&savepoints, (uchar*) &savept) ? -1 : 0))
|
||||
goto err;
|
||||
|
||||
set_active(TRUE);
|
||||
mysql.reconnect= 0;
|
||||
requested_autocommit= FALSE;
|
||||
|
||||
err:
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_mysql::savepoint_release(ulong sp)
|
||||
{
|
||||
SAVEPT *savept, *last= NULL;
|
||||
DBUG_ENTER("federatedx_io_mysql::savepoint_release");
|
||||
DBUG_PRINT("info",("savepoint=%lu", sp));
|
||||
|
||||
while (savepoints.elements)
|
||||
{
|
||||
savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
|
||||
if (savept->level < sp)
|
||||
break;
|
||||
if ((savept->flags & (SAVEPOINT_REALIZED |
|
||||
SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED)
|
||||
last= savept;
|
||||
savepoints.elements--;
|
||||
}
|
||||
|
||||
if (last)
|
||||
{
|
||||
char buffer[STRING_BUFFER_USUAL_SIZE];
|
||||
int length= my_snprintf(buffer, sizeof(buffer),
|
||||
"RELEASE SAVEPOINT save%lu", last->level);
|
||||
actual_query(buffer, length);
|
||||
}
|
||||
|
||||
DBUG_RETURN(last_savepoint());
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_mysql::savepoint_rollback(ulong sp)
|
||||
{
|
||||
SAVEPT *savept;
|
||||
uint index;
|
||||
DBUG_ENTER("federatedx_io_mysql::savepoint_release");
|
||||
DBUG_PRINT("info",("savepoint=%lu", sp));
|
||||
|
||||
while (savepoints.elements)
|
||||
{
|
||||
savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *);
|
||||
if (savept->level <= sp)
|
||||
break;
|
||||
savepoints.elements--;
|
||||
}
|
||||
|
||||
for (index= savepoints.elements, savept= NULL; index;)
|
||||
{
|
||||
savept= dynamic_element(&savepoints, --index, SAVEPT *);
|
||||
if (savept->flags & SAVEPOINT_REALIZED)
|
||||
break;
|
||||
savept= NULL;
|
||||
}
|
||||
|
||||
if (savept && !(savept->flags & SAVEPOINT_RESTRICT))
|
||||
{
|
||||
char buffer[STRING_BUFFER_USUAL_SIZE];
|
||||
int length= my_snprintf(buffer, sizeof(buffer),
|
||||
"ROLLBACK TO SAVEPOINT save%lu", savept->level);
|
||||
actual_query(buffer, length);
|
||||
}
|
||||
|
||||
DBUG_RETURN(last_savepoint());
|
||||
}
|
||||
|
||||
|
||||
void federatedx_io_mysql::savepoint_restrict(ulong sp)
|
||||
{
|
||||
SAVEPT *savept;
|
||||
uint index= savepoints.elements;
|
||||
DBUG_ENTER("federatedx_io_mysql::savepoint_restrict");
|
||||
|
||||
while (index)
|
||||
{
|
||||
savept= dynamic_element(&savepoints, --index, SAVEPT *);
|
||||
if (savept->level > sp)
|
||||
continue;
|
||||
if (savept->level < sp)
|
||||
break;
|
||||
savept->flags|= SAVEPOINT_RESTRICT;
|
||||
break;
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_mysql::simple_query(const char *fmt, ...)
|
||||
{
|
||||
char buffer[STRING_BUFFER_USUAL_SIZE];
|
||||
int length, error;
|
||||
va_list arg;
|
||||
DBUG_ENTER("federatedx_io_mysql::simple_query");
|
||||
|
||||
va_start(arg, fmt);
|
||||
length= my_vsnprintf(buffer, sizeof(buffer), fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
error= query(buffer, length);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_io_mysql::test_all_restrict() const
|
||||
{
|
||||
bool result= FALSE;
|
||||
SAVEPT *savept;
|
||||
uint index= savepoints.elements;
|
||||
DBUG_ENTER("federatedx_io_mysql::test_all_restrict");
|
||||
|
||||
while (index)
|
||||
{
|
||||
savept= dynamic_element(&savepoints, --index, SAVEPT *);
|
||||
if ((savept->flags & (SAVEPOINT_REALIZED |
|
||||
SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED ||
|
||||
(savept->flags & SAVEPOINT_EMITTED))
|
||||
DBUG_RETURN(FALSE);
|
||||
if (savept->flags & SAVEPOINT_RESTRICT)
|
||||
result= TRUE;
|
||||
}
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_mysql::query(const char *buffer, uint length)
|
||||
{
|
||||
int error;
|
||||
bool wants_autocommit= requested_autocommit | is_readonly();
|
||||
DBUG_ENTER("federatedx_io_mysql::query");
|
||||
|
||||
if (!wants_autocommit && test_all_restrict())
|
||||
wants_autocommit= TRUE;
|
||||
|
||||
if (wants_autocommit != actual_autocommit)
|
||||
{
|
||||
if ((error= actual_query(wants_autocommit ? "SET AUTOCOMMIT=1"
|
||||
: "SET AUTOCOMMIT=0", 16)))
|
||||
DBUG_RETURN(error);
|
||||
mysql.reconnect= wants_autocommit ? 1 : 0;
|
||||
actual_autocommit= wants_autocommit;
|
||||
}
|
||||
|
||||
if (!actual_autocommit && last_savepoint() != actual_savepoint())
|
||||
{
|
||||
SAVEPT *savept= dynamic_element(&savepoints, savepoints.elements - 1,
|
||||
SAVEPT *);
|
||||
if (!(savept->flags & SAVEPOINT_RESTRICT))
|
||||
{
|
||||
char buf[STRING_BUFFER_USUAL_SIZE];
|
||||
int len= my_snprintf(buf, sizeof(buf),
|
||||
"SAVEPOINT save%lu", savept->level);
|
||||
if ((error= actual_query(buf, len)))
|
||||
DBUG_RETURN(error);
|
||||
set_active(TRUE);
|
||||
savept->flags|= SAVEPOINT_EMITTED;
|
||||
}
|
||||
savept->flags|= SAVEPOINT_REALIZED;
|
||||
}
|
||||
|
||||
if (!(error= actual_query(buffer, length)))
|
||||
set_active(is_active() || !actual_autocommit);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_mysql::actual_query(const char *buffer, uint length)
|
||||
{
|
||||
int error;
|
||||
DBUG_ENTER("federatedx_io_mysql::actual_query");
|
||||
|
||||
if (!mysql.master)
|
||||
{
|
||||
if (!(mysql_init(&mysql)))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/*
|
||||
BUG# 17044 Federated Storage Engine is not UTF8 clean
|
||||
Add set names to whatever charset the table is at open
|
||||
of table
|
||||
*/
|
||||
/* this sets the csname like 'set names utf8' */
|
||||
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, get_charsetname());
|
||||
|
||||
if (!mysql_real_connect(&mysql,
|
||||
get_hostname(),
|
||||
get_username(),
|
||||
get_password(),
|
||||
get_database(),
|
||||
get_port(),
|
||||
get_socket(), 0))
|
||||
DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
|
||||
mysql.reconnect= 1;
|
||||
}
|
||||
|
||||
error= mysql_real_query(&mysql, buffer, length);
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
size_t federatedx_io_mysql::max_query_size() const
|
||||
{
|
||||
return mysql.net.max_packet_size;
|
||||
}
|
||||
|
||||
|
||||
my_ulonglong federatedx_io_mysql::affected_rows() const
|
||||
{
|
||||
return mysql.affected_rows;
|
||||
}
|
||||
|
||||
|
||||
my_ulonglong federatedx_io_mysql::last_insert_id() const
|
||||
{
|
||||
return mysql.last_used_con->insert_id;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_mysql::error_code()
|
||||
{
|
||||
return mysql_errno(&mysql);
|
||||
}
|
||||
|
||||
|
||||
const char *federatedx_io_mysql::error_str()
|
||||
{
|
||||
return mysql_error(&mysql);
|
||||
}
|
||||
|
||||
|
||||
FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result()
|
||||
{
|
||||
FEDERATEDX_IO_RESULT *result;
|
||||
DBUG_ENTER("federatedx_io_mysql::store_result");
|
||||
|
||||
result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql);
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
void federatedx_io_mysql::free_result(FEDERATEDX_IO_RESULT *io_result)
|
||||
{
|
||||
mysql_free_result((MYSQL_RES *) io_result);
|
||||
}
|
||||
|
||||
|
||||
unsigned int federatedx_io_mysql::get_num_fields(FEDERATEDX_IO_RESULT *io_result)
|
||||
{
|
||||
return mysql_num_fields((MYSQL_RES *) io_result);
|
||||
}
|
||||
|
||||
|
||||
my_ulonglong federatedx_io_mysql::get_num_rows(FEDERATEDX_IO_RESULT *io_result)
|
||||
{
|
||||
return mysql_num_rows((MYSQL_RES *) io_result);
|
||||
}
|
||||
|
||||
|
||||
FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result)
|
||||
{
|
||||
return (FEDERATEDX_IO_ROW *) mysql_fetch_row((MYSQL_RES *) io_result);
|
||||
}
|
||||
|
||||
|
||||
ulong *federatedx_io_mysql::fetch_lengths(FEDERATEDX_IO_RESULT *io_result)
|
||||
{
|
||||
return mysql_fetch_lengths((MYSQL_RES *) io_result);
|
||||
}
|
||||
|
||||
|
||||
const char *federatedx_io_mysql::get_column_data(FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column)
|
||||
{
|
||||
return ((MYSQL_ROW)row)[column];
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_io_mysql::is_column_null(const FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column) const
|
||||
{
|
||||
return !((MYSQL_ROW)row)[column];
|
||||
}
|
||||
|
||||
bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
|
||||
const char *table_name,
|
||||
uint table_name_length, uint flag)
|
||||
{
|
||||
char status_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
|
||||
FEDERATEDX_IO_RESULT *result= 0;
|
||||
FEDERATEDX_IO_ROW *row;
|
||||
String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin);
|
||||
int error;
|
||||
|
||||
status_query_string.length(0);
|
||||
status_query_string.append(STRING_WITH_LEN("SHOW TABLE STATUS LIKE "));
|
||||
append_ident(&status_query_string, table_name,
|
||||
table_name_length, value_quote_char);
|
||||
|
||||
if (query(status_query_string.ptr(), status_query_string.length()))
|
||||
goto error;
|
||||
|
||||
status_query_string.length(0);
|
||||
|
||||
result= store_result();
|
||||
|
||||
/*
|
||||
We're going to use fields num. 4, 12 and 13 of the resultset,
|
||||
so make sure we have these fields.
|
||||
*/
|
||||
if (!result || (get_num_fields(result) < 14))
|
||||
goto error;
|
||||
|
||||
if (!get_num_rows(result))
|
||||
goto error;
|
||||
|
||||
if (!(row= fetch_row(result)))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
deleted is set in ha_federatedx::info
|
||||
*/
|
||||
/*
|
||||
need to figure out what this means as far as federatedx is concerned,
|
||||
since we don't have a "file"
|
||||
|
||||
data_file_length = ?
|
||||
index_file_length = ?
|
||||
delete_length = ?
|
||||
*/
|
||||
if (!is_column_null(row, 4))
|
||||
stats->records= (ha_rows) my_strtoll10(get_column_data(row, 4),
|
||||
(char**) 0, &error);
|
||||
if (!is_column_null(row, 5))
|
||||
stats->mean_rec_length= (ulong) my_strtoll10(get_column_data(row, 5),
|
||||
(char**) 0, &error);
|
||||
|
||||
stats->data_file_length= stats->records * stats->mean_rec_length;
|
||||
|
||||
if (!is_column_null(row, 12))
|
||||
stats->update_time= (time_t) my_strtoll10(get_column_data(row, 12),
|
||||
(char**) 0, &error);
|
||||
if (!is_column_null(row, 13))
|
||||
stats->check_time= (time_t) my_strtoll10(get_column_data(row, 13),
|
||||
(char**) 0, &error);
|
||||
|
||||
free_result(result);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free_result(result);
|
||||
return 1;
|
||||
}
|
277
storage/federatedx/federatedx_io_null.cc
Normal file
277
storage/federatedx/federatedx_io_null.cc
Normal file
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
Copyright (c) 2007, Antony T Curtis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Neither the name of FederatedX nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*#define MYSQL_SERVER 1*/
|
||||
#include "mysql_priv.h"
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
#include "ha_federatedx.h"
|
||||
|
||||
#include "m_string.h"
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
|
||||
#define SAVEPOINT_REALIZED 1
|
||||
#define SAVEPOINT_RESTRICT 2
|
||||
#define SAVEPOINT_EMITTED 4
|
||||
|
||||
|
||||
typedef struct federatedx_savepoint
|
||||
{
|
||||
ulong level;
|
||||
uint flags;
|
||||
} SAVEPT;
|
||||
|
||||
|
||||
class federatedx_io_null :public federatedx_io
|
||||
{
|
||||
public:
|
||||
federatedx_io_null(FEDERATEDX_SERVER *);
|
||||
~federatedx_io_null();
|
||||
|
||||
int query(const char *buffer, uint length);
|
||||
virtual FEDERATEDX_IO_RESULT *store_result();
|
||||
|
||||
virtual size_t max_query_size() const;
|
||||
|
||||
virtual my_ulonglong affected_rows() const;
|
||||
virtual my_ulonglong last_insert_id() const;
|
||||
|
||||
virtual int error_code();
|
||||
virtual const char *error_str();
|
||||
|
||||
void reset();
|
||||
int commit();
|
||||
int rollback();
|
||||
|
||||
int savepoint_set(ulong sp);
|
||||
ulong savepoint_release(ulong sp);
|
||||
ulong savepoint_rollback(ulong sp);
|
||||
void savepoint_restrict(ulong sp);
|
||||
|
||||
ulong last_savepoint() const;
|
||||
ulong actual_savepoint() const;
|
||||
bool is_autocommit() const;
|
||||
|
||||
bool table_metadata(ha_statistics *stats, const char *table_name,
|
||||
uint table_name_length, uint flag);
|
||||
|
||||
/* resultset operations */
|
||||
|
||||
virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
|
||||
virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column);
|
||||
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column) const;
|
||||
};
|
||||
|
||||
|
||||
federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server)
|
||||
{
|
||||
return new (server_root) federatedx_io_null(server);
|
||||
}
|
||||
|
||||
|
||||
federatedx_io_null::federatedx_io_null(FEDERATEDX_SERVER *aserver)
|
||||
: federatedx_io(aserver)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
federatedx_io_null::~federatedx_io_null()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void federatedx_io_null::reset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_null::commit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int federatedx_io_null::rollback()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_null::last_savepoint() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_null::actual_savepoint() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool federatedx_io_null::is_autocommit() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_null::savepoint_set(ulong sp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_null::savepoint_release(ulong sp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ulong federatedx_io_null::savepoint_rollback(ulong sp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void federatedx_io_null::savepoint_restrict(ulong sp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_null::query(const char *buffer, uint length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t federatedx_io_null::max_query_size() const
|
||||
{
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
|
||||
my_ulonglong federatedx_io_null::affected_rows() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
my_ulonglong federatedx_io_null::last_insert_id() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_io_null::error_code()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char *federatedx_io_null::error_str()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
FEDERATEDX_IO_RESULT *federatedx_io_null::store_result()
|
||||
{
|
||||
FEDERATEDX_IO_RESULT *result;
|
||||
DBUG_ENTER("federatedx_io_null::store_result");
|
||||
|
||||
result= NULL;
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
void federatedx_io_null::free_result(FEDERATEDX_IO_RESULT *)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
unsigned int federatedx_io_null::get_num_fields(FEDERATEDX_IO_RESULT *)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
my_ulonglong federatedx_io_null::get_num_rows(FEDERATEDX_IO_RESULT *)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ulong *federatedx_io_null::fetch_lengths(FEDERATEDX_IO_RESULT *)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char *federatedx_io_null::get_column_data(FEDERATEDX_IO_ROW *,
|
||||
unsigned int)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_io_null::is_column_null(const FEDERATEDX_IO_ROW *,
|
||||
unsigned int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool federatedx_io_null::table_metadata(ha_statistics *stats,
|
||||
const char *table_name,
|
||||
uint table_name_length, uint flag)
|
||||
{
|
||||
stats->records= (ha_rows) 0;
|
||||
stats->mean_rec_length= (ulong) 0;
|
||||
stats->data_file_length= 0;
|
||||
|
||||
stats->update_time= (time_t) 0;
|
||||
stats->check_time= (time_t) 0;
|
||||
|
||||
return 0;
|
||||
}
|
45
storage/federatedx/federatedx_probes.h
Normal file
45
storage/federatedx/federatedx_probes.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Generated by dtrace(1M).
|
||||
*/
|
||||
|
||||
#ifndef _FEDERATED_PROBES_H
|
||||
#define _FEDERATED_PROBES_H
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if _DTRACE_VERSION
|
||||
|
||||
#define FEDERATED_CLOSE() \
|
||||
__dtrace_federated___close()
|
||||
#define FEDERATED_CLOSE_ENABLED() \
|
||||
__dtraceenabled_federated___close()
|
||||
#define FEDERATED_OPEN() \
|
||||
__dtrace_federated___open()
|
||||
#define FEDERATED_OPEN_ENABLED() \
|
||||
__dtraceenabled_federated___open()
|
||||
|
||||
|
||||
extern void __dtrace_federated___close(void);
|
||||
extern int __dtraceenabled_federated___close(void);
|
||||
extern void __dtrace_federated___open(void);
|
||||
extern int __dtraceenabled_federated___open(void);
|
||||
|
||||
#else
|
||||
|
||||
#define FEDERATED_CLOSE()
|
||||
#define FEDERATED_CLOSE_ENABLED() (0)
|
||||
#define FEDERATED_OPEN()
|
||||
#define FEDERATED_OPEN_ENABLED() (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FEDERATED_PROBES_H */
|
424
storage/federatedx/federatedx_txn.cc
Normal file
424
storage/federatedx/federatedx_txn.cc
Normal file
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
Copyright (c) 2007, Antony T Curtis
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Neither the name of FederatedX nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*#define MYSQL_SERVER 1*/
|
||||
#include "mysql_priv.h"
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
#include "ha_federatedx.h"
|
||||
|
||||
#include "m_string.h"
|
||||
|
||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||
#pragma implementation // gcc: Class implementation
|
||||
#endif
|
||||
|
||||
|
||||
federatedx_txn::federatedx_txn()
|
||||
: txn_list(0), savepoint_level(0), savepoint_stmt(0), savepoint_next(0)
|
||||
{
|
||||
DBUG_ENTER("federatedx_txn::federatedx_txn");
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
federatedx_txn::~federatedx_txn()
|
||||
{
|
||||
DBUG_ENTER("federatedx_txn::~federatedx_txn");
|
||||
DBUG_ASSERT(!txn_list);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void federatedx_txn::close(FEDERATEDX_SERVER *server)
|
||||
{
|
||||
uint count= 0;
|
||||
federatedx_io *io, **iop;
|
||||
DBUG_ENTER("federatedx_txn::close");
|
||||
|
||||
DBUG_ASSERT(!server->use_count);
|
||||
DBUG_PRINT("info",("use count: %u connections: %u",
|
||||
server->use_count, server->io_count));
|
||||
|
||||
for (iop= &txn_list; (io= *iop);)
|
||||
{
|
||||
if (io->server != server)
|
||||
iop= &io->txn_next;
|
||||
else
|
||||
{
|
||||
*iop= io->txn_next;
|
||||
io->txn_next= NULL;
|
||||
io->busy= FALSE;
|
||||
|
||||
io->idle_next= server->idle_list;
|
||||
server->idle_list= io;
|
||||
}
|
||||
}
|
||||
|
||||
while ((io= server->idle_list))
|
||||
{
|
||||
server->idle_list= io->idle_next;
|
||||
delete io;
|
||||
count++;
|
||||
}
|
||||
|
||||
DBUG_PRINT("info",("closed %u connections, txn_list: %s", count,
|
||||
txn_list ? "active": "empty"));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::acquire(FEDERATEDX_SHARE *share, bool readonly,
|
||||
federatedx_io **ioptr)
|
||||
{
|
||||
federatedx_io *io;
|
||||
FEDERATEDX_SERVER *server= share->s;
|
||||
DBUG_ENTER("federatedx_txn::acquire");
|
||||
DBUG_ASSERT(ioptr && server);
|
||||
|
||||
if (!(io= *ioptr))
|
||||
{
|
||||
/* check to see if we have an available IO connection */
|
||||
for (io= txn_list; io; io= io->txn_next)
|
||||
if (io->server == server)
|
||||
break;
|
||||
|
||||
if (!io)
|
||||
{
|
||||
/* check to see if there are any unowned IO connections */
|
||||
pthread_mutex_lock(&server->mutex);
|
||||
if ((io= server->idle_list))
|
||||
{
|
||||
server->idle_list= io->idle_next;
|
||||
io->idle_next= NULL;
|
||||
}
|
||||
else
|
||||
io= federatedx_io::construct(&server->mem_root, server);
|
||||
|
||||
io->txn_next= txn_list;
|
||||
txn_list= io;
|
||||
|
||||
pthread_mutex_unlock(&server->mutex);
|
||||
}
|
||||
|
||||
if (io->busy)
|
||||
*io->owner_ptr= NULL;
|
||||
|
||||
io->busy= TRUE;
|
||||
io->owner_ptr= ioptr;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(io->busy && io->server == server);
|
||||
|
||||
io->readonly&= readonly;
|
||||
|
||||
DBUG_RETURN((*ioptr= io) ? 0 : -1);
|
||||
}
|
||||
|
||||
|
||||
void federatedx_txn::release(federatedx_io **ioptr)
|
||||
{
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::release");
|
||||
DBUG_ASSERT(ioptr);
|
||||
|
||||
if ((io= *ioptr))
|
||||
{
|
||||
/* mark as available for reuse in this transaction */
|
||||
io->busy= FALSE;
|
||||
*ioptr= NULL;
|
||||
|
||||
DBUG_PRINT("info", ("active: %d autocommit: %d",
|
||||
io->active, io->is_autocommit()));
|
||||
|
||||
if (io->is_autocommit())
|
||||
io->active= FALSE;
|
||||
}
|
||||
|
||||
release_scan();
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void federatedx_txn::release_scan()
|
||||
{
|
||||
uint count= 0, returned= 0;
|
||||
federatedx_io *io, **pio;
|
||||
DBUG_ENTER("federatedx_txn::release_scan");
|
||||
|
||||
/* return any inactive and idle connections to the server */
|
||||
for (pio= &txn_list; (io= *pio); count++)
|
||||
{
|
||||
if (io->active || io->busy)
|
||||
pio= &io->txn_next;
|
||||
else
|
||||
{
|
||||
FEDERATEDX_SERVER *server= io->server;
|
||||
|
||||
/* unlink from list of connections bound to the transaction */
|
||||
*pio= io->txn_next;
|
||||
io->txn_next= NULL;
|
||||
|
||||
/* reset some values */
|
||||
io->readonly= TRUE;
|
||||
|
||||
pthread_mutex_lock(&server->mutex);
|
||||
io->idle_next= server->idle_list;
|
||||
server->idle_list= io;
|
||||
pthread_mutex_unlock(&server->mutex);
|
||||
returned++;
|
||||
}
|
||||
}
|
||||
DBUG_PRINT("info",("returned %u of %u connections(s)", returned, count));
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_txn::txn_begin()
|
||||
{
|
||||
ulong level= 0;
|
||||
DBUG_ENTER("federatedx_txn::txn_begin");
|
||||
|
||||
if (savepoint_next == 0)
|
||||
{
|
||||
savepoint_next++;
|
||||
savepoint_level= savepoint_stmt= 0;
|
||||
sp_acquire(&level);
|
||||
}
|
||||
|
||||
DBUG_RETURN(level == 1);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::txn_commit()
|
||||
{
|
||||
int error= 0;
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::txn_commit");
|
||||
|
||||
if (savepoint_next)
|
||||
{
|
||||
DBUG_ASSERT(savepoint_stmt != 1);
|
||||
|
||||
for (io= txn_list; io; io= io->txn_next)
|
||||
{
|
||||
int rc= 0;
|
||||
|
||||
if (io->active)
|
||||
rc= io->commit();
|
||||
else
|
||||
io->rollback();
|
||||
|
||||
if (io->active && rc)
|
||||
error= -1;
|
||||
|
||||
io->reset();
|
||||
}
|
||||
|
||||
release_scan();
|
||||
|
||||
savepoint_next= savepoint_stmt= savepoint_level= 0;
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::txn_rollback()
|
||||
{
|
||||
int error= 0;
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::txn_commit");
|
||||
|
||||
if (savepoint_next)
|
||||
{
|
||||
DBUG_ASSERT(savepoint_stmt != 1);
|
||||
|
||||
for (io= txn_list; io; io= io->txn_next)
|
||||
{
|
||||
int rc= io->rollback();
|
||||
|
||||
if (io->active && rc)
|
||||
error= -1;
|
||||
|
||||
io->reset();
|
||||
}
|
||||
|
||||
release_scan();
|
||||
|
||||
savepoint_next= savepoint_stmt= savepoint_level= 0;
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_txn::sp_acquire(ulong *sp)
|
||||
{
|
||||
bool rc= FALSE;
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::sp_acquire");
|
||||
DBUG_ASSERT(sp && savepoint_next);
|
||||
|
||||
*sp= savepoint_level= savepoint_next++;
|
||||
|
||||
for (io= txn_list; io; io= io->txn_next)
|
||||
{
|
||||
if (io->readonly)
|
||||
continue;
|
||||
|
||||
io->savepoint_set(savepoint_level);
|
||||
rc= TRUE;
|
||||
}
|
||||
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::sp_rollback(ulong *sp)
|
||||
{
|
||||
ulong level, new_level= savepoint_level;
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::sp_rollback");
|
||||
DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
|
||||
|
||||
for (io= txn_list; io; io= io->txn_next)
|
||||
{
|
||||
if (io->readonly)
|
||||
continue;
|
||||
|
||||
if ((level= io->savepoint_rollback(*sp)) < new_level)
|
||||
new_level= level;
|
||||
}
|
||||
|
||||
savepoint_level= new_level;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::sp_release(ulong *sp)
|
||||
{
|
||||
ulong level, new_level= savepoint_level;
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::sp_release");
|
||||
DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level);
|
||||
|
||||
for (io= txn_list; io; io= io->txn_next)
|
||||
{
|
||||
if (io->readonly)
|
||||
continue;
|
||||
|
||||
if ((level= io->savepoint_release(*sp)) < new_level)
|
||||
new_level= level;
|
||||
}
|
||||
|
||||
savepoint_level= new_level;
|
||||
*sp= 0;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
bool federatedx_txn::stmt_begin()
|
||||
{
|
||||
bool result= FALSE;
|
||||
DBUG_ENTER("federatedx_txn::stmt_begin");
|
||||
|
||||
if (!savepoint_stmt)
|
||||
{
|
||||
if (!savepoint_next)
|
||||
{
|
||||
savepoint_next++;
|
||||
savepoint_level= savepoint_stmt= 0;
|
||||
}
|
||||
result= sp_acquire(&savepoint_stmt);
|
||||
}
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::stmt_commit()
|
||||
{
|
||||
int result= 0;
|
||||
DBUG_ENTER("federatedx_txn::stmt_commit");
|
||||
|
||||
if (savepoint_stmt == 1)
|
||||
{
|
||||
savepoint_stmt= 0;
|
||||
result= txn_commit();
|
||||
}
|
||||
else
|
||||
if (savepoint_stmt)
|
||||
result= sp_release(&savepoint_stmt);
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
int federatedx_txn::stmt_rollback()
|
||||
{
|
||||
int result= 0;
|
||||
DBUG_ENTER("federated:txn::stmt_rollback");
|
||||
|
||||
if (savepoint_stmt == 1)
|
||||
{
|
||||
savepoint_stmt= 0;
|
||||
result= txn_rollback();
|
||||
}
|
||||
else
|
||||
if (savepoint_stmt)
|
||||
{
|
||||
result= sp_rollback(&savepoint_stmt);
|
||||
sp_release(&savepoint_stmt);
|
||||
}
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
|
||||
void federatedx_txn::stmt_autocommit()
|
||||
{
|
||||
federatedx_io *io;
|
||||
DBUG_ENTER("federatedx_txn::stmt_autocommit");
|
||||
|
||||
for (io= txn_list; savepoint_stmt && io; io= io->txn_next)
|
||||
{
|
||||
if (io->readonly)
|
||||
continue;
|
||||
|
||||
io->savepoint_restrict(savepoint_stmt);
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
3483
storage/federatedx/ha_federatedx.cc
Normal file
3483
storage/federatedx/ha_federatedx.cc
Normal file
File diff suppressed because it is too large
Load diff
446
storage/federatedx/ha_federatedx.h
Normal file
446
storage/federatedx/ha_federatedx.h
Normal file
|
@ -0,0 +1,446 @@
|
|||
/*
|
||||
Copyright (c) 2008, Patrick Galbraith
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Patrick Galbraith nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
class federatedx_io;
|
||||
|
||||
/*
|
||||
FEDERATEDX_SERVER will eventually be a structure that will be shared among
|
||||
all FEDERATEDX_SHARE instances so that the federated server can minimise
|
||||
the number of open connections. This will eventually lead to the support
|
||||
of reliable XA federated tables.
|
||||
*/
|
||||
typedef struct st_fedrated_server {
|
||||
MEM_ROOT mem_root;
|
||||
uint use_count, io_count;
|
||||
|
||||
uchar *key;
|
||||
uint key_length;
|
||||
|
||||
const char *scheme;
|
||||
const char *hostname;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *database;
|
||||
const char *socket;
|
||||
ushort port;
|
||||
|
||||
const char *csname;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
federatedx_io *idle_list;
|
||||
} FEDERATEDX_SERVER;
|
||||
|
||||
/*
|
||||
Please read ha_exmple.cc before reading this file.
|
||||
Please keep in mind that the federatedx storage engine implements all methods
|
||||
that are required to be implemented. handler.h has a full list of methods
|
||||
that you can implement.
|
||||
*/
|
||||
|
||||
#ifdef USE_PRAGMA_INTERFACE
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
/*
|
||||
handler::print_error has a case statement for error numbers.
|
||||
This value is (10000) is far out of range and will envoke the
|
||||
default: case.
|
||||
(Current error range is 120-159 from include/my_base.h)
|
||||
*/
|
||||
#define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000
|
||||
|
||||
#define FEDERATEDX_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5
|
||||
#define FEDERATEDX_RECORDS_IN_RANGE 2
|
||||
#define FEDERATEDX_MAX_KEY_LENGTH 3500 // Same as innodb
|
||||
|
||||
/*
|
||||
FEDERATEDX_SHARE is a structure that will be shared amoung all open handlers
|
||||
The example implements the minimum of what you will probably need.
|
||||
*/
|
||||
typedef struct st_federatedx_share {
|
||||
MEM_ROOT mem_root;
|
||||
|
||||
bool parsed;
|
||||
/* this key is unique db/tablename */
|
||||
const char *share_key;
|
||||
/*
|
||||
the primary select query to be used in rnd_init
|
||||
*/
|
||||
char *select_query;
|
||||
/*
|
||||
remote host info, parse_url supplies
|
||||
*/
|
||||
char *server_name;
|
||||
char *connection_string;
|
||||
char *scheme;
|
||||
char *hostname;
|
||||
char *username;
|
||||
char *password;
|
||||
char *database;
|
||||
char *table_name;
|
||||
char *table;
|
||||
char *socket;
|
||||
char *sport;
|
||||
int share_key_length;
|
||||
ushort port;
|
||||
|
||||
uint table_name_length, server_name_length, connect_string_length;
|
||||
uint use_count;
|
||||
THR_LOCK lock;
|
||||
FEDERATEDX_SERVER *s;
|
||||
} FEDERATEDX_SHARE;
|
||||
|
||||
|
||||
typedef struct st_federatedx_result FEDERATEDX_IO_RESULT;
|
||||
typedef struct st_federatedx_row FEDERATEDX_IO_ROW;
|
||||
typedef ptrdiff_t FEDERATEDX_IO_OFFSET;
|
||||
|
||||
class federatedx_io
|
||||
{
|
||||
friend class federatedx_txn;
|
||||
FEDERATEDX_SERVER * const server;
|
||||
federatedx_io **owner_ptr;
|
||||
federatedx_io *txn_next;
|
||||
federatedx_io *idle_next;
|
||||
bool active; /* currently participating in a transaction */
|
||||
bool busy; /* in use by a ha_federated instance */
|
||||
bool readonly;/* indicates that no updates have occurred */
|
||||
|
||||
protected:
|
||||
void set_active(bool new_active)
|
||||
{ active= new_active; }
|
||||
public:
|
||||
federatedx_io(FEDERATEDX_SERVER *);
|
||||
virtual ~federatedx_io();
|
||||
|
||||
bool is_readonly() const { return readonly; }
|
||||
bool is_active() const { return active; }
|
||||
|
||||
const char * get_charsetname() const
|
||||
{ return server->csname ? server->csname : "latin1"; }
|
||||
|
||||
const char * get_hostname() const { return server->hostname; }
|
||||
const char * get_username() const { return server->username; }
|
||||
const char * get_password() const { return server->password; }
|
||||
const char * get_database() const { return server->database; }
|
||||
ushort get_port() const { return server->port; }
|
||||
const char * get_socket() const { return server->socket; }
|
||||
|
||||
static bool handles_scheme(const char *scheme);
|
||||
static federatedx_io *construct(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server);
|
||||
|
||||
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
|
||||
{ return alloc_root(mem_root, size); }
|
||||
static void operator delete(void *ptr, size_t size)
|
||||
{ TRASH(ptr, size); }
|
||||
|
||||
virtual int query(const char *buffer, uint length)=0;
|
||||
virtual FEDERATEDX_IO_RESULT *store_result()=0;
|
||||
|
||||
virtual size_t max_query_size() const=0;
|
||||
|
||||
virtual my_ulonglong affected_rows() const=0;
|
||||
virtual my_ulonglong last_insert_id() const=0;
|
||||
|
||||
virtual int error_code()=0;
|
||||
virtual const char *error_str()=0;
|
||||
|
||||
virtual void reset()=0;
|
||||
virtual int commit()=0;
|
||||
virtual int rollback()=0;
|
||||
|
||||
virtual int savepoint_set(ulong sp)=0;
|
||||
virtual ulong savepoint_release(ulong sp)=0;
|
||||
virtual ulong savepoint_rollback(ulong sp)=0;
|
||||
virtual void savepoint_restrict(ulong sp)=0;
|
||||
|
||||
virtual ulong last_savepoint() const=0;
|
||||
virtual ulong actual_savepoint() const=0;
|
||||
virtual bool is_autocommit() const=0;
|
||||
|
||||
virtual bool table_metadata(ha_statistics *stats, const char *table_name,
|
||||
uint table_name_length, uint flag) = 0;
|
||||
|
||||
/* resultset operations */
|
||||
|
||||
virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0;
|
||||
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0;
|
||||
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0;
|
||||
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result)=0;
|
||||
virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result)=0;
|
||||
virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column)=0;
|
||||
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
|
||||
unsigned int column) const=0;
|
||||
};
|
||||
|
||||
|
||||
class federatedx_txn
|
||||
{
|
||||
federatedx_io *txn_list;
|
||||
ulong savepoint_level;
|
||||
ulong savepoint_stmt;
|
||||
ulong savepoint_next;
|
||||
|
||||
void release_scan();
|
||||
public:
|
||||
federatedx_txn();
|
||||
~federatedx_txn();
|
||||
|
||||
bool has_connections() const { return txn_list != NULL; }
|
||||
bool in_transaction() const { return savepoint_next != 0; }
|
||||
int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io);
|
||||
void release(federatedx_io **io);
|
||||
void close(FEDERATEDX_SERVER *);
|
||||
|
||||
bool txn_begin();
|
||||
int txn_commit();
|
||||
int txn_rollback();
|
||||
|
||||
bool sp_acquire(ulong *save);
|
||||
int sp_rollback(ulong *save);
|
||||
int sp_release(ulong *save);
|
||||
|
||||
bool stmt_begin();
|
||||
int stmt_commit();
|
||||
int stmt_rollback();
|
||||
void stmt_autocommit();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Class definition for the storage engine
|
||||
*/
|
||||
class ha_federatedx: public handler
|
||||
{
|
||||
friend int federatedx_db_init(void *p);
|
||||
|
||||
THR_LOCK_DATA lock; /* MySQL lock */
|
||||
FEDERATEDX_SHARE *share; /* Shared lock info */
|
||||
federatedx_txn *txn;
|
||||
federatedx_io *io;
|
||||
FEDERATEDX_IO_RESULT *stored_result;
|
||||
uint fetch_num; // stores the fetch num
|
||||
FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position()
|
||||
int remote_error_number;
|
||||
char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE];
|
||||
bool ignore_duplicates, replace_duplicates;
|
||||
bool insert_dup_update;
|
||||
DYNAMIC_STRING bulk_insert;
|
||||
|
||||
private:
|
||||
/*
|
||||
return 0 on success
|
||||
return errorcode otherwise
|
||||
*/
|
||||
uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row,
|
||||
FEDERATEDX_IO_RESULT *result);
|
||||
bool create_where_from_key(String *to, KEY *key_info,
|
||||
const key_range *start_key,
|
||||
const key_range *end_key,
|
||||
bool records_in_range, bool eq_range);
|
||||
int stash_remote_error();
|
||||
|
||||
federatedx_txn *get_txn(THD *thd, bool no_create= FALSE);
|
||||
|
||||
static int disconnect(handlerton *hton, MYSQL_THD thd);
|
||||
static int savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv);
|
||||
static int savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv);
|
||||
static int savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv);
|
||||
static int commit(handlerton *hton, MYSQL_THD thd, bool all);
|
||||
static int rollback(handlerton *hton, MYSQL_THD thd, bool all);
|
||||
|
||||
bool append_stmt_insert(String *query);
|
||||
|
||||
int read_next(uchar *buf, FEDERATEDX_IO_RESULT *result);
|
||||
int index_read_idx_with_result_set(uchar *buf, uint index,
|
||||
const uchar *key,
|
||||
uint key_len,
|
||||
ha_rkey_function find_flag,
|
||||
FEDERATEDX_IO_RESULT **result);
|
||||
int real_query(const char *query, uint length);
|
||||
int real_connect(FEDERATEDX_SHARE *my_share, uint create_flag);
|
||||
public:
|
||||
ha_federatedx(handlerton *hton, TABLE_SHARE *table_arg);
|
||||
~ha_federatedx() {}
|
||||
/* The name that will be used for display purposes */
|
||||
const char *table_type() const { return "FEDERATED"; }
|
||||
/*
|
||||
The name of the index type that will be used for display
|
||||
don't implement this method unless you really have indexes
|
||||
*/
|
||||
// perhaps get index type
|
||||
const char *index_type(uint inx) { return "REMOTE"; }
|
||||
const char **bas_ext() const;
|
||||
/*
|
||||
This is a list of flags that says what the storage engine
|
||||
implements. The current table flags are documented in
|
||||
handler.h
|
||||
*/
|
||||
ulonglong table_flags() const
|
||||
{
|
||||
/* fix server to be able to get remote server table flags */
|
||||
return (HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED
|
||||
| HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS |
|
||||
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
|
||||
HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
|
||||
HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
|
||||
}
|
||||
/*
|
||||
This is a bitmap of flags that says how the storage engine
|
||||
implements indexes. The current index flags are documented in
|
||||
handler.h. If you do not implement indexes, just return zero
|
||||
here.
|
||||
|
||||
part is the key part to check. First key part is 0
|
||||
If all_parts it's set, MySQL want to know the flags for the combined
|
||||
index up to and including 'part'.
|
||||
*/
|
||||
/* fix server to be able to get remote server index flags */
|
||||
ulong index_flags(uint inx, uint part, bool all_parts) const
|
||||
{
|
||||
return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
|
||||
}
|
||||
uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
|
||||
uint max_supported_keys() const { return MAX_KEY; }
|
||||
uint max_supported_key_parts() const { return MAX_REF_PARTS; }
|
||||
uint max_supported_key_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
|
||||
uint max_supported_key_part_length() const { return FEDERATEDX_MAX_KEY_LENGTH; }
|
||||
/*
|
||||
Called in test_quick_select to determine if indexes should be used.
|
||||
Normally, we need to know number of blocks . For federatedx we need to
|
||||
know number of blocks on remote side, and number of packets and blocks
|
||||
on the network side (?)
|
||||
Talk to Kostja about this - how to get the
|
||||
number of rows * ...
|
||||
disk scan time on other side (block size, size of the row) + network time ...
|
||||
The reason for "records * 1000" is that such a large number forces
|
||||
this to use indexes "
|
||||
*/
|
||||
double scan_time()
|
||||
{
|
||||
DBUG_PRINT("info", ("records %lu", (ulong) stats.records));
|
||||
return (double)(stats.records*1000);
|
||||
}
|
||||
/*
|
||||
The next method will never be called if you do not implement indexes.
|
||||
*/
|
||||
double read_time(uint index, uint ranges, ha_rows rows)
|
||||
{
|
||||
/*
|
||||
Per Brian, this number is bugus, but this method must be implemented,
|
||||
and at a later date, he intends to document this issue for handler code
|
||||
*/
|
||||
return (double) rows / 20.0+1;
|
||||
}
|
||||
|
||||
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
|
||||
/*
|
||||
Everything below are methods that we implment in ha_federatedx.cc.
|
||||
|
||||
Most of these methods are not obligatory, skip them and
|
||||
MySQL will treat them as not implemented
|
||||
*/
|
||||
int open(const char *name, int mode, uint test_if_locked); // required
|
||||
int close(void); // required
|
||||
|
||||
void start_bulk_insert(ha_rows rows);
|
||||
int end_bulk_insert(bool abort);
|
||||
int write_row(uchar *buf);
|
||||
int update_row(const uchar *old_data, uchar *new_data);
|
||||
int delete_row(const uchar *buf);
|
||||
int index_init(uint keynr, bool sorted);
|
||||
ha_rows estimate_rows_upper_bound();
|
||||
int index_read(uchar *buf, const uchar *key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_idx(uchar *buf, uint idx, const uchar *key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_next(uchar *buf);
|
||||
int index_end();
|
||||
int read_range_first(const key_range *start_key,
|
||||
const key_range *end_key,
|
||||
bool eq_range, bool sorted);
|
||||
int read_range_next();
|
||||
/*
|
||||
unlike index_init(), rnd_init() can be called two times
|
||||
without rnd_end() in between (it only makes sense if scan=1).
|
||||
then the second call should prepare for the new table scan
|
||||
(e.g if rnd_init allocates the cursor, second call should
|
||||
position it to the start of the table, no need to deallocate
|
||||
and allocate it again
|
||||
*/
|
||||
int rnd_init(bool scan); //required
|
||||
int rnd_end();
|
||||
int rnd_next(uchar *buf); //required
|
||||
int rnd_pos(uchar *buf, uchar *pos); //required
|
||||
void position(const uchar *record); //required
|
||||
int info(uint); //required
|
||||
int extra(ha_extra_function operation);
|
||||
|
||||
void update_auto_increment(void);
|
||||
int repair(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
|
||||
int delete_all_rows(void);
|
||||
int create(const char *name, TABLE *form,
|
||||
HA_CREATE_INFO *create_info); //required
|
||||
ha_rows records_in_range(uint inx, key_range *start_key,
|
||||
key_range *end_key);
|
||||
uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
|
||||
|
||||
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
|
||||
enum thr_lock_type lock_type); //required
|
||||
bool get_error_message(int error, String *buf);
|
||||
int start_stmt(THD *thd, thr_lock_type lock_type);
|
||||
int external_lock(THD *thd, int lock_type);
|
||||
int reset(void);
|
||||
int free_result(void);
|
||||
};
|
||||
|
||||
extern const char ident_quote_char; // Character for quoting
|
||||
// identifiers
|
||||
extern const char value_quote_char; // Character for quoting
|
||||
// literals
|
||||
|
||||
extern bool append_ident(String *string, const char *name, uint length,
|
||||
const char quote_char);
|
||||
|
||||
|
||||
extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server);
|
||||
extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
|
||||
FEDERATEDX_SERVER *server);
|
5
storage/federatedx/plug.in
Normal file
5
storage/federatedx/plug.in
Normal file
|
@ -0,0 +1,5 @@
|
|||
MYSQL_STORAGE_ENGINE(federated,,[FederatedX Storage Engine],
|
||||
[FederatedX Storage Engine], [max,max-no-ndb])
|
||||
MYSQL_PLUGIN_DYNAMIC(federated, [ha_federatedx.la])
|
||||
MYSQL_PLUGIN_STATIC(federated, [libfederatedx.a])
|
||||
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federatedx.cc])
|
Loading…
Add table
Reference in a new issue