Browse Source
Added federatedx storage engine
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 Linux machine storage/pbxt/src/cache_xt.cc: Fixed compile warning storage/xtradb/include/buf0buf.ic: Fixed compiler warningpull/843/head
36 changed files with 5669 additions and 57 deletions
-
2client/mysqladmin.cc
-
2extra/yassl/taocrypt/src/twofish.cpp
-
2libmysqld/Makefile.am
-
1mysql-test/mysql-test-run.pl
-
3mysql-test/suite/federated/disabled.def
-
32mysql-test/suite/federated/federated.result
-
14mysql-test/suite/federated/federated.test
-
4mysql-test/suite/federated/federated_archive.result
-
4mysql-test/suite/federated/federated_bug_13118.result
-
4mysql-test/suite/federated/federated_bug_25714.result
-
4mysql-test/suite/federated/federated_cleanup.inc
-
4mysql-test/suite/federated/federated_innodb.result
-
4mysql-test/suite/federated/federated_server.result
-
9mysql-test/suite/federated/federated_server.test
-
9mysql-test/suite/federated/federated_transactions.result
-
14mysql-test/valgrind.supp
-
7storage/federated/README
-
0storage/federated/plug.in.disabled
-
11storage/federatedx/AUTHORS
-
3storage/federatedx/CMakeFiles.txt
-
18storage/federatedx/ChangeLog
-
40storage/federatedx/FAQ
-
64storage/federatedx/Makefile.am
-
33storage/federatedx/README
-
23storage/federatedx/README.windows
-
30storage/federatedx/TODO
-
103storage/federatedx/federatedx_io.cc
-
592storage/federatedx/federatedx_io_mysql.cc
-
277storage/federatedx/federatedx_io_null.cc
-
45storage/federatedx/federatedx_probes.h
-
424storage/federatedx/federatedx_txn.cc
-
3487storage/federatedx/ha_federatedx.cc
-
446storage/federatedx/ha_federatedx.h
-
5storage/federatedx/plug.in
-
4storage/pbxt/src/cache_xt.cc
-
2storage/xtradb/include/buf0buf.ic
@ -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 |
|||
@ -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. |
|||
@ -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 |
|||
@ -0,0 +1,3 @@ |
|||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") |
|||
SET(FEDERATED_SOURCES ha_federatedx.cc) |
|||
MYSQL_STORAGE_ENGINE(FEDERATED) |
|||
@ -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 |
|||
@ -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) |
|||
@ -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.% |
|||
@ -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 |
|||
|
|||
@ -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) |
|||
@ -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 |
|||
@ -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); |
|||
} |
|||
|
|||
|
|||
@ -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; |
|||
} |
|||
@ -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; |
|||
} |
|||
@ -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 */ |
|||
@ -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; |
|||
} |
|||
|
|||
|
|||
3487
storage/federatedx/ha_federatedx.cc
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View 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); |
|||
@ -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]) |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue