Commit 8cebc6e7 authored by joreland@mysql.com's avatar joreland@mysql.com

Merge joreland@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/home/jonas/src/mysql-5.0
parents 0ca5b563 59e156ba
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_FEDERATED
dnl Sets HAVE_FEDERATED if --with-federated-storage-engine is used
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_FEDERATED], [
AC_ARG_WITH([federated-storage-engine],
[
--with-federated-storage-engine
Enable the MySQL Storage Engine],
[federateddb="$withval"],
[federateddb=no])
AC_MSG_CHECKING([for MySQL federated storage engine])
case "$federateddb" in
yes )
AC_DEFINE([HAVE_FEDERATED_DB], [1], [Define to enable Federated Handler])
AC_MSG_RESULT([yes])
[federateddb=yes]
;;
* )
AC_MSG_RESULT([no])
[federateddb=no]
;;
esac
])
dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_FEDERATED SECTION
dnl ---------------------------------------------------------------------------
...@@ -38,6 +38,7 @@ sinclude(config/ac-macros/compiler_flag.m4) ...@@ -38,6 +38,7 @@ sinclude(config/ac-macros/compiler_flag.m4)
sinclude(config/ac-macros/ha_archive.m4) sinclude(config/ac-macros/ha_archive.m4)
sinclude(config/ac-macros/ha_berkeley.m4) sinclude(config/ac-macros/ha_berkeley.m4)
sinclude(config/ac-macros/ha_example.m4) sinclude(config/ac-macros/ha_example.m4)
sinclude(config/ac-macros/ha_federated.m4)
sinclude(config/ac-macros/ha_innodb.m4) sinclude(config/ac-macros/ha_innodb.m4)
sinclude(config/ac-macros/ha_isam.m4) sinclude(config/ac-macros/ha_isam.m4)
sinclude(config/ac-macros/ha_ndbcluster.m4) sinclude(config/ac-macros/ha_ndbcluster.m4)
...@@ -2420,6 +2421,7 @@ MYSQL_CHECK_EXAMPLEDB ...@@ -2420,6 +2421,7 @@ MYSQL_CHECK_EXAMPLEDB
MYSQL_CHECK_ARCHIVEDB MYSQL_CHECK_ARCHIVEDB
MYSQL_CHECK_CSVDB MYSQL_CHECK_CSVDB
MYSQL_CHECK_NDBCLUSTER MYSQL_CHECK_NDBCLUSTER
MYSQL_CHECK_FEDERATED
# If we have threads generate some library functions and test programs # If we have threads generate some library functions and test programs
sql_server_dirs= sql_server_dirs=
......
-- require r/have_federated_db.require
disable_query_log;
show variables like "have_federated_db";
enable_query_log;
...@@ -1347,7 +1347,7 @@ run_testcase () ...@@ -1347,7 +1347,7 @@ run_testcase ()
tsrcdir=$TESTDIR/$tname-src tsrcdir=$TESTDIR/$tname-src
result_file="r/$tname.result" result_file="r/$tname.result"
echo $tname > $CURRENT_TEST echo $tname > $CURRENT_TEST
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0` SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0 \& \( $tname : federated \) = 0`
if [ -n "$RESULT_EXT" -a \( x$RECORD = x1 -o -f "$result_file$RESULT_EXT" \) ] ; then if [ -n "$RESULT_EXT" -a \( x$RECORD = x1 -o -f "$result_file$RESULT_EXT" \) ] ; then
result_file="$result_file$RESULT_EXT" result_file="$result_file$RESULT_EXT"
fi fi
......
This diff is collapsed.
This diff is collapsed.
Variable_name Value
have_federated_db YES
...@@ -325,6 +325,7 @@ NDB YES/NO Alias for NDBCLUSTER ...@@ -325,6 +325,7 @@ NDB YES/NO Alias for NDBCLUSTER
EXAMPLE YES/NO Example storage engine EXAMPLE YES/NO Example storage engine
ARCHIVE YES/NO Archive storage engine ARCHIVE YES/NO Archive storage engine
CSV YES/NO CSV storage engine CSV YES/NO CSV storage engine
FEDERATED YES/NO Federated MySQL storage engine
drop table if exists t5; drop table if exists t5;
prepare stmt1 from ' drop table if exists t5 ' ; prepare stmt1 from ' drop table if exists t5 ' ;
execute stmt1 ; execute stmt1 ;
......
...@@ -1299,6 +1299,8 @@ INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); ...@@ -1299,6 +1299,8 @@ INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
SELECT * FROM t2; SELECT * FROM t2;
OPTIMIZE TABLE t2; OPTIMIZE TABLE t2;
SELECT * FROM t2; SELECT * FROM t2;
REPAIR TABLE t2;
SELECT * FROM t2;
# #
# Test bulk inserts # Test bulk inserts
......
This diff is collapsed.
...@@ -38,6 +38,18 @@ ...@@ -38,6 +38,18 @@
Command *parse_command(Command_factory * factory, const char *text); Command *parse_command(Command_factory * factory, const char *text);
Mysql_connection_thread_args::Mysql_connection_thread_args(
struct st_vio *vio_arg,
Thread_registry &thread_registry_arg,
const User_map &user_map_arg,
ulong connection_id_arg,
Instance_map &instance_map_arg) :
vio(vio_arg)
,thread_registry(thread_registry_arg)
,user_map(user_map_arg)
,connection_id(connection_id_arg)
,instance_map(instance_map_arg)
{}
/* /*
MySQL connection - handle one connection with mysql command line client MySQL connection - handle one connection with mysql command line client
......
...@@ -48,13 +48,7 @@ struct Mysql_connection_thread_args ...@@ -48,13 +48,7 @@ struct Mysql_connection_thread_args
Thread_registry &thread_registry_arg, Thread_registry &thread_registry_arg,
const User_map &user_map_arg, const User_map &user_map_arg,
ulong connection_id_arg, ulong connection_id_arg,
Instance_map &instance_map_arg) : Instance_map &instance_map_arg);
vio(vio_arg)
,thread_registry(thread_registry_arg)
,user_map(user_map_arg)
,connection_id(connection_id_arg)
,instance_map(instance_map_arg)
{}
}; };
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
...@@ -62,7 +62,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ...@@ -62,7 +62,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \ sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
parse_file.h sql_view.h sql_trigger.h \ parse_file.h sql_view.h sql_trigger.h \
examples/ha_example.h examples/ha_archive.h \ examples/ha_example.h examples/ha_archive.h \
examples/ha_tina.h examples/ha_tina.h \
ha_federated.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \
...@@ -98,7 +99,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -98,7 +99,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \ sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
sp_cache.cc parse_file.cc sql_trigger.cc \ sp_cache.cc parse_file.cc sql_trigger.cc \
examples/ha_example.cc examples/ha_archive.cc \ examples/ha_example.cc examples/ha_archive.cc \
examples/ha_tina.cc examples/ha_tina.cc \
ha_federated.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS) gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
mysql_tzinfo_to_sql_SOURCES = mysql_tzinfo_to_sql.cc mysql_tzinfo_to_sql_SOURCES = mysql_tzinfo_to_sql.cc
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#ifdef HAVE_ARCHIVE_DB #ifdef HAVE_ARCHIVE_DB
#include "ha_archive.h" #include "ha_archive.h"
#include <my_dir.h>
/* /*
First, if you want to understand storage engines you should look at First, if you want to understand storage engines you should look at
...@@ -227,8 +228,7 @@ int ha_archive::read_meta_file(File meta_file, ulonglong *rows) ...@@ -227,8 +228,7 @@ int ha_archive::read_meta_file(File meta_file, ulonglong *rows)
/* /*
This method writes out the header of a meta file and returns whether or not it was successful. This method writes out the header of a meta file and returns whether or not it was successful.
By setting dirty you say whether or not the file represents the actual state of the data file. By setting dirty you say whether or not the file represents the actual state of the data file.
Upon ::open() we set to dirty, and upon ::close() we set to clean. If we determine during Upon ::open() we set to dirty, and upon ::close() we set to clean.
a read that the file was dirty we will force a rebuild of this file.
*/ */
int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty) int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty)
{ {
...@@ -305,6 +305,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) ...@@ -305,6 +305,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
share->use_count= 0; share->use_count= 0;
share->table_name_length= length; share->table_name_length= length;
share->table_name= tmp_name; share->table_name= tmp_name;
share->crashed= FALSE;
fn_format(share->data_file_name,table_name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME); fn_format(share->data_file_name,table_name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
fn_format(meta_file_name,table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME); fn_format(meta_file_name,table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
strmov(share->table_name,table_name); strmov(share->table_name,table_name);
...@@ -315,23 +316,14 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) ...@@ -315,23 +316,14 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1) if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1)
goto error; goto error;
if (read_meta_file(share->meta_file, &share->rows_recorded))
{
/*
The problem here is that for some reason, probably a crash, the meta
file has been corrupted. So what do we do? Well we try to rebuild it
ourself. Once that happens, we reread it, but if that fails we just
call it quits and return an error.
*/
if (rebuild_meta_file(share->table_name, share->meta_file))
goto error;
if (read_meta_file(share->meta_file, &share->rows_recorded))
goto error;
}
/* /*
After we read, we set the file to dirty. When we close, we will do the After we read, we set the file to dirty. When we close, we will do the
opposite. opposite. If the meta file will not open we assume it is crashed and
leave it up to the user to fix.
*/ */
if (read_meta_file(share->meta_file, &share->rows_recorded))
share->crashed= TRUE;
else
(void)write_meta_file(share->meta_file, share->rows_recorded, TRUE); (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
/* /*
It is expensive to open and close the data files and since you can't have It is expensive to open and close the data files and since you can't have
...@@ -408,7 +400,7 @@ int ha_archive::open(const char *name, int mode, uint test_if_locked) ...@@ -408,7 +400,7 @@ int ha_archive::open(const char *name, int mode, uint test_if_locked)
DBUG_ENTER("ha_archive::open"); DBUG_ENTER("ha_archive::open");
if (!(share= get_share(name, table))) if (!(share= get_share(name, table)))
DBUG_RETURN(1); DBUG_RETURN(-1);
thr_lock_data_init(&share->lock,&lock,NULL); thr_lock_data_init(&share->lock,&lock,NULL);
if ((archive= gzopen(share->data_file_name, "rb")) == NULL) if ((archive= gzopen(share->data_file_name, "rb")) == NULL)
...@@ -530,6 +522,9 @@ int ha_archive::write_row(byte * buf) ...@@ -530,6 +522,9 @@ int ha_archive::write_row(byte * buf)
z_off_t written; z_off_t written;
DBUG_ENTER("ha_archive::write_row"); DBUG_ENTER("ha_archive::write_row");
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time(); table->timestamp_field->set_time();
...@@ -579,6 +574,9 @@ int ha_archive::rnd_init(bool scan) ...@@ -579,6 +574,9 @@ int ha_archive::rnd_init(bool scan)
DBUG_ENTER("ha_archive::rnd_init"); DBUG_ENTER("ha_archive::rnd_init");
int read; // gzread() returns int, and we use this to check the header int read; // gzread() returns int, and we use this to check the header
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
/* We rewind the file so that we can read from the beginning if scan */ /* We rewind the file so that we can read from the beginning if scan */
if (scan) if (scan)
{ {
...@@ -672,6 +670,9 @@ int ha_archive::rnd_next(byte *buf) ...@@ -672,6 +670,9 @@ int ha_archive::rnd_next(byte *buf)
int rc; int rc;
DBUG_ENTER("ha_archive::rnd_next"); DBUG_ENTER("ha_archive::rnd_next");
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
if (!scan_rows) if (!scan_rows)
DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_RETURN(HA_ERR_END_OF_FILE);
scan_rows--; scan_rows--;
...@@ -722,22 +723,23 @@ int ha_archive::rnd_pos(byte * buf, byte *pos) ...@@ -722,22 +723,23 @@ int ha_archive::rnd_pos(byte * buf, byte *pos)
} }
/* /*
This method rebuilds the meta file. It does this by walking the datafile and This method repairs the meta file. It does this by walking the datafile and
rewriting the meta file. rewriting the meta file.
*/ */
int ha_archive::rebuild_meta_file(char *table_name, File meta_file) int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
{ {
int rc; int rc;
byte *buf; byte *buf;
ulonglong rows_recorded= 0; ulonglong rows_recorded= 0;
gzFile rebuild_file; /* Archive file we are working with */ gzFile rebuild_file; // Archive file we are working with
File meta_file; // Meta file we use
char data_file_name[FN_REFLEN]; char data_file_name[FN_REFLEN];
DBUG_ENTER("ha_archive::rebuild_meta_file"); DBUG_ENTER("ha_archive::repair");
/* /*
Open up the meta file to recreate it. Open up the meta file to recreate it.
*/ */
fn_format(data_file_name, table_name, "", ARZ, fn_format(data_file_name, share->table_name, "", ARZ,
MY_REPLACE_EXT|MY_UNPACK_FILENAME); MY_REPLACE_EXT|MY_UNPACK_FILENAME);
if ((rebuild_file= gzopen(data_file_name, "rb")) == NULL) if ((rebuild_file= gzopen(data_file_name, "rb")) == NULL)
DBUG_RETURN(errno ? errno : -1); DBUG_RETURN(errno ? errno : -1);
...@@ -767,11 +769,18 @@ int ha_archive::rebuild_meta_file(char *table_name, File meta_file) ...@@ -767,11 +769,18 @@ int ha_archive::rebuild_meta_file(char *table_name, File meta_file)
*/ */
if (rc == HA_ERR_END_OF_FILE) if (rc == HA_ERR_END_OF_FILE)
{ {
(void)write_meta_file(meta_file, rows_recorded, FALSE); fn_format(data_file_name,share->table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
if ((meta_file= my_open(data_file_name, O_RDWR, MYF(0))) == -1)
{
rc= HA_ERR_CRASHED_ON_USAGE;
goto error;
}
(void)write_meta_file(meta_file, rows_recorded, TRUE);
rc= 0; rc= 0;
} }
my_free((gptr) buf, MYF(0)); my_free((gptr) buf, MYF(0));
share->crashed= FALSE;
error: error:
gzclose(rebuild_file); gzclose(rebuild_file);
...@@ -790,13 +799,14 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -790,13 +799,14 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
char block[IO_SIZE]; char block[IO_SIZE];
char writer_filename[FN_REFLEN]; char writer_filename[FN_REFLEN];
/* Closing will cause all data waiting to be flushed */
gzclose(share->archive_write);
share->archive_write= NULL;
/* Lets create a file to contain the new data */ /* Lets create a file to contain the new data */
fn_format(writer_filename, share->table_name, "", ARN, fn_format(writer_filename, share->table_name, "", ARN,
MY_REPLACE_EXT|MY_UNPACK_FILENAME); MY_REPLACE_EXT|MY_UNPACK_FILENAME);
/* Closing will cause all data waiting to be flushed, to be flushed */
gzclose(share->archive_write);
if ((reader= gzopen(share->data_file_name, "rb")) == NULL) if ((reader= gzopen(share->data_file_name, "rb")) == NULL)
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -814,16 +824,6 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -814,16 +824,6 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
my_rename(writer_filename,share->data_file_name,MYF(0)); my_rename(writer_filename,share->data_file_name,MYF(0));
/*
We reopen the file in case some IO is waiting to go through.
In theory the table is closed right after this operation,
but it is possible for IO to still happen.
I may be being a bit too paranoid right here.
*/
if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
DBUG_RETURN(errno ? errno : -1);
share->dirty= FALSE;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -880,13 +880,27 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd, ...@@ -880,13 +880,27 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
void ha_archive::info(uint flag) void ha_archive::info(uint flag)
{ {
DBUG_ENTER("ha_archive::info"); DBUG_ENTER("ha_archive::info");
/* /*
This should be an accurate number now, though bulk and delayed inserts can This should be an accurate number now, though bulk and delayed inserts can
cause the number to be inaccurate. cause the number to be inaccurate.
*/ */
records= share->rows_recorded; records= share->rows_recorded;
deleted= 0; deleted= 0;
/* Costs quite a bit more to get all information */
if (flag & HA_STATUS_TIME)
{
MY_STAT file_stat; // Stat information for the data file
VOID(my_stat(share->data_file_name, &file_stat, MYF(MY_WME)));
mean_rec_length= table->reclength + buffer.alloced_length();
data_file_length= file_stat.st_size;
create_time= file_stat.st_ctime;
update_time= file_stat.st_mtime;
max_data_file_length= share->rows_recorded * mean_rec_length;
}
delete_length= 0;
index_file_length=0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -900,7 +914,7 @@ void ha_archive::info(uint flag) ...@@ -900,7 +914,7 @@ void ha_archive::info(uint flag)
*/ */
void ha_archive::start_bulk_insert(ha_rows rows) void ha_archive::start_bulk_insert(ha_rows rows)
{ {
DBUG_ENTER("ha_archive::info"); DBUG_ENTER("ha_archive::start_bulk_insert");
bulk_insert= TRUE; bulk_insert= TRUE;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -912,6 +926,7 @@ void ha_archive::start_bulk_insert(ha_rows rows) ...@@ -912,6 +926,7 @@ void ha_archive::start_bulk_insert(ha_rows rows)
*/ */
int ha_archive::end_bulk_insert() int ha_archive::end_bulk_insert()
{ {
DBUG_ENTER("ha_archive::end_bulk_insert");
bulk_insert= FALSE; bulk_insert= FALSE;
share->dirty= TRUE; share->dirty= TRUE;
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -35,6 +35,7 @@ typedef struct st_archive_share { ...@@ -35,6 +35,7 @@ typedef struct st_archive_share {
File meta_file; /* Meta file we use */ File meta_file; /* Meta file we use */
gzFile archive_write; /* Archive file we are working with */ gzFile archive_write; /* Archive file we are working with */
bool dirty; /* Flag for if a flush should occur */ bool dirty; /* Flag for if a flush should occur */
bool crashed; /* Meta file is crashed */
ulonglong rows_recorded; /* Number of rows in tables */ ulonglong rows_recorded; /* Number of rows in tables */
} ARCHIVE_SHARE; } ARCHIVE_SHARE;
...@@ -91,13 +92,14 @@ class ha_archive: public handler ...@@ -91,13 +92,14 @@ class ha_archive: public handler
int write_meta_file(File meta_file, ulonglong rows, bool dirty); int write_meta_file(File meta_file, ulonglong rows, bool dirty);
ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table); ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table);
int free_share(ARCHIVE_SHARE *share); int free_share(ARCHIVE_SHARE *share);
int rebuild_meta_file(char *table_name, File meta_file); bool auto_repair() const { return 1; } // For the moment we just do this
int read_data_header(gzFile file_to_read); int read_data_header(gzFile file_to_read);
int write_data_header(gzFile file_to_write); int write_data_header(gzFile file_to_write);
void position(const byte *record); void position(const byte *record);
void info(uint); void info(uint);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
void start_bulk_insert(ha_rows rows); void start_bulk_insert(ha_rows rows);
int end_bulk_insert(); int end_bulk_insert();
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
......
...@@ -211,6 +211,15 @@ class Field ...@@ -211,6 +211,15 @@ class Field
ptr-=row_offset; ptr-=row_offset;
return tmp; return tmp;
} }
inline String *val_str(String *str, char *new_ptr)
{
char *old_ptr= ptr;
ptr= new_ptr;
val_str(str);
ptr= old_ptr;
return str;
}
virtual bool send_binary(Protocol *protocol); virtual bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{ {
......
This diff is collapsed.
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Please read ha_exmple.cc before reading this file.
Please keep in mind that the federated storage engine implements all methods
that are required to be implemented. handler.h has a full list of methods
that you can implement.
*/
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
#include <mysql.h>
//#include <client.h>
/*
FEDERATED_SHARE is a structure that will be shared amoung all open handlers
The example implements the minimum of what you will probably need.
*/
//FIX document
typedef struct st_federated_share {
char *table_name;
char *table_base_name;
// the primary select query to be used in rnd_init
char *select_query;
// remote host info, parse_url supplies
char *scheme;
char *hostname;
char *username;
char *password;
char *database;
char *table;
char *socket;
char *sport;
int port;
uint table_name_length,table_base_name_length,use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
} FEDERATED_SHARE;
/*
Class definition for the storage engine
*/
class ha_federated: public handler
{
THR_LOCK_DATA lock; /* MySQL lock */
FEDERATED_SHARE *share; /* Shared lock info */
MYSQL *mysql;
MYSQL_RES *result;
uint ref_length;
uint fetch_num; // stores the fetch num
MYSQL_ROW_OFFSET current_position; // Current position used by ::position()
private:
/*
return 0 on success
return errorcode otherwise
*/
//FIX
uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row);
uint type_quote(int type);
void quote_data(String *string1, Field *field);
public:
ha_federated(TABLE *table): handler(table),
mysql(0),
ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
{
}
~ha_federated()
{
}
/* 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
*/
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
Serg: Double check these (Brian)
// FIX add blob support
*/
ulong table_flags() const
{
return (HA_TABLE_SCAN_ON_INDEX | HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | HA_AUTO_PART_KEY |
HA_TABLE_SCAN_ON_INDEX);
}
/*
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'.
*/
ulong index_flags(uint inx, uint part, bool all_parts) const
{
return (HA_READ_NEXT);
// return (HA_READ_NEXT | HA_ONLY_WHOLE_INDEX);
}
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 1024; }
uint max_supported_key_length() const { return 1024; }
/*
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time() { DBUG_PRINT("ha_federated::scan_time", ("rows %d", records)); return (double)(records*2); }
/*
The next method will never be called if you do not implement indexes.
*/
virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
/*
Everything below are methods that we implment in ha_federated.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
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
int index_init(uint keynr);
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_next(byte * buf);
int index_end();
/*
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(byte *buf); //required
int rnd_pos(byte * buf, byte *pos); //required
void position(const byte *record); //required
void info(uint); //required
int delete_all_rows(void);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); //required
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); //required
};
...@@ -47,6 +47,9 @@ ...@@ -47,6 +47,9 @@
#ifdef HAVE_NDBCLUSTER_DB #ifdef HAVE_NDBCLUSTER_DB
#include "ha_ndbcluster.h" #include "ha_ndbcluster.h"
#endif #endif
#ifdef HAVE_FEDERATED_DB
#include "ha_federated.h"
#endif
#include <myisampack.h> #include <myisampack.h>
#include <errno.h> #include <errno.h>
...@@ -92,6 +95,8 @@ struct show_table_type_st sys_table_types[]= ...@@ -92,6 +95,8 @@ struct show_table_type_st sys_table_types[]=
"Archive storage engine", DB_TYPE_ARCHIVE_DB}, "Archive storage engine", DB_TYPE_ARCHIVE_DB},
{"CSV",&have_csv_db, {"CSV",&have_csv_db,
"CSV storage engine", DB_TYPE_CSV_DB}, "CSV storage engine", DB_TYPE_CSV_DB},
{"FEDERATED",&have_federated_db,
"Federated MySQL storage engine", DB_TYPE_FEDERATED_DB},
{NullS, NULL, NullS, DB_TYPE_UNKNOWN} {NullS, NULL, NullS, DB_TYPE_UNKNOWN}
}; };
...@@ -200,6 +205,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type) ...@@ -200,6 +205,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
case DB_TYPE_ARCHIVE_DB: case DB_TYPE_ARCHIVE_DB:
return new ha_archive(table); return new ha_archive(table);
#endif #endif
#ifdef HAVE_FEDERATED_DB
case DB_TYPE_FEDERATED_DB:
return new ha_federated(table);
#endif
#ifdef HAVE_CSV_DB #ifdef HAVE_CSV_DB
case DB_TYPE_CSV_DB: case DB_TYPE_CSV_DB:
return new ha_tina(table); return new ha_tina(table);
......
...@@ -152,6 +152,7 @@ enum db_type ...@@ -152,6 +152,7 @@ enum db_type
DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB, DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER, DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB, DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
DB_TYPE_FEDERATED_DB,
DB_TYPE_DEFAULT // Must be last DB_TYPE_DEFAULT // Must be last
}; };
......
...@@ -1070,6 +1070,7 @@ extern struct my_option my_long_options[]; ...@@ -1070,6 +1070,7 @@ extern struct my_option my_long_options[];
extern SHOW_COMP_OPTION have_isam, have_innodb, have_berkeley_db; extern SHOW_COMP_OPTION have_isam, have_innodb, have_berkeley_db;
extern SHOW_COMP_OPTION have_example_db, have_archive_db, have_csv_db; extern SHOW_COMP_OPTION have_example_db, have_archive_db, have_csv_db;
extern SHOW_COMP_OPTION have_federated_db;
extern SHOW_COMP_OPTION have_raid, have_openssl, have_symlink; extern SHOW_COMP_OPTION have_raid, have_openssl, have_symlink;
extern SHOW_COMP_OPTION have_query_cache, have_berkeley_db, have_innodb; extern SHOW_COMP_OPTION have_query_cache, have_berkeley_db, have_innodb;
extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
......
...@@ -392,6 +392,7 @@ CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -392,6 +392,7 @@ CHARSET_INFO *national_charset_info, *table_alias_charset;
SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster, SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster,
have_example_db, have_archive_db, have_csv_db; have_example_db, have_archive_db, have_csv_db;
SHOW_COMP_OPTION have_federated_db;
SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache; SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
SHOW_COMP_OPTION have_geometry, have_rtree_keys; SHOW_COMP_OPTION have_geometry, have_rtree_keys;
SHOW_COMP_OPTION have_crypt, have_compress; SHOW_COMP_OPTION have_crypt, have_compress;
...@@ -5793,6 +5794,11 @@ static void mysql_init_variables(void) ...@@ -5793,6 +5794,11 @@ static void mysql_init_variables(void)
#else #else
have_archive_db= SHOW_OPTION_NO; have_archive_db= SHOW_OPTION_NO;
#endif #endif
#ifdef HAVE_FEDERATED_DB
have_federated_db= SHOW_OPTION_YES;
#else
have_federated_db= SHOW_OPTION_NO;
#endif
#ifdef HAVE_CSV_DB #ifdef HAVE_CSV_DB
have_csv_db= SHOW_OPTION_YES; have_csv_db= SHOW_OPTION_YES;
#else #else
......
...@@ -716,6 +716,7 @@ struct show_var_st init_vars[]= { ...@@ -716,6 +716,7 @@ struct show_var_st init_vars[]= {
{"have_crypt", (char*) &have_crypt, SHOW_HAVE}, {"have_crypt", (char*) &have_crypt, SHOW_HAVE},
{"have_csv", (char*) &have_csv_db, SHOW_HAVE}, {"have_csv", (char*) &have_csv_db, SHOW_HAVE},
{"have_example_engine", (char*) &have_example_db, SHOW_HAVE}, {"have_example_engine", (char*) &have_example_db, SHOW_HAVE},
{"have_federated_db", (char*) &have_federated_db, SHOW_HAVE},
{"have_geometry", (char*) &have_geometry, SHOW_HAVE}, {"have_geometry", (char*) &have_geometry, SHOW_HAVE},
{"have_innodb", (char*) &have_innodb, SHOW_HAVE}, {"have_innodb", (char*) &have_innodb, SHOW_HAVE},
{"have_isam", (char*) &have_isam, SHOW_HAVE}, {"have_isam", (char*) &have_isam, SHOW_HAVE},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment