diff options
Diffstat (limited to 'storage/myisammrg')
29 files changed, 2062 insertions, 0 deletions
diff --git a/storage/myisammrg/.cvsignore b/storage/myisammrg/.cvsignore new file mode 100644 index 00000000000..e9955884756 --- /dev/null +++ b/storage/myisammrg/.cvsignore @@ -0,0 +1,3 @@ +.deps +Makefile +Makefile.in diff --git a/storage/myisammrg/CMakeLists.txt b/storage/myisammrg/CMakeLists.txt new file mode 100644 index 00000000000..a86eff9d764 --- /dev/null +++ b/storage/myisammrg/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib + ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/extra/yassl/include) +ADD_LIBRARY(myisammrg myrg_close.c myrg_create.c myrg_delete.c myrg_extra.c myrg_info.c + ha_myisammrg.cc + myrg_locking.c myrg_open.c myrg_panic.c myrg_queue.c myrg_range.c + myrg_rfirst.c myrg_rkey.c myrg_rlast.c myrg_rnext.c myrg_rnext_same.c + myrg_rprev.c myrg_rrnd.c myrg_rsame.c myrg_static.c myrg_update.c + myrg_write.c) diff --git a/storage/myisammrg/Makefile.am b/storage/myisammrg/Makefile.am new file mode 100644 index 00000000000..2008cc62559 --- /dev/null +++ b/storage/myisammrg/Makefile.am @@ -0,0 +1,45 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 + +MYSQLDATAdir = $(localstatedir) +MYSQLSHAREdir = $(pkgdatadir) +MYSQLBASEdir= $(prefix) +MYSQLLIBdir= $(pkglibdir) +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I$(top_srcdir)/regex \ + -I$(top_srcdir)/sql \ + -I$(srcdir) +WRAPLIBS= + +LDADD = + +DEFS = @DEFS@ +pkglib_LIBRARIES = libmyisammrg.a +noinst_HEADERS = myrg_def.h ha_myisammrg.h +noinst_LIBRARIES = libmyisammrg.a +libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \ + myrg_rrnd.c myrg_update.c myrg_delete.c myrg_rsame.c \ + myrg_panic.c myrg_close.c myrg_create.c myrg_static.c \ + myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \ + myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c \ + ha_myisammrg.cc \ + myrg_rnext_same.c + + +EXTRA_DIST = CMakeLists.txt plug.in + +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc new file mode 100644 index 00000000000..9637173a3ad --- /dev/null +++ b/storage/myisammrg/ha_myisammrg.cc @@ -0,0 +1,607 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#define MYSQL_SERVER 1 +#include "mysql_priv.h" +#include <mysql/plugin.h> +#include <m_ctype.h> +#include "ha_myisammrg.h" +#include "myrg_def.h" + + +/***************************************************************************** +** MyISAM MERGE tables +*****************************************************************************/ + +static handler *myisammrg_create_handler(TABLE_SHARE *table, + MEM_ROOT *mem_root); + +static handler *myisammrg_create_handler(handlerton *hton, + TABLE_SHARE *table, + MEM_ROOT *mem_root) +{ + return new (mem_root) ha_myisammrg(hton, table); +} + + +ha_myisammrg::ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg) + :handler(hton, table_arg), file(0) +{} + +static const char *ha_myisammrg_exts[] = { + ".MRG", + NullS +}; + +const char **ha_myisammrg::bas_ext() const +{ + return ha_myisammrg_exts; +} + + +const char *ha_myisammrg::index_type(uint key_number) +{ + return ((table->key_info[key_number].flags & HA_FULLTEXT) ? + "FULLTEXT" : + (table->key_info[key_number].flags & HA_SPATIAL) ? + "SPATIAL" : + (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ? + "RTREE" : + "BTREE"); +} + + +int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) +{ + char name_buff[FN_REFLEN]; + + DBUG_PRINT("info", ("ha_myisammrg::open")); + if (!(file=myrg_open(fn_format(name_buff,name,"","", + MY_UNPACK_FILENAME|MY_APPEND_EXT), + mode, test_if_locked))) + { + DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno)); + return (my_errno ? my_errno : -1); + } + DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc...")); + myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref); + if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED || + test_if_locked == HA_OPEN_ABORT_IF_LOCKED)) + myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK,0); + info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED)) + myrg_extra(file,HA_EXTRA_WAIT_LOCK,0); + + if (table->s->reclength != stats.mean_rec_length && stats.mean_rec_length) + { + DBUG_PRINT("error",("reclength: %lu mean_rec_length: %lu", + table->s->reclength, stats.mean_rec_length)); + goto err; + } +#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4 + /* Merge table has more than 2G rows */ + if (table->s->crashed) + goto err; +#endif + return (0); +err: + myrg_close(file); + file=0; + return (my_errno= HA_ERR_WRONG_MRG_TABLE_DEF); +} + +int ha_myisammrg::close(void) +{ + return myrg_close(file); +} + +int ha_myisammrg::write_row(byte * buf) +{ + statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); + + if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables) + return (HA_ERR_TABLE_READONLY); + + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) + table->timestamp_field->set_time(); + if (table->next_number_field && buf == table->record[0]) + { + int error; + if ((error= update_auto_increment())) + return error; + } + return myrg_write(file,buf); +} + +int ha_myisammrg::update_row(const byte * old_data, byte * new_data) +{ + statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) + table->timestamp_field->set_time(); + return myrg_update(file,old_data,new_data); +} + +int ha_myisammrg::delete_row(const byte * buf) +{ + statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); + return myrg_delete(file,buf); +} + +int ha_myisammrg::index_read(byte * buf, const byte * key, + uint key_len, enum ha_rkey_function find_flag) +{ + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); + int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key, + uint key_len, enum ha_rkey_function find_flag) +{ + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); + int error=myrg_rkey(file,buf,index, key, key_len, find_flag); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len) +{ + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); + int error=myrg_rkey(file,buf,active_index, key, key_len, + HA_READ_PREFIX_LAST); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_next(byte * buf) +{ + statistic_increment(table->in_use->status_var.ha_read_next_count, + &LOCK_status); + int error=myrg_rnext(file,buf,active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_prev(byte * buf) +{ + statistic_increment(table->in_use->status_var.ha_read_prev_count, + &LOCK_status); + int error=myrg_rprev(file,buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_first(byte * buf) +{ + statistic_increment(table->in_use->status_var.ha_read_first_count, + &LOCK_status); + int error=myrg_rfirst(file, buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_last(byte * buf) +{ + statistic_increment(table->in_use->status_var.ha_read_last_count, + &LOCK_status); + int error=myrg_rlast(file, buf, active_index); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +int ha_myisammrg::index_next_same(byte * buf, + const byte *key __attribute__((unused)), + uint length __attribute__((unused))) +{ + statistic_increment(table->in_use->status_var.ha_read_next_count, + &LOCK_status); + int error=myrg_rnext_same(file,buf); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + + +int ha_myisammrg::rnd_init(bool scan) +{ + return myrg_reset(file); +} + + +int ha_myisammrg::rnd_next(byte *buf) +{ + statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, + &LOCK_status); + int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + + +int ha_myisammrg::rnd_pos(byte * buf, byte *pos) +{ + statistic_increment(table->in_use->status_var.ha_read_rnd_count, + &LOCK_status); + int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length)); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +void ha_myisammrg::position(const byte *record) +{ + ulonglong position= myrg_position(file); + my_store_ptr(ref, ref_length, (my_off_t) position); +} + + +ha_rows ha_myisammrg::records_in_range(uint inx, key_range *min_key, + key_range *max_key) +{ + return (ha_rows) myrg_records_in_range(file, (int) inx, min_key, max_key); +} + + +int ha_myisammrg::info(uint flag) +{ + MYMERGE_INFO info; + (void) myrg_status(file,&info,flag); + /* + The following fails if one has not compiled MySQL with -DBIG_TABLES + and one has more than 2^32 rows in the merge tables. + */ + stats.records = (ha_rows) info.records; + stats.deleted = (ha_rows) info.deleted; +#if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4 + if ((info.records >= (ulonglong) 1 << 32) || + (info.deleted >= (ulonglong) 1 << 32)) + table->s->crashed= 1; +#endif + stats.data_file_length=info.data_file_length; + errkey = info.errkey; + table->s->keys_in_use.set_prefix(table->s->keys); + table->s->db_options_in_use= info.options; + stats.mean_rec_length= info.reclength; + + /* + The handler::block_size is used all over the code in index scan cost + calculations. It is used to get number of disk seeks required to + retrieve a number of index tuples. + If the merge table has N underlying tables, then (assuming underlying + tables have equal size, the only "simple" approach we can use) + retrieving X index records from a merge table will require N times more + disk seeks compared to doing the same on a MyISAM table with equal + number of records. + In the edge case (file_tables > myisam_block_size) we'll get + block_size==0, and index calculation code will act as if we need one + disk seek to retrieve one index tuple. + + TODO: In 5.2 index scan cost calculation will be factored out into a + virtual function in class handler and we'll be able to remove this hack. + */ + stats.block_size= 0; + if (file->tables) + stats.block_size= myisam_block_size / file->tables; + + stats.update_time= 0; +#if SIZEOF_OFF_T > 4 + ref_length=6; // Should be big enough +#else + ref_length=4; // Can't be > than my_off_t +#endif + if (flag & HA_STATUS_CONST) + { + if (table->s->key_parts && info.rec_per_key) + { +#ifdef HAVE_purify + /* + valgrind may be unhappy about it, because optimizer may access values + between file->keys and table->key_parts, that will be uninitialized. + It's safe though, because even if opimizer will decide to use a key + with such a number, it'll be an error later anyway. + */ + bzero((char*) table->key_info[0].rec_per_key, + sizeof(table->key_info[0].rec_per_key) * table->s->key_parts); +#endif + memcpy((char*) table->key_info[0].rec_per_key, + (char*) info.rec_per_key, + sizeof(table->key_info[0].rec_per_key) * + min(file->keys, table->s->key_parts)); + } + } + return 0; +} + + +int ha_myisammrg::extra(enum ha_extra_function operation) +{ + /* As this is just a mapping, we don't have to force the underlying + tables to be closed */ + if (operation == HA_EXTRA_FORCE_REOPEN || + operation == HA_EXTRA_PREPARE_FOR_DELETE) + return 0; + return myrg_extra(file,operation,0); +} + +int ha_myisammrg::reset(void) +{ + return myrg_reset(file); +} + +/* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */ + +int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size) +{ + if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE) + return 0; + return myrg_extra(file, operation, (void*) &cache_size); +} + +int ha_myisammrg::external_lock(THD *thd, int lock_type) +{ + return myrg_lock_database(file,lock_type); +} + +uint ha_myisammrg::lock_count(void) const +{ + return file->tables; +} + + +THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, + THR_LOCK_DATA **to, + enum thr_lock_type lock_type) +{ + MYRG_TABLE *open_table; + + for (open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) + { + *(to++)= &open_table->table->lock; + if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK) + open_table->table->lock.type=lock_type; + } + return to; +} + + +/* Find out database name and table name from a filename */ + +static void split_file_name(const char *file_name, + LEX_STRING *db, LEX_STRING *name) +{ + uint dir_length, prefix_length; + char buff[FN_REFLEN]; + + db->length= 0; + strmake(buff, file_name, sizeof(buff)-1); + dir_length= dirname_length(buff); + if (dir_length > 1) + { + /* Get database */ + buff[dir_length-1]= 0; // Remove end '/' + prefix_length= dirname_length(buff); + db->str= (char*) file_name+ prefix_length; + db->length= dir_length - prefix_length -1; + } + name->str= (char*) file_name+ dir_length; + name->length= (uint) (fn_ext(name->str) - name->str); +} + + +void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) +{ + DBUG_ENTER("ha_myisammrg::update_create_info"); + + if (!(create_info->used_fields & HA_CREATE_USED_UNION)) + { + MYRG_TABLE *open_table; + THD *thd=current_thd; + + create_info->merge_list.next= &create_info->merge_list.first; + create_info->merge_list.elements=0; + + for (open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) + { + TABLE_LIST *ptr; + LEX_STRING db, name; + + if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) + goto err; + split_file_name(open_table->table->filename, &db, &name); + if (!(ptr->table_name= thd->strmake(name.str, name.length))) + goto err; + if (db.length && !(ptr->db= thd->strmake(db.str, db.length))) + goto err; + + create_info->merge_list.elements++; + (*create_info->merge_list.next) = (byte*) ptr; + create_info->merge_list.next= (byte**) &ptr->next_local; + } + *create_info->merge_list.next=0; + } + if (!(create_info->used_fields & HA_CREATE_USED_INSERT_METHOD)) + { + create_info->merge_insert_method = file->merge_insert_method; + } + DBUG_VOID_RETURN; + +err: + create_info->merge_list.elements=0; + create_info->merge_list.first=0; + DBUG_VOID_RETURN; +} + + +int ha_myisammrg::create(const char *name, register TABLE *form, + HA_CREATE_INFO *create_info) +{ + char buff[FN_REFLEN]; + const char **table_names, **pos; + TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first; + THD *thd= current_thd; + uint dirlgt= dirname_length(name); + DBUG_ENTER("ha_myisammrg::create"); + + if (!(table_names= (const char**) + thd->alloc((create_info->merge_list.elements+1) * sizeof(char*)))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + for (pos= table_names; tables; tables= tables->next_local) + { + const char *table_name; + TABLE *tbl= 0; + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + tbl= find_temporary_table(thd, tables); + if (!tbl) + { + /* + Construct the path to the MyISAM table. Try to meet two conditions: + 1.) Allow to include MyISAM tables from different databases, and + 2.) allow for moving DATADIR around in the file system. + The first means that we need paths in the .MRG file. The second + means that we should not have absolute paths in the .MRG file. + The best, we can do, is to use 'mysql_data_home', which is '.' + in mysqld and may be an absolute path in an embedded server. + This means that it might not be possible to move the DATADIR of + an embedded server without changing the paths in the .MRG file. + */ + uint length= build_table_filename(buff, sizeof(buff), + tables->db, tables->table_name, "", 0); + /* + If a MyISAM table is in the same directory as the MERGE table, + we use the table name without a path. This means that the + DATADIR can easily be moved even for an embedded server as long + as the MyISAM tables are from the same database as the MERGE table. + */ + if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt)) + table_name= tables->table_name; + else + if (! (table_name= thd->strmake(buff, length))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + else + table_name= tbl->s->path.str; + *pos++= table_name; + } + *pos=0; + DBUG_RETURN(myrg_create(fn_format(buff,name,"","", + MY_RESOLVE_SYMLINKS| + MY_UNPACK_FILENAME|MY_APPEND_EXT), + table_names, + create_info->merge_insert_method, + (my_bool) 0)); +} + + +void ha_myisammrg::append_create_info(String *packet) +{ + const char *current_db; + uint db_length; + THD *thd= current_thd; + MYRG_TABLE *open_table, *first; + + if (file->merge_insert_method != MERGE_INSERT_DISABLED) + { + packet->append(STRING_WITH_LEN(" INSERT_METHOD=")); + packet->append(get_type(&merge_insert_method,file->merge_insert_method-1)); + } + packet->append(STRING_WITH_LEN(" UNION=(")); + + current_db= table->s->db.str; + db_length= table->s->db.length; + + for (first=open_table=file->open_tables ; + open_table != file->end_table ; + open_table++) + { + LEX_STRING db, name; + split_file_name(open_table->table->filename, &db, &name); + if (open_table != first) + packet->append(','); + /* Report database for mapped table if it isn't in current database */ + if (db.length && + (db_length != db.length || + strncmp(current_db, db.str, db.length))) + { + append_identifier(thd, packet, db.str, db.length); + packet->append('.'); + } + append_identifier(thd, packet, name.str, name.length); + } + packet->append(')'); +} + + +bool ha_myisammrg::check_if_incompatible_data(HA_CREATE_INFO *info, + uint table_changes) +{ + /* + For myisammrg, we should always re-generate the mapping file as this + is trivial to do + */ + return COMPATIBLE_DATA_NO; +} + +extern int myrg_panic(enum ha_panic_function flag); +int myisammrg_panic(handlerton *hton, ha_panic_function flag) +{ + return myrg_panic(flag); +} + +static int myisammrg_init(void *p) +{ + handlerton *myisammrg_hton; + + myisammrg_hton= (handlerton *)p; + + myisammrg_hton->state= SHOW_OPTION_YES; + myisammrg_hton->db_type= DB_TYPE_MRG_MYISAM; + myisammrg_hton->create= myisammrg_create_handler; + myisammrg_hton->panic= myisammrg_panic; + myisammrg_hton->flags= HTON_CAN_RECREATE|HTON_NO_PARTITION; + + return 0; +} + +struct st_mysql_storage_engine myisammrg_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +mysql_declare_plugin(myisammrg) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &myisammrg_storage_engine, + "MRG_MYISAM", + "MySQL AB", + "Collection of identical MyISAM tables", + PLUGIN_LICENSE_GPL, + myisammrg_init, /* Plugin Init */ + NULL, /* Plugin Deinit */ + 0x0100, /* 1.0 */ + NULL, /* status variables */ + NULL, /* system variables */ + NULL /* config options */ +} +mysql_declare_plugin_end; diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h new file mode 100644 index 00000000000..ae3cb0aea42 --- /dev/null +++ b/storage/myisammrg/ha_myisammrg.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + + +#ifdef USE_PRAGMA_INTERFACE +#pragma interface /* gcc class implementation */ +#endif + +/* class for the the myisam merge handler */ + +#include <myisammrg.h> + +class ha_myisammrg: public handler +{ + MYRG_INFO *file; + + public: + ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg); + ~ha_myisammrg() {} + const char *table_type() const { return "MRG_MyISAM"; } + const char **bas_ext() const; + const char *index_type(uint key_number); + ulonglong table_flags() const + { + return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_NO_TRANSACTIONS | + HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED | + HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE | + HA_CAN_BIT_FIELD | HA_NO_COPY_ON_ALTER); + } + ulong index_flags(uint inx, uint part, bool all_parts) const + { + return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ? + 0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE | + HA_READ_ORDER | HA_KEYREAD_ONLY); + } + uint max_supported_keys() const { return MI_MAX_KEY; } + uint max_supported_key_length() const { return MI_MAX_KEY_LENGTH; } + uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; } + double scan_time() + { return ulonglong2double(stats.data_file_length) / IO_SIZE + file->tables; } + + int open(const char *name, int mode, uint test_if_locked); + int close(void); + int write_row(byte * buf); + int update_row(const byte * old_data, byte * new_data); + int delete_row(const byte * buf); + 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_read_last(byte * buf, const byte * key, uint key_len); + int index_next(byte * buf); + int index_prev(byte * buf); + int index_first(byte * buf); + int index_last(byte * buf); + int index_next_same(byte *buf, const byte *key, uint keylen); + int rnd_init(bool scan); + int rnd_next(byte *buf); + int rnd_pos(byte * buf, byte *pos); + void position(const byte *record); + ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key); + int info(uint); + int reset(void); + int extra(enum ha_extra_function operation); + int extra_opt(enum ha_extra_function operation, ulong cache_size); + int external_lock(THD *thd, int lock_type); + uint lock_count(void) const; + int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); + THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, + enum thr_lock_type lock_type); + void update_create_info(HA_CREATE_INFO *create_info); + void append_create_info(String *packet); + MYRG_INFO *myrg_info() { return file; } + bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); +}; diff --git a/storage/myisammrg/make-ccc b/storage/myisammrg/make-ccc new file mode 100755 index 00000000000..a7e3dfc3cdb --- /dev/null +++ b/storage/myisammrg/make-ccc @@ -0,0 +1,3 @@ +ccc -I./../include -I../include -DDBUG_OFF -fast -O3 -c myrg_close.c myrg_create.c myrg_delete.c myrg_extra.c myrg_info.c myrg_locking.c myrg_open.c myrg_panic.c myrg_rrnd.c myrg_rsame.c myrg_static.c myrg_update.c +rm libmyisammrg.a +ar -cr libmyisammrg.a myrg_close.o diff --git a/storage/myisammrg/myrg_close.c b/storage/myisammrg/myrg_close.c new file mode 100644 index 00000000000..897020c6865 --- /dev/null +++ b/storage/myisammrg/myrg_close.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* close a isam-database */ + +#include "myrg_def.h" + +int myrg_close(MYRG_INFO *info) +{ + int error=0,new_error; + MYRG_TABLE *file; + DBUG_ENTER("myrg_close"); + + for (file=info->open_tables ; file != info->end_table ; file++) + if ((new_error=mi_close(file->table))) + error=new_error; + delete_queue(&info->by_key); + pthread_mutex_lock(&THR_LOCK_open); + myrg_open_list=list_delete(myrg_open_list,&info->open_list); + pthread_mutex_unlock(&THR_LOCK_open); + my_free((gptr) info,MYF(0)); + if (error) + { + DBUG_RETURN(my_errno=error); + } + DBUG_RETURN(0); +} diff --git a/storage/myisammrg/myrg_create.c b/storage/myisammrg/myrg_create.c new file mode 100644 index 00000000000..3261cc1d6ad --- /dev/null +++ b/storage/myisammrg/myrg_create.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* Create a MYMERGE_-file */ + +#include "myrg_def.h" + + /* create file named 'name' and save filenames in it + table_names should be NULL or a vector of string-pointers with + a NULL-pointer last + */ + +int myrg_create(const char *name, const char **table_names, + uint insert_method, my_bool fix_names) +{ + int save_errno; + uint errpos; + File file; + char buff[FN_REFLEN],*end; + DBUG_ENTER("myrg_create"); + + errpos=0; + if ((file = my_create(fn_format(buff,name,"",MYRG_NAME_EXT, + MY_UNPACK_FILENAME|MY_APPEND_EXT),0, + O_RDWR | O_EXCL | O_NOFOLLOW,MYF(MY_WME))) < 0) + goto err; + errpos=1; + if (table_names) + { + for ( ; *table_names ; table_names++) + { + strmov(buff,*table_names); + if (fix_names) + fn_same(buff,name,4); + *(end=strend(buff))='\n'; + end[1]=0; + if (my_write(file,buff,(uint) (end-buff+1), + MYF(MY_WME | MY_NABP))) + goto err; + } + } + if (insert_method != MERGE_INSERT_DISABLED) + { + end=strxmov(buff,"#INSERT_METHOD=", + get_type(&merge_insert_method,insert_method-1),"\n",NullS); + if (my_write(file,buff,(uint) (end-buff),MYF(MY_WME | MY_NABP))) + goto err; + } + if (my_close(file,MYF(0))) + goto err; + DBUG_RETURN(0); + +err: + save_errno=my_errno ? my_errno : -1; + switch (errpos) { + case 1: + VOID(my_close(file,MYF(0))); + } + DBUG_RETURN(my_errno=save_errno); +} /* myrg_create */ diff --git a/storage/myisammrg/myrg_def.h b/storage/myisammrg/myrg_def.h new file mode 100644 index 00000000000..00e7950bccf --- /dev/null +++ b/storage/myisammrg/myrg_def.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* This file is included by all myisam-merge files */ + +#ifndef N_MAXKEY +#include "../myisam/myisamdef.h" +#endif + +#include "myisammrg.h" + +extern LIST *myrg_open_list; + +#ifdef THREAD +extern pthread_mutex_t THR_LOCK_open; +#endif + +int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag); +int _myrg_mi_read_record(MI_INFO *info, byte *buf); + diff --git a/storage/myisammrg/myrg_delete.c b/storage/myisammrg/myrg_delete.c new file mode 100644 index 00000000000..8b89ed62ac1 --- /dev/null +++ b/storage/myisammrg/myrg_delete.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* Delete last read record */ + +#include "myrg_def.h" + +int myrg_delete(MYRG_INFO *info, const byte *record) +{ + if (!info->current_table) + return (my_errno= HA_ERR_NO_ACTIVE_RECORD); + + return mi_delete(info->current_table->table,record); +} diff --git a/storage/myisammrg/myrg_extra.c b/storage/myisammrg/myrg_extra.c new file mode 100644 index 00000000000..2d6f9423de9 --- /dev/null +++ b/storage/myisammrg/myrg_extra.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* + Extra functions we want to do with a database + - All flags, exept record-cache-flags, are set in all used databases + record-cache-flags are set in myrg_rrnd when we are changing database. +*/ + +#include "myrg_def.h" + +int myrg_extra(MYRG_INFO *info,enum ha_extra_function function, + void *extra_arg) +{ + int error,save_error=0; + MYRG_TABLE *file; + DBUG_ENTER("myrg_extra"); + DBUG_PRINT("info",("function: %lu", (ulong) function)); + + if (function == HA_EXTRA_CACHE) + { + info->cache_in_use=1; + info->cache_size= (extra_arg ? *(ulong*) extra_arg : + my_default_record_cache_size); + } + else + { + if (function == HA_EXTRA_NO_CACHE || + function == HA_EXTRA_PREPARE_FOR_UPDATE) + info->cache_in_use=0; + if (function == HA_EXTRA_RESET_STATE) + { + info->current_table=0; + info->last_used_table=info->open_tables; + } + for (file=info->open_tables ; file != info->end_table ; file++) + { + if ((error=mi_extra(file->table, function, extra_arg))) + save_error=error; + } + } + DBUG_RETURN(save_error); +} + + +void myrg_extrafunc(MYRG_INFO *info, invalidator_by_filename inv) +{ + MYRG_TABLE *file; + DBUG_ENTER("myrg_extrafunc"); + + for (file=info->open_tables ; file != info->end_table ; file++) + file->table->s->invalidator = inv; + + DBUG_VOID_RETURN; +} + + +int myrg_reset(MYRG_INFO *info) +{ + int save_error= 0; + MYRG_TABLE *file; + DBUG_ENTER("myrg_reset"); + + info->cache_in_use=0; + info->current_table=0; + info->last_used_table= info->open_tables; + + for (file=info->open_tables ; file != info->end_table ; file++) + { + int error; + if ((error= mi_reset(file->table))) + save_error=error; + } + DBUG_RETURN(save_error); +} diff --git a/storage/myisammrg/myrg_info.c b/storage/myisammrg/myrg_info.c new file mode 100644 index 00000000000..ba840ac444b --- /dev/null +++ b/storage/myisammrg/myrg_info.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + +ulonglong myrg_position(MYRG_INFO *info) +{ + MYRG_TABLE *current_table; + + if (!(current_table = info->current_table) && + info->open_tables != info->end_table) + current_table = info->open_tables; + return current_table ? + current_table->table->lastpos + current_table->file_offset : + ~(ulonglong) 0; +} + +int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag) +{ + MYRG_TABLE *current_table; + DBUG_ENTER("myrg_status"); + + if (!(current_table = info->current_table) && + info->open_tables != info->end_table) + current_table = info->open_tables; + x->recpos = info->current_table ? + info->current_table->table->lastpos + info->current_table->file_offset : + (ulong) -1L; + if (flag != HA_STATUS_POS) + { + MYRG_TABLE *file; + + info->records=info->del=info->data_file_length=0; + for (file=info->open_tables ; file != info->end_table ; file++) + { + file->file_offset=info->data_file_length; + info->data_file_length+=file->table->s->state.state.data_file_length; + info->records+=file->table->s->state.state.records; + info->del+=file->table->s->state.state.del; + DBUG_PRINT("info2",("table: %s, offset: %lu", + file->table->filename,(ulong) file->file_offset)); + } + x->records= info->records; + x->deleted= info->del; + x->data_file_length= info->data_file_length; + x->reclength= info->reclength; + x->options= info->options; + if (current_table) + x->errkey= current_table->table->errkey; + else + x->errkey= 0; + x->rec_per_key = info->rec_per_key_part; + } + DBUG_RETURN(0); +} diff --git a/storage/myisammrg/myrg_locking.c b/storage/myisammrg/myrg_locking.c new file mode 100644 index 00000000000..98e8305b9ce --- /dev/null +++ b/storage/myisammrg/myrg_locking.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* + Lock databases against read or write. +*/ + +#include "myrg_def.h" + +int myrg_lock_database(MYRG_INFO *info, int lock_type) +{ + int error,new_error; + MYRG_TABLE *file; + + error=0; + for (file=info->open_tables ; file != info->end_table ; file++) + { +#ifdef __WIN__ + /* + Make sure this table is marked as owned by a merge table. + The semaphore is never released as long as table remains + in memory. This should be refactored into a more generic + approach (observer pattern) + */ + (file->table)->owned_by_merge = TRUE; +#endif + if ((new_error=mi_lock_database(file->table,lock_type))) + error=new_error; + } + return(error); +} diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c new file mode 100644 index 00000000000..dafb3246cbf --- /dev/null +++ b/storage/myisammrg/myrg_open.c @@ -0,0 +1,179 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* open a MyISAM MERGE table */ + +#include "myrg_def.h" +#include <stddef.h> +#include <errno.h> +#ifdef VMS +#include "mrg_static.c" +#endif + +/* + open a MyISAM MERGE table + if handle_locking is 0 then exit with error if some table is locked + if handle_locking is 1 then wait if table is locked +*/ + + +MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) +{ + int save_errno,errpos=0; + uint files= 0, i, dir_length, length, key_parts, min_keys= 0; + ulonglong file_offset=0; + char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; + MYRG_INFO *m_info=0; + File fd; + IO_CACHE file; + MI_INFO *isam=0; + uint found_merge_insert_method= 0; + DBUG_ENTER("myrg_open"); + + LINT_INIT(key_parts); + + bzero((char*) &file,sizeof(file)); + if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT, + MY_UNPACK_FILENAME|MY_APPEND_EXT), + O_RDONLY | O_SHARE,MYF(0))) < 0) + goto err; + errpos=1; + if (init_io_cache(&file, fd, 4*IO_SIZE, READ_CACHE, 0, 0, + MYF(MY_WME | MY_NABP))) + goto err; + errpos=2; + dir_length=dirname_part(name_buff,name); + while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) + { + if ((end=buff+length)[-1] == '\n') + end[-1]='\0'; + if (buff[0] && buff[0] != '#') + files++; + } + + my_b_seek(&file, 0); + while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) + { + if ((end=buff+length)[-1] == '\n') + *--end='\0'; + if (!buff[0]) + continue; /* Skip empty lines */ + if (buff[0] == '#') + { + if (!strncmp(buff+1,"INSERT_METHOD=",14)) + { /* Lookup insert method */ + int tmp=find_type(buff+15,&merge_insert_method,2); + found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); + } + continue; /* Skip comments */ + } + + if (!has_path(buff)) + { + VOID(strmake(name_buff+dir_length,buff, + sizeof(name_buff)-1-dir_length)); + VOID(cleanup_dirname(buff,name_buff)); + } + else + fn_format(buff, buff, "", "", 0); + if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) + { + my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; + goto err; + } + if (!m_info) /* First file */ + { + key_parts=isam->s->base.key_parts; + if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) + + files*sizeof(MYRG_TABLE) + + key_parts*sizeof(long), + MYF(MY_WME|MY_ZEROFILL)))) + goto err; + if (files) + { + m_info->open_tables=(MYRG_TABLE *) (m_info+1); + m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); + m_info->tables= files; + files= 0; + } + m_info->reclength=isam->s->base.reclength; + min_keys= isam->s->base.keys; + errpos=3; + } + m_info->open_tables[files].table= isam; + m_info->open_tables[files].file_offset=(my_off_t) file_offset; + file_offset+=isam->state->data_file_length; + files++; + if (m_info->reclength != isam->s->base.reclength) + { + my_errno=HA_ERR_WRONG_MRG_TABLE_DEF; + goto err; + } + m_info->options|= isam->s->options; + m_info->records+= isam->state->records; + m_info->del+= isam->state->del; + m_info->data_file_length+= isam->state->data_file_length; + if (min_keys > isam->s->base.keys) + min_keys= isam->s->base.keys; + for (i=0; i < key_parts; i++) + m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] / + m_info->tables); + } + + if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO), + MYF(MY_WME | MY_ZEROFILL)))) + goto err; + /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */ + m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA); + m_info->merge_insert_method= found_merge_insert_method; + + if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L) + { + my_errno=HA_ERR_RECORD_FILE_FULL; + goto err; + } + m_info->keys= min_keys; + bzero((char*) &m_info->by_key,sizeof(m_info->by_key)); + + /* this works ok if the table list is empty */ + m_info->end_table=m_info->open_tables+files; + m_info->last_used_table=m_info->open_tables; + + VOID(my_close(fd,MYF(0))); + end_io_cache(&file); + m_info->open_list.data=(void*) m_info; + pthread_mutex_lock(&THR_LOCK_open); + myrg_open_list=list_add(myrg_open_list,&m_info->open_list); + pthread_mutex_unlock(&THR_LOCK_open); + DBUG_RETURN(m_info); + +err: + save_errno=my_errno; + switch (errpos) { + case 3: + while (files) + mi_close(m_info->open_tables[--files].table); + my_free((char*) m_info,MYF(0)); + /* Fall through */ + case 2: + end_io_cache(&file); + /* Fall through */ + case 1: + VOID(my_close(fd,MYF(0))); + } + my_errno=save_errno; + DBUG_RETURN (NULL); +} diff --git a/storage/myisammrg/myrg_panic.c b/storage/myisammrg/myrg_panic.c new file mode 100644 index 00000000000..ab08b8082c3 --- /dev/null +++ b/storage/myisammrg/myrg_panic.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + + /* if flag == HA_PANIC_CLOSE then all misam files are closed */ + /* if flag == HA_PANIC_WRITE then all misam files are unlocked and + all changed data in single user misam is written to file */ + /* if flag == HA_PANIC_READ then all misam files that was locked when + mi_panic(HA_PANIC_WRITE) was done is locked. A mi_readinfo() is + done for all single user files to get changes in database */ + + +int myrg_panic(enum ha_panic_function flag) +{ + int error=0; + LIST *list_element,*next_open; + MYRG_INFO *info; + DBUG_ENTER("myrg_panic"); + + for (list_element=myrg_open_list ; list_element ; list_element=next_open) + { + next_open=list_element->next; /* Save if close */ + info=(MYRG_INFO*) list_element->data; + if (flag == HA_PANIC_CLOSE && myrg_close(info)) + error=my_errno; + } + if (myrg_open_list && flag != HA_PANIC_CLOSE) + DBUG_RETURN(mi_panic(flag)); + if (error) + my_errno=error; + DBUG_RETURN(error); +} diff --git a/storage/myisammrg/myrg_queue.c b/storage/myisammrg/myrg_queue.c new file mode 100644 index 00000000000..74fdddc7748 --- /dev/null +++ b/storage/myisammrg/myrg_queue.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + +static int queue_key_cmp(void *keyseg, byte *a, byte *b) +{ + MYRG_TABLE *ma= (MYRG_TABLE *)a; + MYRG_TABLE *mb= (MYRG_TABLE *)b; + MI_INFO *aa= ma->table; + MI_INFO *bb= mb->table; + uint not_used[2]; + int ret= ha_key_cmp((HA_KEYSEG *)keyseg, aa->lastkey, bb->lastkey, + USE_WHOLE_KEY, SEARCH_FIND, not_used); + if (ret < 0) + return -1; + if (ret > 0) + return 1; + + /* + If index tuples have the same values, let the record with least rowid + value be "smaller", so index scans return records ordered by (keytuple, + rowid). This is used by index_merge access method, grep for ROR in + sql/opt_range.cc for details. + */ + return (ma->file_offset < mb->file_offset)? -1 : (ma->file_offset > + mb->file_offset) ? 1 : 0; +} /* queue_key_cmp */ + + +int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag) +{ + int error=0; + QUEUE *q= &(info->by_key); + + if (inx < (int) info->keys) + { + if (!is_queue_inited(q)) + { + if (init_queue(q,info->tables, 0, + (myisam_readnext_vec[search_flag] == SEARCH_SMALLER), + queue_key_cmp, + info->open_tables->table->s->keyinfo[inx].seg)) + error=my_errno; + } + else + { + if (reinit_queue(q,info->tables, 0, + (myisam_readnext_vec[search_flag] == SEARCH_SMALLER), + queue_key_cmp, + info->open_tables->table->s->keyinfo[inx].seg)) + error=my_errno; + } + } + else + my_errno= error= HA_ERR_WRONG_INDEX; + return error; +} + +int _myrg_mi_read_record(MI_INFO *info, byte *buf) +{ + if (!(*info->read_record)(info,info->lastpos,buf)) + { + info->update|= HA_STATE_AKTIV; /* Record is read */ + return 0; + } + return my_errno; +} diff --git a/storage/myisammrg/myrg_range.c b/storage/myisammrg/myrg_range.c new file mode 100644 index 00000000000..aafdf70525c --- /dev/null +++ b/storage/myisammrg/myrg_range.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + +ha_rows myrg_records_in_range(MYRG_INFO *info, int inx, + key_range *min_key, key_range *max_key) +{ + ha_rows records=0, res; + MYRG_TABLE *table; + + for (table=info->open_tables ; table != info->end_table ; table++) + { + res= mi_records_in_range(table->table, inx, min_key, max_key); + if (res == HA_POS_ERROR) + return HA_POS_ERROR; + if (records > HA_POS_ERROR - res) + return HA_POS_ERROR-1; + records+=res; + } + return records; +} + diff --git a/storage/myisammrg/myrg_rfirst.c b/storage/myisammrg/myrg_rfirst.c new file mode 100644 index 00000000000..9ba07686c47 --- /dev/null +++ b/storage/myisammrg/myrg_rfirst.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + + /* Read first row according to specific key */ + +int myrg_rfirst(MYRG_INFO *info, byte *buf, int inx) +{ + MYRG_TABLE *table; + MI_INFO *mi; + int err; + + if (_myrg_init_queue(info,inx,HA_READ_KEY_OR_NEXT)) + return my_errno; + + for (table=info->open_tables ; table != info->end_table ; table++) + { + if ((err=mi_rfirst(table->table,NULL,inx))) + { + if (err == HA_ERR_END_OF_FILE) + continue; + return err; + } + /* adding to queue */ + queue_insert(&(info->by_key),(byte *)table); + } + /* We have done a read in all tables */ + info->last_used_table=table; + + if (!info->by_key.elements) + return HA_ERR_END_OF_FILE; + + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + return _myrg_mi_read_record(mi,buf); +} diff --git a/storage/myisammrg/myrg_rkey.c b/storage/myisammrg/myrg_rkey.c new file mode 100644 index 00000000000..85464374d5d --- /dev/null +++ b/storage/myisammrg/myrg_rkey.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* Read record based on a key */ + +/* + * HA_READ_KEY_EXACT => SEARCH_BIGGER + * HA_READ_KEY_OR_NEXT => SEARCH_BIGGER + * HA_READ_AFTER_KEY => SEARCH_BIGGER + * HA_READ_PREFIX => SEARCH_BIGGER + * HA_READ_KEY_OR_PREV => SEARCH_SMALLER + * HA_READ_BEFORE_KEY => SEARCH_SMALLER + * HA_READ_PREFIX_LAST => SEARCH_SMALLER + */ + + +#include "myrg_def.h" + +/* todo: we could store some additional info to speedup lookups: + column (key, keyseg) can be constant per table + it can also be increasing (table1.val > table2.val > ...), + or decreasing, <=, >=, etc. + SerG +*/ + +int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, + uint key_len, enum ha_rkey_function search_flag) +{ + byte *key_buff; + uint pack_key_length; + MYRG_TABLE *table; + MI_INFO *mi; + int err; + DBUG_ENTER("myrg_rkey"); + LINT_INIT(key_buff); + LINT_INIT(pack_key_length); + + if (_myrg_init_queue(info,inx,search_flag)) + DBUG_RETURN(my_errno); + + for (table=info->open_tables ; table != info->end_table ; table++) + { + mi=table->table; + + if (table == info->open_tables) + { + err=mi_rkey(mi,0,inx,key,key_len,search_flag); + /* Get the saved packed key and packed key length. */ + key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length; + pack_key_length=mi->pack_key_length; + } + else + { + mi->once_flags|= USE_PACKED_KEYS; + err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag); + } + info->last_used_table=table+1; + + if (err) + { + if (err == HA_ERR_KEY_NOT_FOUND) + continue; + DBUG_PRINT("exit", ("err: %d", err)); + DBUG_RETURN(err); + } + /* adding to queue */ + queue_insert(&(info->by_key),(byte *)table); + + } + + DBUG_PRINT("info", ("tables with matches: %u", info->by_key.elements)); + if (!info->by_key.elements) + DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); + + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + mi->once_flags|= RRND_PRESERVE_LASTINX; + DBUG_PRINT("info", ("using table no: %d", + (int) (info->current_table - info->open_tables + 1))); + DBUG_DUMP("result key", (byte*) mi->lastkey, mi->lastkey_length); + DBUG_RETURN(_myrg_mi_read_record(mi,buf)); +} diff --git a/storage/myisammrg/myrg_rlast.c b/storage/myisammrg/myrg_rlast.c new file mode 100644 index 00000000000..96bb798bd4f --- /dev/null +++ b/storage/myisammrg/myrg_rlast.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + + /* Read last row with the same key as the previous read. */ + +int myrg_rlast(MYRG_INFO *info, byte *buf, int inx) +{ + MYRG_TABLE *table; + MI_INFO *mi; + int err; + + if (_myrg_init_queue(info,inx, HA_READ_KEY_OR_PREV)) + return my_errno; + + for (table=info->open_tables ; table < info->end_table ; table++) + { + if ((err=mi_rlast(table->table,NULL,inx))) + { + if (err == HA_ERR_END_OF_FILE) + continue; + return err; + } + /* adding to queue */ + queue_insert(&(info->by_key),(byte *)table); + } + /* We have done a read in all tables */ + info->last_used_table=table; + + if (!info->by_key.elements) + return HA_ERR_END_OF_FILE; + + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + return _myrg_mi_read_record(mi,buf); +} + diff --git a/storage/myisammrg/myrg_rnext.c b/storage/myisammrg/myrg_rnext.c new file mode 100644 index 00000000000..0929c63fc1d --- /dev/null +++ b/storage/myisammrg/myrg_rnext.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + + /* + Read next row with the same key as previous read + */ + +int myrg_rnext(MYRG_INFO *info, byte *buf, int inx) +{ + int err; + MI_INFO *mi; + + if (!info->current_table) + return (HA_ERR_KEY_NOT_FOUND); + + /* at first, do rnext for the table found before */ + if ((err=mi_rnext(info->current_table->table,NULL,inx))) + { + if (err == HA_ERR_END_OF_FILE) + { + queue_remove(&(info->by_key),0); + if (!info->by_key.elements) + return HA_ERR_END_OF_FILE; + } + else + return err; + } + else + { + /* Found here, adding to queue */ + queue_top(&(info->by_key))=(byte *)(info->current_table); + queue_replaced(&(info->by_key)); + } + + /* now, mymerge's read_next is as simple as one queue_top */ + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + return _myrg_mi_read_record(mi,buf); +} diff --git a/storage/myisammrg/myrg_rnext_same.c b/storage/myisammrg/myrg_rnext_same.c new file mode 100644 index 00000000000..997e4100acd --- /dev/null +++ b/storage/myisammrg/myrg_rnext_same.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + + +int myrg_rnext_same(MYRG_INFO *info, byte *buf) +{ + int err; + MI_INFO *mi; + + if (!info->current_table) + return (HA_ERR_KEY_NOT_FOUND); + + /* at first, do rnext for the table found before */ + if ((err=mi_rnext_same(info->current_table->table,NULL))) + { + if (err == HA_ERR_END_OF_FILE) + { + queue_remove(&(info->by_key),0); + if (!info->by_key.elements) + return HA_ERR_END_OF_FILE; + } + else + return err; + } + else + { + /* Found here, adding to queue */ + queue_top(&(info->by_key))=(byte *)(info->current_table); + queue_replaced(&(info->by_key)); + } + + /* now, mymerge's read_next is as simple as one queue_top */ + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + return _myrg_mi_read_record(mi,buf); +} + diff --git a/storage/myisammrg/myrg_rprev.c b/storage/myisammrg/myrg_rprev.c new file mode 100644 index 00000000000..797993e903d --- /dev/null +++ b/storage/myisammrg/myrg_rprev.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + + /* + Read previous row with the same key as previous read + */ + +int myrg_rprev(MYRG_INFO *info, byte *buf, int inx) +{ + int err; + MI_INFO *mi; + + if (!info->current_table) + return (HA_ERR_KEY_NOT_FOUND); + + /* at first, do rprev for the table found before */ + if ((err=mi_rprev(info->current_table->table,NULL,inx))) + { + if (err == HA_ERR_END_OF_FILE) + { + queue_remove(&(info->by_key),0); + if (!info->by_key.elements) + return HA_ERR_END_OF_FILE; + } + else + return err; + } + else + { + /* Found here, adding to queue */ + queue_top(&(info->by_key))=(byte *)(info->current_table); + queue_replaced(&(info->by_key)); + } + + /* now, mymerge's read_prev is as simple as one queue_top */ + mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table; + return _myrg_mi_read_record(mi,buf); +} diff --git a/storage/myisammrg/myrg_rrnd.c b/storage/myisammrg/myrg_rrnd.c new file mode 100644 index 00000000000..d623ea8ea9c --- /dev/null +++ b/storage/myisammrg/myrg_rrnd.c @@ -0,0 +1,117 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* + Read a record with random-access. The position to the record must + get by myrg_info(). The next record can be read with pos= -1 */ + + +#include "myrg_def.h" + +static MYRG_TABLE *find_table(MYRG_TABLE *start,MYRG_TABLE *end,ulonglong pos); + +/* + If filepos == HA_OFFSET_ERROR, read next + Returns same as mi_rrnd: + 0 = Ok. + HA_ERR_RECORD_DELETED = Record is deleted. + HA_ERR_END_OF_FILE = EOF. +*/ + +int myrg_rrnd(MYRG_INFO *info,byte *buf,ulonglong filepos) +{ + int error; + MI_INFO *isam_info; + DBUG_ENTER("myrg_rrnd"); + DBUG_PRINT("info",("offset: %lu", (ulong) filepos)); + + if (filepos == HA_OFFSET_ERROR) + { + if (!info->current_table) + { + if (info->open_tables == info->end_table) + { /* No tables */ + DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE); + } + isam_info=(info->current_table=info->open_tables)->table; + if (info->cache_in_use) + mi_extra(isam_info,HA_EXTRA_CACHE,(byte*) &info->cache_size); + filepos=isam_info->s->pack.header_length; + isam_info->lastinx= (uint) -1; /* Can't forward or backward */ + } + else + { + isam_info=info->current_table->table; + filepos= isam_info->nextpos; + } + + for (;;) + { + isam_info->update&= HA_STATE_CHANGED; + if ((error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf, + (my_off_t) filepos,1)) != + HA_ERR_END_OF_FILE) + DBUG_RETURN(error); + if (info->cache_in_use) + mi_extra(info->current_table->table, HA_EXTRA_NO_CACHE, + (byte*) &info->cache_size); + if (info->current_table+1 == info->end_table) + DBUG_RETURN(HA_ERR_END_OF_FILE); + info->current_table++; + info->last_used_table=info->current_table; + if (info->cache_in_use) + mi_extra(info->current_table->table, HA_EXTRA_CACHE, + (byte*) &info->cache_size); + info->current_table->file_offset= + info->current_table[-1].file_offset+ + info->current_table[-1].table->state->data_file_length; + + isam_info=info->current_table->table; + filepos=isam_info->s->pack.header_length; + isam_info->lastinx= (uint) -1; + } + } + info->current_table=find_table(info->open_tables, + info->end_table-1,filepos); + isam_info=info->current_table->table; + isam_info->update&= HA_STATE_CHANGED; + DBUG_RETURN((*isam_info->s->read_rnd) + (isam_info, (byte*) buf, + (my_off_t) (filepos - info->current_table->file_offset), + 0)); +} + + + /* Find which table to use according to file-pos */ + +static MYRG_TABLE *find_table(MYRG_TABLE *start, MYRG_TABLE *end, + ulonglong pos) +{ + MYRG_TABLE *mid; + DBUG_ENTER("find_table"); + + while (start != end) + { + mid=start+((uint) (end-start)+1)/2; + if (mid->file_offset > pos) + end=mid-1; + else + start=mid; + } + DBUG_PRINT("info",("offset: %lu, table: %s", + (ulong) pos, start->table->filename)); + DBUG_RETURN(start); +} diff --git a/storage/myisammrg/myrg_rsame.c b/storage/myisammrg/myrg_rsame.c new file mode 100644 index 00000000000..f6b2164dc21 --- /dev/null +++ b/storage/myisammrg/myrg_rsame.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +#include "myrg_def.h" + +int myrg_rsame(MYRG_INFO *info,byte *record,int inx) +{ + if (inx) /* not yet used, should be 0 */ + return (my_errno=HA_ERR_WRONG_INDEX); + + if (!info->current_table) + return (my_errno=HA_ERR_NO_ACTIVE_RECORD); + + return mi_rsame(info->current_table->table,record,inx); +} diff --git a/storage/myisammrg/myrg_static.c b/storage/myisammrg/myrg_static.c new file mode 100644 index 00000000000..9e76cbae07b --- /dev/null +++ b/storage/myisammrg/myrg_static.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* + Static variables for pisam library. All definied here for easy making of + a shared library +*/ + +#ifndef stdin +#include "myrg_def.h" +#endif + +LIST *myrg_open_list=0; +static const char *merge_insert_methods[] = +{ "FIRST", "LAST", NullS }; +TYPELIB merge_insert_method= { array_elements(merge_insert_methods)-1,"", + merge_insert_methods, 0}; diff --git a/storage/myisammrg/myrg_update.c b/storage/myisammrg/myrg_update.c new file mode 100644 index 00000000000..7b9f614b965 --- /dev/null +++ b/storage/myisammrg/myrg_update.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* Update last read record */ + +#include "myrg_def.h" + +int myrg_update(register MYRG_INFO *info,const byte *oldrec, byte *newrec) +{ + if (!info->current_table) + return (my_errno=HA_ERR_NO_ACTIVE_RECORD); + + return mi_update(info->current_table->table,oldrec,newrec); +} diff --git a/storage/myisammrg/myrg_write.c b/storage/myisammrg/myrg_write.c new file mode 100644 index 00000000000..532709e361d --- /dev/null +++ b/storage/myisammrg/myrg_write.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2001 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */ + +/* Write a row to a MyISAM MERGE table */ + +#include "myrg_def.h" + +int myrg_write(register MYRG_INFO *info, byte *rec) +{ + /* [phi] MERGE_WRITE_DISABLED is handled by the else case */ + if (info->merge_insert_method == MERGE_INSERT_TO_FIRST) + return mi_write((info->current_table=info->open_tables)->table,rec); + else if (info->merge_insert_method == MERGE_INSERT_TO_LAST) + return mi_write((info->current_table=info->end_table-1)->table,rec); + else /* unsupported insertion method */ + return (my_errno= HA_ERR_WRONG_COMMAND); +} diff --git a/storage/myisammrg/plug.in b/storage/myisammrg/plug.in new file mode 100644 index 00000000000..1f94e07d881 --- /dev/null +++ b/storage/myisammrg/plug.in @@ -0,0 +1,6 @@ +MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine], + [Merge multiple MySQL tables into one]) +MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg]) +MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg.a]) +MYSQL_PLUGIN_MANDATORY(myisammrg) +MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisammrg, [ha_myisammrg.cc]) |