summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <acurtis@xiphis.org>2005-12-21 10:18:40 -0800
committerunknown <acurtis@xiphis.org>2005-12-21 10:18:40 -0800
commit613dd50a33ac3e64073abdbdae66ce3a93e69e30 (patch)
treed777ca5871199d389af93e8cbe06e1bdbc16a10b /sql
parent9c81773b37a5ec1a689632e3161ae6b9d1fdeb46 (diff)
downloadmariadb-git-613dd50a33ac3e64073abdbdae66ce3a93e69e30.tar.gz
Finalize storage engine plugins
Give BerkeleyDB savepoints Remove "enum db_type" from most of the code storage/example/ha_example.h: Rename: sql/examples/ha_example.h -> storage/example/ha_example.h storage/csv/ha_tina.h: Rename: sql/examples/ha_tina.h -> storage/csv/ha_tina.h config/ac-macros/storage.m4: if hton name is "no", then we don't install it as a builtin configure.in: pluggable changes include/plugin.h: version field mysql-test/r/bdb.result: savepoint results copied from innodb test mysql-test/r/information_schema.result: PLUGINS information schema mysql-test/r/information_schema_db.result: PLUGINS information schema mysql-test/t/bdb.test: savepoint test copied from innodb test sql/Makefile.am: tina and example are not here anymore sql/authors.h: minor tweek sql/ha_archive.cc: remove unwanted handlerton entries sql/ha_berkeley.cc: remove unwanted handlerton entries support for savepoints changes to show logs sql/ha_blackhole.cc: remove unwanted handlerton entries sql/ha_federated.cc: remove unwanted handlerton entries sql/ha_heap.cc: remove unwanted handlerton entries sql/ha_innodb.cc: remove unwanted handlerton entries changes for show status sql/ha_myisam.cc: remove unwanted handlerton entries sql/ha_myisammrg.cc: remove unwanted handlerton entries sql/ha_ndbcluster.cc: remove unwanted handlerton entries changes to stat_print sql/ha_partition.cc: remove unwanted handlerton entries bye bye enum db_type sql/ha_partition.h: bye bye enum db_type sql/handler.cc: remove unwanted handlerton entries bye bye enum db_type sql/handler.h: remove unwanted handlerton entries bye bye enum db_type changes to stat_print_fn sql/item_sum.cc: bye bye enum db_type sql/log.cc: remove unwanted handlerton entries sql/mysql_priv.h: bye bye enum db_type sql/mysqld.cc: bye bye enum db_type reorder plugin initialization sql/set_var.cc: bye bye enum db_type sql/set_var.h: bye bye enum db_type sql/sql_base.cc: bye bye enum db_type sql/sql_cache.cc: bye bye enum db_type sql/sql_class.h: bye bye enum db_type sql/sql_delete.cc: bye bye enum db_type sql/sql_insert.cc: bye bye enum db_type sql/sql_lex.h: show plugin sql/sql_parse.cc: bye bye enum db_type sql/sql_partition.cc: bye bye enum db_type sql/sql_plugin.cc: loadable storage engines sql/sql_plugin.h: loadable storage engines sql/sql_rename.cc: bye bye enum db_type sql/sql_select.cc: bye bye enum db_type sql/sql_show.cc: SHOW PLUGIN PLUGINS information schema changes to show engines sql/sql_table.cc: bye bye enum db_type sql/sql_view.cc: bye bye enum db_type sql/sql_view.h: bye bye enum db_type sql/sql_yacc.yy: bye bye enum db_type sql/table.cc: bye bye enum db_type sql/table.h: bye bye enum db_type sql/unireg.cc: bye bye enum db_type storage/csv/ha_tina.cc: make tina into a loadable plugin storage/example/ha_example.cc: make into a plugin storage/csv/Makefile.am: New BitKeeper file ``storage/csv/Makefile.am'' storage/example/Makefile.am: New BitKeeper file ``storage/example/Makefile.am''
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/authors.h3
-rw-r--r--sql/examples/ha_example.cc715
-rw-r--r--sql/examples/ha_example.h155
-rw-r--r--sql/examples/ha_tina.cc935
-rw-r--r--sql/examples/ha_tina.h130
-rw-r--r--sql/ha_archive.cc4
-rw-r--r--sql/ha_berkeley.cc81
-rw-r--r--sql/ha_blackhole.cc4
-rw-r--r--sql/ha_federated.cc4
-rw-r--r--sql/ha_heap.cc4
-rw-r--r--sql/ha_innodb.cc60
-rw-r--r--sql/ha_myisam.cc4
-rw-r--r--sql/ha_myisammrg.cc4
-rw-r--r--sql/ha_ndbcluster.cc10
-rw-r--r--sql/ha_partition.cc26
-rw-r--r--sql/ha_partition.h2
-rw-r--r--sql/handler.cc773
-rw-r--r--sql/handler.h82
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/log.cc4
-rw-r--r--sql/mysql_priv.h10
-rw-r--r--sql/mysqld.cc31
-rw-r--r--sql/set_var.cc30
-rw-r--r--sql/set_var.h7
-rw-r--r--sql/sql_base.cc6
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_delete.cc7
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_partition.cc33
-rw-r--r--sql/sql_plugin.cc238
-rw-r--r--sql/sql_plugin.h11
-rw-r--r--sql/sql_rename.cc5
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/sql_show.cc186
-rw-r--r--sql/sql_table.cc80
-rw-r--r--sql/sql_view.cc6
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/sql_yacc.yy56
-rw-r--r--sql/table.cc28
-rw-r--r--sql/table.h7
-rw-r--r--sql/unireg.cc21
45 files changed, 1237 insertions, 2566 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 1090c6d48c7..a5b81ffdcdb 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -101,9 +101,7 @@ EXTRA_mysqld_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
ha_innodb.h ha_berkeley.h ha_archive.h \
ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
ha_blackhole.h ha_federated.h ha_ndbcluster.h \
- ha_partition.cc ha_partition.h \
- examples/ha_tina.cc examples/ha_example.cc \
- examples/ha_tina.h examples/ha_example.h
+ ha_partition.cc ha_partition.h
mysqld_DEPENDENCIES = @mysql_se_objs@
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
diff --git a/sql/authors.h b/sql/authors.h
index 1c6e1d468c4..fde1806f4be 100644
--- a/sql/authors.h
+++ b/sql/authors.h
@@ -62,7 +62,8 @@ struct show_table_authors_st show_table_authors[]= {
{ "Albert Chin-A-Young", "",
"Tru64 port, large file support, better TCP wrappers support" },
{ "Jorge del Conde", "Mexico City, Mexico", "Windows development" },
- { "Antony T. Curtis", "Norwalk, CA, USA", "Parser, port to OS/2" },
+ { "Antony T. Curtis", "Norwalk, CA, USA",
+ "Parser, port to OS/2, storage engines and some random stuff" },
{ "Yuri Dario", "", "OS/2 port" },
{ "Sergei Golubchik", "Kerpen, Germany",
"Full-text search, precision math" },
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
deleted file mode 100644
index 5b32b549e8d..00000000000
--- a/sql/examples/ha_example.cc
+++ /dev/null
@@ -1,715 +0,0 @@
-/* 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 */
-
-/*
- ha_example is a stubbed storage engine. It does nothing at this point. It
- will let you create/open/delete tables but that is all. You can enable it
- in your buld by doing the following during your build process:
- ./configure --with-example-storage-engine
-
- Once this is done mysql will let you create tables with:
- CREATE TABLE A (...) ENGINE=EXAMPLE;
-
- The example is setup to use table locks. It implements an example "SHARE"
- that is inserted into a hash by table name. You can use this to store
- information of state that any example handler object will be able to see
- if it is using the same table.
-
- Please read the object definition in ha_example.h before reading the rest
- if this file.
-
- To get an idea of what occurs here is an example select that would do a
- scan of an entire table:
- ha_example::store_lock
- ha_example::external_lock
- ha_example::info
- ha_example::rnd_init
- ha_example::extra
- ENUM HA_EXTRA_CACHE Cash record in HA_rrnd()
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::rnd_next
- ha_example::extra
- ENUM HA_EXTRA_NO_CACHE End cacheing of records (def)
- ha_example::external_lock
- ha_example::extra
- ENUM HA_EXTRA_RESET Reset database to after open
-
- In the above example has 9 row called before rnd_next signalled that it was
- at the end of its data. In the above example the table was already opened
- (or you would have seen a call to ha_example::open(). Calls to
- ha_example::extra() are hints as to what will be occuring to the request.
-
- Happy coding!
- -Brian
-*/
-
-#ifdef USE_PRAGMA_IMPLEMENTATION
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "../mysql_priv.h"
-
-#include "ha_example.h"
-
-static handler* example_create_handler(TABLE_SHARE *table);
-
-handlerton example_hton= {
- "EXAMPLE",
- SHOW_OPTION_YES,
- "Example storage engine",
- DB_TYPE_EXAMPLE_DB,
- NULL, /* We do need to write one! */
- 0, /* slot */
- 0, /* savepoint size. */
- NULL, /* close_connection */
- NULL, /* savepoint */
- NULL, /* rollback to savepoint */
- NULL, /* release savepoint */
- NULL, /* commit */
- NULL, /* rollback */
- NULL, /* prepare */
- NULL, /* recover */
- NULL, /* commit_by_xid */
- NULL, /* rollback_by_xid */
- NULL, /* create_cursor_read_view */
- NULL, /* set_cursor_read_view */
- NULL, /* close_cursor_read_view */
- example_create_handler, /* Create a new handler */
- NULL, /* Drop a database */
- NULL, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
- NULL, /* Start Consistent Snapshot */
- NULL, /* Flush logs */
- NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
- HTON_CAN_RECREATE
-};
-
-/* Variables for example share methods */
-static HASH example_open_tables; // Hash used to track open tables
-pthread_mutex_t example_mutex; // This is the mutex we use to init the hash
-static int example_init= 0; // Variable for checking the init state of hash
-
-
-/*
- Function we use in the creation of our hash to get key.
-*/
-static byte* example_get_key(EXAMPLE_SHARE *share,uint *length,
- my_bool not_used __attribute__((unused)))
-{
- *length=share->table_name_length;
- return (byte*) share->table_name;
-}
-
-
-/*
- Example of simple lock controls. The "share" it creates is structure we will
- pass to each example handler. Do you have to have one of these? Well, you have
- pieces that are used for locking, and they are needed to function.
-*/
-static EXAMPLE_SHARE *get_share(const char *table_name, TABLE *table)
-{
- EXAMPLE_SHARE *share;
- uint length;
- char *tmp_name;
-
- /*
- So why does this exist? There is no way currently to init a storage engine.
- Innodb and BDB both have modifications to the server to allow them to
- do this. Since you will not want to do this, this is probably the next
- best method.
- */
- if (!example_init)
- {
- /* Hijack a mutex for init'ing the storage engine */
- pthread_mutex_lock(&LOCK_mysql_create_db);
- if (!example_init)
- {
- example_init++;
- VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST));
- (void) hash_init(&example_open_tables,system_charset_info,32,0,0,
- (hash_get_key) example_get_key,0,0);
- }
- pthread_mutex_unlock(&LOCK_mysql_create_db);
- }
- pthread_mutex_lock(&example_mutex);
- length=(uint) strlen(table_name);
-
- if (!(share=(EXAMPLE_SHARE*) hash_search(&example_open_tables,
- (byte*) table_name,
- length)))
- {
- if (!(share=(EXAMPLE_SHARE *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &share, sizeof(*share),
- &tmp_name, length+1,
- NullS)))
- {
- pthread_mutex_unlock(&example_mutex);
- return NULL;
- }
-
- share->use_count=0;
- share->table_name_length=length;
- share->table_name=tmp_name;
- strmov(share->table_name,table_name);
- if (my_hash_insert(&example_open_tables, (byte*) share))
- goto error;
- thr_lock_init(&share->lock);
- pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
- }
- share->use_count++;
- pthread_mutex_unlock(&example_mutex);
-
- return share;
-
-error:
- pthread_mutex_destroy(&share->mutex);
- pthread_mutex_unlock(&example_mutex);
- my_free((gptr) share, MYF(0));
-
- return NULL;
-}
-
-
-/*
- Free lock controls. We call this whenever we close a table. If the table had
- the last reference to the share then we free memory associated with it.
-*/
-static int free_share(EXAMPLE_SHARE *share)
-{
- pthread_mutex_lock(&example_mutex);
- if (!--share->use_count)
- {
- hash_delete(&example_open_tables, (byte*) share);
- thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
- my_free((gptr) share, MYF(0));
- }
- pthread_mutex_unlock(&example_mutex);
-
- return 0;
-}
-
-
-static handler* example_create_handler(TABLE_SHARE *table)
-{
- return new ha_example(table);
-}
-
-
-ha_example::ha_example(TABLE_SHARE *table_arg)
- :handler(&example_hton, table_arg)
-{}
-
-/*
- If frm_error() is called then we will use this to to find out what file extentions
- exist for the storage engine. This is also used by the default rename_table and
- delete_table method in handler.cc.
-*/
-static const char *ha_example_exts[] = {
- NullS
-};
-
-const char **ha_example::bas_ext() const
-{
- return ha_example_exts;
-}
-
-
-/*
- Used for opening tables. The name will be the name of the file.
- A table is opened when it needs to be opened. For instance
- when a request comes in for a select on the table (tables are not
- open and closed for each request, they are cached).
-
- Called from handler.cc by handler::ha_open(). The server opens all tables by
- calling ha_open() which then calls the handler specific open().
-*/
-int ha_example::open(const char *name, int mode, uint test_if_locked)
-{
- DBUG_ENTER("ha_example::open");
-
- if (!(share = get_share(name, table)))
- DBUG_RETURN(1);
- thr_lock_data_init(&share->lock,&lock,NULL);
-
- DBUG_RETURN(0);
-}
-
-
-/*
- Closes a table. We call the free_share() function to free any resources
- that we have allocated in the "shared" structure.
-
- Called from sql_base.cc, sql_select.cc, and table.cc.
- In sql_select.cc it is only used to close up temporary tables or during
- the process where a temporary table is converted over to being a
- myisam table.
- For sql_base.cc look at close_data_tables().
-*/
-int ha_example::close(void)
-{
- DBUG_ENTER("ha_example::close");
- DBUG_RETURN(free_share(share));
-}
-
-
-/*
- write_row() inserts a row. No extra() hint is given currently if a bulk load
- is happeneding. buf() is a byte array of data. You can use the field
- information to extract the data from the native byte array type.
- Example of this would be:
- for (Field **field=table->field ; *field ; field++)
- {
- ...
- }
-
- See ha_tina.cc for an example of extracting all of the data as strings.
- ha_berekly.cc has an example of how to store it intact by "packing" it
- for ha_berkeley's own native storage type.
-
- See the note for update_row() on auto_increments and timestamps. This
- case also applied to write_row().
-
- Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
- sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
-*/
-int ha_example::write_row(byte * buf)
-{
- DBUG_ENTER("ha_example::write_row");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- Yes, update_row() does what you expect, it updates a row. old_data will have
- the previous row record in it, while new_data will have the newest data in
- it.
- Keep in mind that the server can do updates based on ordering if an ORDER BY
- clause was used. Consecutive ordering is not guarenteed.
- Currently new_data will not have an updated auto_increament record, or
- and updated timestamp field. You can do these for example by doing these:
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
- if (table->next_number_field && record == table->record[0])
- update_auto_increment();
-
- Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
-*/
-int ha_example::update_row(const byte * old_data, byte * new_data)
-{
-
- DBUG_ENTER("ha_example::update_row");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- This will delete a row. buf will contain a copy of the row to be deleted.
- The server will call this right after the current row has been called (from
- either a previous rnd_nexT() or index call).
- If you keep a pointer to the last row or can access a primary key it will
- make doing the deletion quite a bit easier.
- Keep in mind that the server does no guarentee consecutive deletions. ORDER BY
- clauses can be used.
-
- Called in sql_acl.cc and sql_udf.cc to manage internal table information.
- Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select it is
- used for removing duplicates while in insert it is used for REPLACE calls.
-*/
-int ha_example::delete_row(const byte * buf)
-{
- DBUG_ENTER("ha_example::delete_row");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- Positions an index cursor to the index specified in the handle. Fetches the
- row if available. If the key value is null, begin at the first key of the
- index.
-*/
-int ha_example::index_read(byte * buf, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
-{
- DBUG_ENTER("ha_example::index_read");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- Positions an index cursor to the index specified in key. Fetches the
- row if any. This is only used to read whole keys.
-*/
-int ha_example::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
-{
- DBUG_ENTER("ha_example::index_read_idx");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- Used to read forward through the index.
-*/
-int ha_example::index_next(byte * buf)
-{
- DBUG_ENTER("ha_example::index_next");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- Used to read backwards through the index.
-*/
-int ha_example::index_prev(byte * buf)
-{
- DBUG_ENTER("ha_example::index_prev");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- index_first() asks for the first key in the index.
-
- Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
- and sql_select.cc.
-*/
-int ha_example::index_first(byte * buf)
-{
- DBUG_ENTER("ha_example::index_first");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- index_last() asks for the last key in the index.
-
- Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
- and sql_select.cc.
-*/
-int ha_example::index_last(byte * buf)
-{
- DBUG_ENTER("ha_example::index_last");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- rnd_init() is called when the system wants the storage engine to do a table
- scan.
- See the example in the introduction at the top of this file to see when
- rnd_init() is called.
-
- Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
- and sql_update.cc.
-*/
-int ha_example::rnd_init(bool scan)
-{
- DBUG_ENTER("ha_example::rnd_init");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_example::rnd_end()
-{
- DBUG_ENTER("ha_example::rnd_end");
- DBUG_RETURN(0);
-}
-
-/*
- This is called for each row of the table scan. When you run out of records
- you should return HA_ERR_END_OF_FILE. Fill buff up with the row information.
- The Field structure for the table is the key to getting data into buf
- in a manner that will allow the server to understand it.
-
- Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
- and sql_update.cc.
-*/
-int ha_example::rnd_next(byte *buf)
-{
- DBUG_ENTER("ha_example::rnd_next");
- DBUG_RETURN(HA_ERR_END_OF_FILE);
-}
-
-
-/*
- position() is called after each call to rnd_next() if the data needs
- to be ordered. You can do something like the following to store
- the position:
- my_store_ptr(ref, ref_length, current_position);
-
- The server uses ref to store data. ref_length in the above case is
- the size needed to store current_position. ref is just a byte array
- that the server will maintain. If you are using offsets to mark rows, then
- current_position should be the offset. If it is a primary key like in
- BDB, then it needs to be a primary key.
-
- Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
-*/
-void ha_example::position(const byte *record)
-{
- DBUG_ENTER("ha_example::position");
- DBUG_VOID_RETURN;
-}
-
-
-/*
- This is like rnd_next, but you are given a position to use
- to determine the row. The position will be of the type that you stored in
- ref. You can use ha_get_ptr(pos,ref_length) to retrieve whatever key
- or position you saved when position() was called.
- Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
-*/
-int ha_example::rnd_pos(byte * buf, byte *pos)
-{
- DBUG_ENTER("ha_example::rnd_pos");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- ::info() is used to return information to the optimizer.
- see my_base.h for the complete description
-
- Currently this table handler doesn't implement most of the fields
- really needed. SHOW also makes use of this data
- Another note, you will probably want to have the following in your
- code:
- if (records < 2)
- records = 2;
- The reason is that the server will optimize for cases of only a single
- record. If in a table scan you don't know the number of records
- it will probably be better to set records to two so you can return
- as many records as you need.
- Along with records a few more variables you may wish to set are:
- records
- deleted
- data_file_length
- index_file_length
- delete_length
- check_time
- Take a look at the public variables in handler.h for more information.
-
- Called in:
- filesort.cc
- ha_heap.cc
- item_sum.cc
- opt_sum.cc
- sql_delete.cc
- sql_delete.cc
- sql_derived.cc
- sql_select.cc
- sql_select.cc
- sql_select.cc
- sql_select.cc
- sql_select.cc
- sql_show.cc
- sql_show.cc
- sql_show.cc
- sql_show.cc
- sql_table.cc
- sql_union.cc
- sql_update.cc
-
-*/
-void ha_example::info(uint flag)
-{
- DBUG_ENTER("ha_example::info");
- DBUG_VOID_RETURN;
-}
-
-
-/*
- extra() is called whenever the server wishes to send a hint to
- the storage engine. The myisam engine implements the most hints.
- ha_innodb.cc has the most exhaustive list of these hints.
-*/
-int ha_example::extra(enum ha_extra_function operation)
-{
- DBUG_ENTER("ha_example::extra");
- DBUG_RETURN(0);
-}
-
-
-/*
- Deprecated and likely to be removed in the future. Storage engines normally
- just make a call like:
- ha_example::extra(HA_EXTRA_RESET);
- to handle it.
-*/
-int ha_example::reset(void)
-{
- DBUG_ENTER("ha_example::reset");
- DBUG_RETURN(0);
-}
-
-
-/*
- Used to delete all rows in a table. Both for cases of truncate and
- for cases where the optimizer realizes that all rows will be
- removed as a result of a SQL statement.
-
- Called from item_sum.cc by Item_func_group_concat::clear(),
- Item_sum_count_distinct::clear(), and Item_func_group_concat::clear().
- Called from sql_delete.cc by mysql_delete().
- Called from sql_select.cc by JOIN::reinit().
- Called from sql_union.cc by st_select_lex_unit::exec().
-*/
-int ha_example::delete_all_rows()
-{
- DBUG_ENTER("ha_example::delete_all_rows");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/*
- First you should go read the section "locking functions for mysql" in
- lock.cc to understand this.
- This create a lock on the table. If you are implementing a storage engine
- that can handle transacations look at ha_berkely.cc to see how you will
- want to goo about doing this. Otherwise you should consider calling flock()
- here.
-
- Called from lock.cc by lock_external() and unlock_external(). Also called
- from sql_table.cc by copy_data_between_tables().
-*/
-int ha_example::external_lock(THD *thd, int lock_type)
-{
- DBUG_ENTER("ha_example::external_lock");
- DBUG_RETURN(0);
-}
-
-
-/*
- The idea with handler::store_lock() is the following:
-
- The statement decided which locks we should need for the table
- for updates/deletes/inserts we get WRITE locks, for SELECT... we get
- read locks.
-
- Before adding the lock into the table lock handler (see thr_lock.c)
- mysqld calls store lock with the requested locks. Store lock can now
- modify a write lock to a read lock (or some other lock), ignore the
- lock (if we don't want to use MySQL table locks at all) or add locks
- for many tables (like we do when we are using a MERGE handler).
-
- Berkeley DB for example changes all WRITE locks to TL_WRITE_ALLOW_WRITE
- (which signals that we are doing WRITES, but we are still allowing other
- reader's and writer's.
-
- When releasing locks, store_lock() are also called. In this case one
- usually doesn't have to do anything.
-
- In some exceptional cases MySQL may send a request for a TL_IGNORE;
- This means that we are requesting the same lock as last time and this
- should also be ignored. (This may happen when someone does a flush
- table when we have opened a part of the tables, in which case mysqld
- closes and reopens the tables and tries to get the same locks at last
- time). In the future we will probably try to remove this.
-
- Called from lock.cc by get_lock_data().
-*/
-THR_LOCK_DATA **ha_example::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
- lock.type=lock_type;
- *to++= &lock;
- return to;
-}
-
-/*
- Used to delete a table. By the time delete_table() has been called all
- opened references to this table will have been closed (and your globally
- shared references released. The variable name will just be the name of
- the table. You will need to remove any files you have created at this point.
-
- If you do not implement this, the default delete_table() is called from
- handler.cc and it will delete all files with the file extentions returned
- by bas_ext().
-
- Called from handler.cc by delete_table and ha_create_table(). Only used
- during create if the table_flag HA_DROP_BEFORE_CREATE was specified for
- the storage engine.
-*/
-int ha_example::delete_table(const char *name)
-{
- DBUG_ENTER("ha_example::delete_table");
- /* This is not implemented but we want someone to be able that it works. */
- DBUG_RETURN(0);
-}
-
-/*
- Renames a table from one name to another from alter table call.
-
- If you do not implement this, the default rename_table() is called from
- handler.cc and it will delete all files with the file extentions returned
- by bas_ext().
-
- Called from sql_table.cc by mysql_rename_table().
-*/
-int ha_example::rename_table(const char * from, const char * to)
-{
- DBUG_ENTER("ha_example::rename_table ");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-/*
- Given a starting key, and an ending key estimate the number of rows that
- will exist between the two. end_key may be empty which in case determine
- if start_key matches any rows.
-
- Called from opt_range.cc by check_quick_keys().
-*/
-ha_rows ha_example::records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
-{
- DBUG_ENTER("ha_example::records_in_range");
- DBUG_RETURN(10); // low number to force index usage
-}
-
-
-/*
- create() is called to create a database. The variable name will have the name
- of the table. When create() is called you do not need to worry about opening
- the table. Also, the FRM file will have already been created so adjusting
- create_info will not do you any good. You can overwrite the frm file at this
- point if you wish to change the table definition, but there are no methods
- currently provided for doing that.
-
- Called from handle.cc by ha_create_table().
-*/
-int ha_example::create(const char *name, TABLE *table_arg,
- HA_CREATE_INFO *create_info)
-{
- DBUG_ENTER("ha_example::create");
- /* This is not implemented but we want someone to be able that it works. */
- DBUG_RETURN(0);
-}
diff --git a/sql/examples/ha_example.h b/sql/examples/ha_example.h
deleted file mode 100644
index 139a50a3281..00000000000
--- a/sql/examples/ha_example.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* 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 example storage engine implements all methods
- that are required to be implemented. handler.h has a full list of methods
- that you can implement.
-*/
-
-#ifdef USE_PRAGMA_INTERFACE
-#pragma interface /* gcc class implementation */
-#endif
-
-/*
- EXAMPLE_SHARE is a structure that will be shared amoung all open handlers
- The example implements the minimum of what you will probably need.
-*/
-typedef struct st_example_share {
- char *table_name;
- uint table_name_length,use_count;
- pthread_mutex_t mutex;
- THR_LOCK lock;
-} EXAMPLE_SHARE;
-
-/*
- Class definition for the storage engine
-*/
-class ha_example: public handler
-{
- THR_LOCK_DATA lock; /* MySQL lock */
- EXAMPLE_SHARE *share; /* Shared lock info */
-
-public:
- ha_example(TABLE_SHARE *table_arg);
- ~ha_example()
- {
- }
- /* The name that will be used for display purposes */
- const char *table_type() const { return "EXAMPLE"; }
- /*
- 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 "HASH"; }
- 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
- */
- ulong table_flags() const
- {
- return 0;
- }
- /*
- 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 0;
- }
- /*
- unireg.cc will call the following to make sure that the storage engine can
- handle the data it is about to send.
-
- Return *real* limits of your storage engine here. MySQL will do
- min(your_limits, MySQL_limits) automatically
-
- There is no need to implement ..._key_... methods if you don't suport
- indexes.
- */
- uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_supported_keys() const { return 0; }
- uint max_supported_key_parts() const { return 0; }
- uint max_supported_key_length() const { return 0; }
- /*
- Called in test_quick_select to determine if indexes should be used.
- */
- virtual double scan_time() { return (double) (records+deleted) / 20.0+10; }
- /*
- 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_example.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_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_prev(byte * buf);
- int index_first(byte * buf);
- int index_last(byte * buf);
- /*
- 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 extra(enum ha_extra_function operation);
- int reset(void);
- int external_lock(THD *thd, int lock_type); //required
- int delete_all_rows(void);
- ha_rows records_in_range(uint inx, key_range *min_key,
- key_range *max_key);
- int delete_table(const char *from);
- int rename_table(const char * from, const char * to);
- 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
-};
-
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
deleted file mode 100644
index 4f2dc0b5cac..00000000000
--- a/sql/examples/ha_tina.cc
+++ /dev/null
@@ -1,935 +0,0 @@
-/* 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 */
-
-/*
- Make sure to look at ha_tina.h for more details.
-
- First off, this is a play thing for me, there are a number of things
- wrong with it:
- *) It was designed for csv and therefore its performance is highly
- questionable.
- *) Indexes have not been implemented. This is because the files can
- be traded in and out of the table directory without having to worry
- about rebuilding anything.
- *) NULLs and "" are treated equally (like a spreadsheet).
- *) There was in the beginning no point to anyone seeing this other
- then me, so there is a good chance that I haven't quite documented
- it well.
- *) Less design, more "make it work"
-
- Now there are a few cool things with it:
- *) Errors can result in corrupted data files.
- *) Data files can be read by spreadsheets directly.
-
-TODO:
- *) Move to a block system for larger files
- *) Error recovery, its all there, just need to finish it
- *) Document how the chains work.
-
- -Brian
-*/
-
-#ifdef USE_PRAGMA_IMPLEMENTATION
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-
-#include "ha_tina.h"
-#include <sys/mman.h>
-
-/* Stuff for shares */
-pthread_mutex_t tina_mutex;
-static HASH tina_open_tables;
-static int tina_init= 0;
-static handler *tina_create_handler(TABLE_SHARE *table);
-
-handlerton tina_hton= {
- "CSV",
- SHOW_OPTION_YES,
- "CSV storage engine",
- DB_TYPE_CSV_DB,
- NULL, /* One needs to be written! */
- 0, /* slot */
- 0, /* savepoint size. */
- NULL, /* close_connection */
- NULL, /* savepoint */
- NULL, /* rollback to savepoint */
- NULL, /* release savepoint */
- NULL, /* commit */
- NULL, /* rollback */
- NULL, /* prepare */
- NULL, /* recover */
- NULL, /* commit_by_xid */
- NULL, /* rollback_by_xid */
- NULL, /* create_cursor_read_view */
- NULL, /* set_cursor_read_view */
- NULL, /* close_cursor_read_view */
- tina_create_handler, /* Create a new handler */
- NULL, /* Drop a database */
- tina_end, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
- NULL, /* Start Consistent Snapshot */
- NULL, /* Flush logs */
- NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
- HTON_CAN_RECREATE
-};
-
-/*****************************************************************************
- ** TINA tables
- *****************************************************************************/
-
-/*
- Used for sorting chains with qsort().
-*/
-int sort_set (tina_set *a, tina_set *b)
-{
- /*
- We assume that intervals do not intersect. So, it is enought to compare
- any two points. Here we take start of intervals for comparison.
- */
- return ( a->begin > b->begin ? -1 : ( a->begin < b->begin ? 1 : 0 ) );
-}
-
-static byte* tina_get_key(TINA_SHARE *share,uint *length,
- my_bool not_used __attribute__((unused)))
-{
- *length=share->table_name_length;
- return (byte*) share->table_name;
-}
-
-/*
- Reloads the mmap file.
-*/
-int get_mmap(TINA_SHARE *share, int write)
-{
- DBUG_ENTER("ha_tina::get_mmap");
- if (share->mapped_file && my_munmap(share->mapped_file,
- share->file_stat.st_size))
- DBUG_RETURN(1);
-
- if (my_fstat(share->data_file, &share->file_stat, MYF(MY_WME)) == -1)
- DBUG_RETURN(1);
-
- if (share->file_stat.st_size)
- {
- if (write)
- share->mapped_file= (byte *)my_mmap(NULL, share->file_stat.st_size,
- PROT_READ|PROT_WRITE, MAP_SHARED,
- share->data_file, 0);
- else
- share->mapped_file= (byte *)my_mmap(NULL, share->file_stat.st_size,
- PROT_READ, MAP_PRIVATE,
- share->data_file, 0);
- if ((share->mapped_file ==(caddr_t)-1))
- {
- /*
- Bad idea you think? See the problem is that nothing actually checks
- the return value of ::rnd_init(), so tossing an error is about
- it for us.
- Never going to happen right? :)
- */
- my_message(errno, "Woops, blew up opening a mapped file", 0);
- DBUG_ASSERT(0);
- DBUG_RETURN(1);
- }
- }
- else
- share->mapped_file= NULL;
-
- DBUG_RETURN(0);
-}
-
-/*
- Simple lock controls.
-*/
-static TINA_SHARE *get_share(const char *table_name, TABLE *table)
-{
- TINA_SHARE *share;
- char *tmp_name;
- uint length;
-
- if (!tina_init)
- {
- /* Hijack a mutex for init'ing the storage engine */
- pthread_mutex_lock(&LOCK_mysql_create_db);
- if (!tina_init)
- {
- tina_init++;
- VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
- (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
- (hash_get_key) tina_get_key,0,0);
- }
- pthread_mutex_unlock(&LOCK_mysql_create_db);
- }
- pthread_mutex_lock(&tina_mutex);
- length=(uint) strlen(table_name);
- if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
- (byte*) table_name,
- length)))
- {
- char data_file_name[FN_REFLEN];
- if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &share, sizeof(*share),
- &tmp_name, length+1,
- NullS))
- {
- pthread_mutex_unlock(&tina_mutex);
- return NULL;
- }
-
- share->use_count= 0;
- share->table_name_length= length;
- share->table_name= tmp_name;
- strmov(share->table_name, table_name);
- fn_format(data_file_name, table_name, "", ".CSV",
- MY_REPLACE_EXT|MY_UNPACK_FILENAME);
- if (my_hash_insert(&tina_open_tables, (byte*) share))
- goto error;
- thr_lock_init(&share->lock);
- pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
-
- if ((share->data_file= my_open(data_file_name, O_RDWR|O_APPEND,
- MYF(0))) == -1)
- goto error2;
-
- /*
- We only use share->data_file for writing, so we scan to
- the end to append
- */
- if (my_seek(share->data_file, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
- goto error2;
-
- share->mapped_file= NULL; // We don't know the state as we just allocated it
- if (get_mmap(share, 0) > 0)
- goto error3;
- }
- share->use_count++;
- pthread_mutex_unlock(&tina_mutex);
-
- return share;
-
-error3:
- my_close(share->data_file,MYF(0));
-error2:
- thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
-error:
- pthread_mutex_unlock(&tina_mutex);
- my_free((gptr) share, MYF(0));
-
- return NULL;
-}
-
-
-/*
- Free lock controls.
-*/
-static int free_share(TINA_SHARE *share)
-{
- DBUG_ENTER("ha_tina::free_share");
- pthread_mutex_lock(&tina_mutex);
- int result_code= 0;
- if (!--share->use_count){
- /* Drop the mapped file */
- if (share->mapped_file)
- my_munmap(share->mapped_file, share->file_stat.st_size);
- result_code= my_close(share->data_file,MYF(0));
- hash_delete(&tina_open_tables, (byte*) share);
- thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
- my_free((gptr) share, MYF(0));
- }
- pthread_mutex_unlock(&tina_mutex);
-
- DBUG_RETURN(result_code);
-}
-
-int tina_end(ha_panic_function type)
-{
- if (tina_init)
- {
- hash_free(&tina_open_tables);
- VOID(pthread_mutex_destroy(&tina_mutex));
- }
- tina_init= 0;
- return 0;
-}
-
-/*
- Finds the end of a line.
- Currently only supports files written on a UNIX OS.
-*/
-byte * find_eoln(byte *data, off_t begin, off_t end)
-{
- for (off_t x= begin; x < end; x++)
- if (data[x] == '\n')
- return data + x;
-
- return 0;
-}
-
-
-static handler *tina_create_handler(TABLE_SHARE *table)
-{
- return new ha_tina(table);
-}
-
-
-ha_tina::ha_tina(TABLE_SHARE *table_arg)
- :handler(&tina_hton, table_arg),
- /*
- These definitions are found in handler.h
- They are not probably completely right.
- */
- current_position(0), next_position(0), chain_alloced(0),
- chain_size(DEFAULT_CHAIN_LENGTH), records_is_known(0)
-{
- /* Set our original buffers from pre-allocated memory */
- buffer.set(byte_buffer, IO_SIZE, system_charset_info);
- chain= chain_buffer;
-}
-
-/*
- Encode a buffer into the quoted format.
-*/
-
-int ha_tina::encode_quote(byte *buf)
-{
- char attribute_buffer[1024];
- String attribute(attribute_buffer, sizeof(attribute_buffer), &my_charset_bin);
-
- buffer.length(0);
- for (Field **field=table->field ; *field ; field++)
- {
- const char *ptr;
- const char *end_ptr;
-
- (*field)->val_str(&attribute,&attribute);
- ptr= attribute.ptr();
- end_ptr= attribute.length() + ptr;
-
- buffer.append('"');
-
- while (ptr < end_ptr)
- {
- if (*ptr == '"')
- {
- buffer.append('\\');
- buffer.append('"');
- *ptr++;
- }
- else if (*ptr == '\r')
- {
- buffer.append('\\');
- buffer.append('r');
- *ptr++;
- }
- else if (*ptr == '\\')
- {
- buffer.append('\\');
- buffer.append('\\');
- *ptr++;
- }
- else if (*ptr == '\n')
- {
- buffer.append('\\');
- buffer.append('n');
- *ptr++;
- }
- else
- buffer.append(*ptr++);
- }
- buffer.append('"');
- buffer.append(',');
- }
- // Remove the comma, add a line feed
- buffer.length(buffer.length() - 1);
- buffer.append('\n');
- //buffer.replace(buffer.length(), 0, "\n", 1);
-
- return (buffer.length());
-}
-
-/*
- chain_append() adds delete positions to the chain that we use to keep
- track of space. Then the chain will be used to cleanup "holes", occured
- due to deletes and updates.
-*/
-int ha_tina::chain_append()
-{
- if ( chain_ptr != chain && (chain_ptr -1)->end == current_position)
- (chain_ptr -1)->end= next_position;
- else
- {
- /* We set up for the next position */
- if ((off_t)(chain_ptr - chain) == (chain_size -1))
- {
- off_t location= chain_ptr - chain;
- chain_size += DEFAULT_CHAIN_LENGTH;
- if (chain_alloced)
- {
- /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
- if ((chain= (tina_set *) my_realloc((gptr)chain,
- chain_size, MYF(MY_WME))) == NULL)
- return -1;
- }
- else
- {
- tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
- MYF(MY_WME));
- memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
- chain= ptr;
- chain_alloced++;
- }
- chain_ptr= chain + location;
- }
- chain_ptr->begin= current_position;
- chain_ptr->end= next_position;
- chain_ptr++;
- }
-
- return 0;
-}
-
-
-/*
- Scans for a row.
-*/
-int ha_tina::find_current_row(byte *buf)
-{
- byte *mapped_ptr= (byte *)share->mapped_file + current_position;
- byte *end_ptr;
- DBUG_ENTER("ha_tina::find_current_row");
-
- /* EOF should be counted as new line */
- if ((end_ptr= find_eoln(share->mapped_file, current_position,
- share->file_stat.st_size)) == 0)
- DBUG_RETURN(HA_ERR_END_OF_FILE);
-
- for (Field **field=table->field ; *field ; field++)
- {
- buffer.length(0);
- mapped_ptr++; // Increment past the first quote
- for(;mapped_ptr != end_ptr; mapped_ptr++)
- {
- // Need to convert line feeds!
- if (*mapped_ptr == '"' &&
- (((mapped_ptr[1] == ',') && (mapped_ptr[2] == '"')) ||
- (mapped_ptr == end_ptr -1 )))
- {
- mapped_ptr += 2; // Move past the , and the "
- break;
- }
- if (*mapped_ptr == '\\' && mapped_ptr != (end_ptr - 1))
- {
- mapped_ptr++;
- if (*mapped_ptr == 'r')
- buffer.append('\r');
- else if (*mapped_ptr == 'n' )
- buffer.append('\n');
- else if ((*mapped_ptr == '\\') || (*mapped_ptr == '"'))
- buffer.append(*mapped_ptr);
- else /* This could only happed with an externally created file */
- {
- buffer.append('\\');
- buffer.append(*mapped_ptr);
- }
- }
- else
- buffer.append(*mapped_ptr);
- }
- (*field)->store(buffer.ptr(), buffer.length(), system_charset_info);
- }
- next_position= (end_ptr - share->mapped_file)+1;
- /* Maybe use \N for null? */
- memset(buf, 0, table->s->null_bytes); /* We do not implement nulls! */
-
- DBUG_RETURN(0);
-}
-
-/*
- If frm_error() is called in table.cc this is called to find out what file
- extensions exist for this handler.
-*/
-static const char *ha_tina_exts[] = {
- ".CSV",
- NullS
-};
-
-const char **ha_tina::bas_ext() const
-{
- return ha_tina_exts;
-}
-
-
-/*
- Open a database file. Keep in mind that tables are caches, so
- this will not be called for every request. Any sort of positions
- that need to be reset should be kept in the ::extra() call.
-*/
-int ha_tina::open(const char *name, int mode, uint test_if_locked)
-{
- DBUG_ENTER("ha_tina::open");
-
- if (!(share= get_share(name, table)))
- DBUG_RETURN(1);
- thr_lock_data_init(&share->lock,&lock,NULL);
- ref_length=sizeof(off_t);
-
- DBUG_RETURN(0);
-}
-
-
-/*
- Close a database file. We remove ourselves from the shared strucutre.
- If it is empty we destroy it and free the mapped file.
-*/
-int ha_tina::close(void)
-{
- DBUG_ENTER("ha_tina::close");
- DBUG_RETURN(free_share(share));
-}
-
-/*
- This is an INSERT. At the moment this handler just seeks to the end
- of the file and appends the data. In an error case it really should
- just truncate to the original position (this is not done yet).
-*/
-int ha_tina::write_row(byte * buf)
-{
- int size;
- DBUG_ENTER("ha_tina::write_row");
-
- statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
-
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
-
- size= encode_quote(buf);
-
- if (my_write(share->data_file, buffer.ptr(), size, MYF(MY_WME | MY_NABP)))
- DBUG_RETURN(-1);
-
- /*
- Ok, this is means that we will be doing potentially bad things
- during a bulk insert on some OS'es. What we need is a cleanup
- call for ::write_row that would let us fix up everything after the bulk
- insert. The archive handler does this with an extra mutx call, which
- might be a solution for this.
- */
- if (get_mmap(share, 0) > 0)
- DBUG_RETURN(-1);
- records++;
- DBUG_RETURN(0);
-}
-
-
-/*
- This is called for an update.
- Make sure you put in code to increment the auto increment, also
- update any timestamp data. Currently auto increment is not being
- fixed since autoincrements have yet to be added to this table handler.
- This will be called in a table scan right before the previous ::rnd_next()
- call.
-*/
-int ha_tina::update_row(const byte * old_data, byte * new_data)
-{
- int size;
- DBUG_ENTER("ha_tina::update_row");
-
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
-
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
-
- size= encode_quote(new_data);
-
- if (chain_append())
- DBUG_RETURN(-1);
-
- if (my_write(share->data_file, buffer.ptr(), size, MYF(MY_WME | MY_NABP)))
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
-}
-
-
-/*
- Deletes a row. First the database will find the row, and then call this
- method. In the case of a table scan, the previous call to this will be
- the ::rnd_next() that found this row.
- The exception to this is an ORDER BY. This will cause the table handler
- to walk the table noting the positions of all rows that match a query.
- The table will then be deleted/positioned based on the ORDER (so RANDOM,
- DESC, ASC).
-*/
-int ha_tina::delete_row(const byte * buf)
-{
- DBUG_ENTER("ha_tina::delete_row");
- statistic_increment(table->in_use->status_var.ha_delete_count,
- &LOCK_status);
-
- if (chain_append())
- DBUG_RETURN(-1);
-
- --records;
-
- DBUG_RETURN(0);
-}
-
-/*
- Fill buf with value from key. Simply this is used for a single index read
- with a key.
-*/
-int ha_tina::index_read(byte * buf, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
-{
- DBUG_ENTER("ha_tina::index_read");
- DBUG_ASSERT(0);
- DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
-}
-
-/*
- Fill buf with value from key. Simply this is used for a single index read
- with a key.
- Whatever the current key is we will use it. This is what will be in "index".
-*/
-int ha_tina::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
-{
- DBUG_ENTER("ha_tina::index_read_idx");
- DBUG_ASSERT(0);
- DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
-}
-
-
-/*
- Read the next position in the index.
-*/
-int ha_tina::index_next(byte * buf)
-{
- DBUG_ENTER("ha_tina::index_next");
- DBUG_ASSERT(0);
- DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
-}
-
-/*
- Read the previous position in the index.
-*/
-int ha_tina::index_prev(byte * buf)
-{
- DBUG_ENTER("ha_tina::index_prev");
- DBUG_ASSERT(0);
- DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
-}
-
-/*
- Read the first position in the index
-*/
-int ha_tina::index_first(byte * buf)
-{
- DBUG_ENTER("ha_tina::index_first");
- DBUG_ASSERT(0);
- DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
-}
-
-/*
- Read the last position in the index
- With this we don't need to do a filesort() with index.
- We just read the last row and call previous.
-*/
-int ha_tina::index_last(byte * buf)
-{
- DBUG_ENTER("ha_tina::index_last");
- DBUG_ASSERT(0);
- DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
-}
-
-/*
- All table scans call this first.
- The order of a table scan is:
-
- ha_tina::store_lock
- ha_tina::external_lock
- ha_tina::info
- ha_tina::rnd_init
- ha_tina::extra
- ENUM HA_EXTRA_CACHE Cash record in HA_rrnd()
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::rnd_next
- ha_tina::extra
- ENUM HA_EXTRA_NO_CACHE End cacheing of records (def)
- ha_tina::external_lock
- ha_tina::extra
- ENUM HA_EXTRA_RESET Reset database to after open
-
- Each call to ::rnd_next() represents a row returned in the can. When no more
- rows can be returned, rnd_next() returns a value of HA_ERR_END_OF_FILE.
- The ::info() call is just for the optimizer.
-
-*/
-
-int ha_tina::rnd_init(bool scan)
-{
- DBUG_ENTER("ha_tina::rnd_init");
-
- current_position= next_position= 0;
- records= 0;
- records_is_known= 0;
- chain_ptr= chain;
-#ifdef HAVE_MADVISE
- if (scan)
- (void) madvise(share->mapped_file, share->file_stat.st_size,
- MADV_SEQUENTIAL);
-#endif
-
- DBUG_RETURN(0);
-}
-
-/*
- ::rnd_next() does all the heavy lifting for a table scan. You will need to
- populate *buf with the correct field data. You can walk the field to
- determine at what position you should store the data (take a look at how
- ::find_current_row() works). The structure is something like:
- 0Foo Dog Friend
- The first offset is for the first attribute. All space before that is
- reserved for null count.
- Basically this works as a mask for which rows are nulled (compared to just
- empty).
- This table handler doesn't do nulls and does not know the difference between
- NULL and "". This is ok since this table handler is for spreadsheets and
- they don't know about them either :)
-*/
-int ha_tina::rnd_next(byte *buf)
-{
- DBUG_ENTER("ha_tina::rnd_next");
-
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
-
- current_position= next_position;
- if (!share->mapped_file)
- DBUG_RETURN(HA_ERR_END_OF_FILE);
- if (HA_ERR_END_OF_FILE == find_current_row(buf) )
- DBUG_RETURN(HA_ERR_END_OF_FILE);
-
- records++;
- DBUG_RETURN(0);
-}
-
-/*
- In the case of an order by rows will need to be sorted.
- ::position() is called after each call to ::rnd_next(),
- the data it stores is to a byte array. You can store this
- data via my_store_ptr(). ref_length is a variable defined to the
- class that is the sizeof() of position being stored. In our case
- its just a position. Look at the bdb code if you want to see a case
- where something other then a number is stored.
-*/
-void ha_tina::position(const byte *record)
-{
- DBUG_ENTER("ha_tina::position");
- my_store_ptr(ref, ref_length, current_position);
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Used to fetch a row from a posiion stored with ::position().
- my_get_ptr() retrieves the data for you.
-*/
-
-int ha_tina::rnd_pos(byte * buf, byte *pos)
-{
- DBUG_ENTER("ha_tina::rnd_pos");
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
- current_position= my_get_ptr(pos,ref_length);
- DBUG_RETURN(find_current_row(buf));
-}
-
-/*
- ::info() is used to return information to the optimizer.
- Currently this table handler doesn't implement most of the fields
- really needed. SHOW also makes use of this data
-*/
-void ha_tina::info(uint flag)
-{
- DBUG_ENTER("ha_tina::info");
- /* This is a lie, but you don't want the optimizer to see zero or 1 */
- if (!records_is_known && records < 2)
- records= 2;
- DBUG_VOID_RETURN;
-}
-
-/*
- Grab bag of flags that are sent to the able handler every so often.
- HA_EXTRA_RESET and HA_EXTRA_RESET_STATE are the most frequently called.
- You are not required to implement any of these.
-*/
-int ha_tina::extra(enum ha_extra_function operation)
-{
- DBUG_ENTER("ha_tina::extra");
- DBUG_RETURN(0);
-}
-
-/*
- This is no longer used.
-*/
-int ha_tina::reset(void)
-{
- DBUG_ENTER("ha_tina::reset");
- ha_tina::extra(HA_EXTRA_RESET);
- DBUG_RETURN(0);
-}
-
-
-/*
- Called after each table scan. In particular after deletes,
- and updates. In the last case we employ chain of deleted
- slots to clean up all of the dead space we have collected while
- performing deletes/updates.
-*/
-int ha_tina::rnd_end()
-{
- DBUG_ENTER("ha_tina::rnd_end");
-
- records_is_known= 1;
-
- /* First position will be truncate position, second will be increment */
- if ((chain_ptr - chain) > 0)
- {
- tina_set *ptr;
- off_t length;
-
- /*
- Setting up writable map, this will contain all of the data after the
- get_mmap call that we have added to the file.
- */
- if (get_mmap(share, 1) > 0)
- DBUG_RETURN(-1);
- length= share->file_stat.st_size;
-
- /*
- The sort handles updates/deletes with random orders.
- It also sorts so that we move the final blocks to the
- beginning so that we move the smallest amount of data possible.
- */
- qsort(chain, (size_t)(chain_ptr - chain), sizeof(tina_set),
- (qsort_cmp)sort_set);
- for (ptr= chain; ptr < chain_ptr; ptr++)
- {
- memmove(share->mapped_file + ptr->begin, share->mapped_file + ptr->end,
- length - (size_t)ptr->end);
- length= length - (size_t)(ptr->end - ptr->begin);
- }
-
- /* Truncate the file to the new size */
- if (my_chsize(share->data_file, length, 0, MYF(MY_WME)))
- DBUG_RETURN(-1);
-
- if (my_munmap(share->mapped_file, length))
- DBUG_RETURN(-1);
-
- /* We set it to null so that get_mmap() won't try to unmap it */
- share->mapped_file= NULL;
- if (get_mmap(share, 0) > 0)
- DBUG_RETURN(-1);
- }
-
- DBUG_RETURN(0);
-}
-
-
-/*
- DELETE without WHERE calls this
-*/
-
-int ha_tina::delete_all_rows()
-{
- DBUG_ENTER("ha_tina::delete_all_rows");
-
- if (!records_is_known)
- return (my_errno=HA_ERR_WRONG_COMMAND);
-
- int rc= my_chsize(share->data_file, 0, 0, MYF(MY_WME));
-
- if (get_mmap(share, 0) > 0)
- DBUG_RETURN(-1);
-
- records=0;
- DBUG_RETURN(rc);
-}
-
-/*
- Always called by the start of a transaction (or by "lock tables");
-*/
-int ha_tina::external_lock(THD *thd, int lock_type)
-{
- DBUG_ENTER("ha_tina::external_lock");
- DBUG_RETURN(0); // No external locking
-}
-
-/*
- Called by the database to lock the table. Keep in mind that this
- is an internal lock.
-*/
-THR_LOCK_DATA **ha_tina::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
- lock.type=lock_type;
- *to++= &lock;
- return to;
-}
-
-/*
- Create a table. You do not want to leave the table open after a call to
- this (the database will call ::open() if it needs to).
-*/
-
-int ha_tina::create(const char *name, TABLE *table_arg,
- HA_CREATE_INFO *create_info)
-{
- char name_buff[FN_REFLEN];
- File create_file;
- DBUG_ENTER("ha_tina::create");
-
- if ((create_file= my_create(fn_format(name_buff, name, "", ".CSV",
- MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
- O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
- DBUG_RETURN(-1);
-
- my_close(create_file,MYF(0));
-
- DBUG_RETURN(0);
-}
-
diff --git a/sql/examples/ha_tina.h b/sql/examples/ha_tina.h
deleted file mode 100644
index c46750fb703..00000000000
--- a/sql/examples/ha_tina.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* 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 */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <my_dir.h>
-
-#define DEFAULT_CHAIN_LENGTH 512
-
-typedef struct st_tina_share {
- char *table_name;
- byte *mapped_file; /* mapped region of file */
- uint table_name_length,use_count;
- MY_STAT file_stat; /* Stat information for the data file */
- File data_file; /* Current open data file */
- pthread_mutex_t mutex;
- THR_LOCK lock;
-} TINA_SHARE;
-
-typedef struct tina_set {
- off_t begin;
- off_t end;
-};
-
-class ha_tina: public handler
-{
- THR_LOCK_DATA lock; /* MySQL lock */
- TINA_SHARE *share; /* Shared lock info */
- off_t current_position; /* Current position in the file during a file scan */
- off_t next_position; /* Next position in the file scan */
- byte byte_buffer[IO_SIZE];
- String buffer;
- /*
- The chain contains "holes" in the file, occured because of
- deletes/updates. It is used in rnd_end() to get rid of them
- in the end of the query.
- */
- tina_set chain_buffer[DEFAULT_CHAIN_LENGTH];
- tina_set *chain;
- tina_set *chain_ptr;
- byte chain_alloced;
- uint32 chain_size;
- bool records_is_known;
-
-public:
- ha_tina(TABLE_SHARE *table_arg);
- ~ha_tina()
- {
- if (chain_alloced)
- my_free((gptr)chain,0);
- }
- const char *table_type() const { return "CSV"; }
- const char *index_type(uint inx) { return "NONE"; }
- const char **bas_ext() const;
- ulong table_flags() const
- {
- return (HA_REC_NOT_IN_SEQ | HA_NOT_EXACT_COUNT |
- HA_NO_AUTO_INCREMENT );
- }
- ulong index_flags(uint idx, uint part, bool all_parts) const
- {
- /* We will never have indexes so this will never be called(AKA we return zero) */
- return 0;
- }
- uint max_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_keys() const { return 0; }
- uint max_key_parts() const { return 0; }
- uint max_key_length() const { return 0; }
- /*
- Called in test_quick_select to determine if indexes should be used.
- */
- virtual double scan_time() { return (double) (records+deleted) / 20.0+10; }
- /* The next method will never be called */
- virtual bool fast_key_read() { return 1;}
- /*
- TODO: return actual upper bound of number of records in the table.
- (e.g. save number of records seen on full table scan and/or use file size
- as upper bound)
- */
- ha_rows estimate_rows_upper_bound() { return HA_POS_ERROR; }
-
- 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_next(byte * buf);
- int index_prev(byte * buf);
- int index_first(byte * buf);
- int index_last(byte * buf);
- int rnd_init(bool scan=1);
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- int rnd_end();
- void position(const byte *record);
- void info(uint);
- int extra(enum ha_extra_function operation);
- int reset(void);
- int external_lock(THD *thd, int lock_type);
- int delete_all_rows(void);
- 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);
-
- /* The following methods were added just for TINA */
- int encode_quote(byte *buf);
- int find_current_row(byte *buf);
- int chain_append();
-};
-
-int tina_end(ha_panic_function type);
-
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index b5c2f2a6555..e5f93ea063c 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -140,6 +140,7 @@ static handler *archive_create_handler(TABLE_SHARE *table);
/* dummy handlerton - only to have something to return from archive_db_init */
handlerton archive_hton = {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"ARCHIVE",
SHOW_OPTION_YES,
"Archive storage engine",
@@ -163,12 +164,9 @@ handlerton archive_hton = {
archive_create_handler, /* Create a new handler */
NULL, /* Drop a database */
archive_db_end, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_NO_FLAGS
};
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 7ef7b6bbf0f..b5d231ee8f8 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -114,20 +114,24 @@ static void berkeley_noticecall(DB_ENV *db_env, db_notices notice);
static int berkeley_close_connection(THD *thd);
static int berkeley_commit(THD *thd, bool all);
static int berkeley_rollback(THD *thd, bool all);
+static int berkeley_rollback_to_savepoint(THD* thd, void *savepoint);
+static int berkeley_savepoint(THD* thd, void *savepoint);
+static int berkeley_release_savepoint(THD* thd, void *savepoint);
static handler *berkeley_create_handler(TABLE_SHARE *table);
handlerton berkeley_hton = {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"BerkeleyDB",
SHOW_OPTION_YES,
"Supports transactions and page-level locking",
DB_TYPE_BERKELEY_DB,
berkeley_init,
0, /* slot */
- 0, /* savepoint size */
+ sizeof(DB_TXN *), /* savepoint size */
berkeley_close_connection,
- NULL, /* savepoint_set */
- NULL, /* savepoint_rollback */
- NULL, /* savepoint_release */
+ berkeley_savepoint, /* savepoint_set */
+ berkeley_rollback_to_savepoint, /* savepoint_rollback */
+ berkeley_release_savepoint, /* savepoint_release */
berkeley_commit,
berkeley_rollback,
NULL, /* prepare */
@@ -140,12 +144,9 @@ handlerton berkeley_hton = {
berkeley_create_handler, /* Create a new handler */
NULL, /* Drop a database */
berkeley_end, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
berkeley_flush_logs, /* Flush logs */
berkeley_show_status, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME
};
@@ -157,6 +158,7 @@ handler *berkeley_create_handler(TABLE_SHARE *table)
typedef struct st_berkeley_trx_data {
DB_TXN *all;
DB_TXN *stmt;
+ DB_TXN *sp_level;
uint bdb_lock_count;
} berkeley_trx_data;
@@ -309,10 +311,53 @@ static int berkeley_rollback(THD *thd, bool all)
DBUG_RETURN(error);
}
+static int berkeley_savepoint(THD* thd, void *savepoint)
+{
+ int error;
+ DB_TXN **save_txn= (DB_TXN**) savepoint;
+ DBUG_ENTER("berkeley_savepoint");
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ if (!(error= db_env->txn_begin(db_env, trx->sp_level, save_txn, 0)))
+ {
+ trx->sp_level= *save_txn;
+ }
+ DBUG_RETURN(error);
+}
+
+static int berkeley_rollback_to_savepoint(THD* thd, void *savepoint)
+{
+ int error;
+ DB_TXN *parent, **save_txn= (DB_TXN**) savepoint;
+ DBUG_ENTER("berkeley_rollback_to_savepoint");
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ parent= (*save_txn)->parent;
+ if (!(error= (*save_txn)->abort(*save_txn)))
+ {
+ trx->sp_level= parent;
+ error= berkeley_savepoint(thd, savepoint);
+ }
+ DBUG_RETURN(error);
+}
+
+static int berkeley_release_savepoint(THD* thd, void *savepoint)
+{
+ int error;
+ DB_TXN *parent, **save_txn= (DB_TXN**) savepoint;
+ DBUG_ENTER("berkeley_release_savepoint");
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ parent= (*save_txn)->parent;
+ if (!(error= (*save_txn)->commit(*save_txn,0)))
+ {
+ trx->sp_level= parent;
+ *save_txn= 0;
+ }
+ DBUG_RETURN(error);
+}
static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print)
{
char **all_logs, **free_logs, **a, **f;
+ uint hton_name_len= strlen(berkeley_hton.name);
int error=1;
MEM_ROOT **root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC);
MEM_ROOT show_logs_root, *old_mem_root= *root_ptr;
@@ -337,19 +382,20 @@ static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print)
{
for (a = all_logs, f = free_logs; *a; ++a)
{
- const char *status;
if (f && *f && strcmp(*a, *f) == 0)
{
f++;
- status= SHOW_LOG_STATUS_FREE;
+ if ((error= stat_print(thd, berkeley_hton.name, hton_name_len,
+ *a, strlen(*a),
+ STRING_WITH_LEN(SHOW_LOG_STATUS_FREE))))
+ break;
}
else
- status= SHOW_LOG_STATUS_INUSE;
-
- if (stat_print(thd, berkeley_hton.name, *a, status))
{
- error=1;
- goto err;
+ if ((error= stat_print(thd, berkeley_hton.name, hton_name_len,
+ *a, strlen(*a),
+ STRING_WITH_LEN(SHOW_LOG_STATUS_INUSE))))
+ break;
}
}
}
@@ -1882,6 +1928,8 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
if (!trx)
DBUG_RETURN(1);
}
+ if (trx->all == 0)
+ trx->sp_level= 0;
if (lock_type != F_UNLCK)
{
if (!trx->bdb_lock_count++)
@@ -1900,12 +1948,13 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
trx->bdb_lock_count--; // We didn't get the lock
DBUG_RETURN(error);
}
+ trx->sp_level= trx->all;
trans_register_ha(thd, TRUE, &berkeley_hton);
if (thd->in_lock_tables)
DBUG_RETURN(0); // Don't create stmt trans
}
DBUG_PRINT("trans",("starting transaction stmt"));
- if ((error= db_env->txn_begin(db_env, trx->all, &trx->stmt, 0)))
+ if ((error= db_env->txn_begin(db_env, trx->sp_level, &trx->stmt, 0)))
{
/* We leave the possible master transaction open */
trx->bdb_lock_count--; // We didn't get the lock
@@ -1959,7 +2008,7 @@ int ha_berkeley::start_stmt(THD *thd, thr_lock_type lock_type)
if (!trx->stmt)
{
DBUG_PRINT("trans",("starting transaction stmt"));
- error= db_env->txn_begin(db_env, trx->all, &trx->stmt, 0);
+ error= db_env->txn_begin(db_env, trx->sp_level, &trx->stmt, 0);
trans_register_ha(thd, FALSE, &berkeley_hton);
}
transaction= trx->stmt;
diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc
index e2b0fc29d86..615836b9867 100644
--- a/sql/ha_blackhole.cc
+++ b/sql/ha_blackhole.cc
@@ -30,6 +30,7 @@ static handler *blackhole_create_handler(TABLE_SHARE *table);
/* Blackhole storage engine handlerton */
handlerton blackhole_hton= {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"BLACKHOLE",
SHOW_OPTION_YES,
"/dev/null storage engine (anything you write to it disappears)",
@@ -53,12 +54,9 @@ handlerton blackhole_hton= {
blackhole_create_handler, /* Create a new handler */
NULL, /* Drop a database */
NULL, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_CAN_RECREATE
};
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index e0f0b6ee35a..d90f2506e2b 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -367,6 +367,7 @@ static int federated_rollback(THD *thd, bool all);
/* Federated storage engine handlerton */
handlerton federated_hton= {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"FEDERATED",
SHOW_OPTION_YES,
"Federated MySQL storage engine",
@@ -390,12 +391,9 @@ handlerton federated_hton= {
federated_create_handler, /* Create a new handler */
NULL, /* Drop a database */
federated_db_end, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_ALTER_NOT_SUPPORTED
};
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index ddc6c1bfb8f..a83a95ac863 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -27,6 +27,7 @@
static handler *heap_create_handler(TABLE_SHARE *table);
handlerton heap_hton= {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"MEMORY",
SHOW_OPTION_YES,
"Hash based, stored in memory, useful for temporary tables",
@@ -50,12 +51,9 @@ handlerton heap_hton= {
heap_create_handler, /* Create a new handler */
NULL, /* Drop a database */
heap_panic, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_CAN_RECREATE
};
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 1562803aed7..c2e2b64201d 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -208,6 +208,7 @@ static int innobase_release_savepoint(THD* thd, void *savepoint);
static handler *innobase_create_handler(TABLE_SHARE *table);
handlerton innobase_hton = {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"InnoDB",
SHOW_OPTION_YES,
"Supports transactions, row-level locking, and foreign keys",
@@ -231,16 +232,9 @@ handlerton innobase_hton = {
innobase_create_handler, /* Create a new handler */
innobase_drop_database, /* Drop a database */
innobase_end, /* Panic call */
- innobase_release_temporary_latches, /* Release temporary latches */
- innodb_export_status, /* Update Statistics */
innobase_start_trx_and_assign_read_view, /* Start Consistent Snapshot */
innobase_flush_logs, /* Flush logs */
innobase_show_status, /* Show status */
-#ifdef HAVE_REPLICATION
- innobase_repl_report_sent_binlog, /* Replication Report Sent Binlog */
-#else
- NULL,
-#endif
HTON_NO_FLAGS
};
@@ -1977,6 +1971,11 @@ innobase_repl_report_sent_binlog(
int cmp;
ibool can_release_threads = 0;
+ if (!innodb_inited) {
+
+ return 0;
+ }
+
/* If synchronous replication is not switched on, or this thd is
sending binlog to a slave where we do not need synchronous replication,
then return immediately */
@@ -6472,10 +6471,11 @@ ha_innobase::transactional_table_lock(
Here we export InnoDB status variables to MySQL. */
int
-innodb_export_status(void)
+innodb_export_status()
/*======================*/
{
- srv_export_innodb_status();
+ if (innodb_inited)
+ srv_export_innodb_status();
return 0;
}
@@ -6562,7 +6562,8 @@ innodb_show_status(
bool result = FALSE;
- if (stat_print(thd, innobase_hton.name, "", str)) {
+ if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name),
+ STRING_WITH_LEN(""), str, flen)) {
result= TRUE;
}
my_free(str, MYF(0));
@@ -6587,6 +6588,7 @@ innodb_mutex_show_status(
ulint rw_lock_count_os_wait= 0;
ulint rw_lock_count_os_yield= 0;
ulonglong rw_lock_wait_time= 0;
+ uint hton_name_len= strlen(innobase_hton.name), buf1len, buf2len;
DBUG_ENTER("innodb_mutex_show_status");
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
@@ -6601,16 +6603,17 @@ innodb_mutex_show_status(
{
if (mutex->count_using > 0)
{
- my_snprintf(buf1, sizeof(buf1), "%s:%s",
- mutex->cmutex_name, mutex->cfile_name);
- my_snprintf(buf2, sizeof(buf2),
- "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
- "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
- mutex->count_using, mutex->count_spin_loop,
- mutex->count_spin_rounds,
- mutex->count_os_wait, mutex->count_os_yield,
- mutex->lspent_time/1000);
- if (stat_print(thd, innobase_hton.name, buf1, buf2))
+ buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%s",
+ mutex->cmutex_name, mutex->cfile_name);
+ buf2len= my_snprintf(buf2, sizeof(buf2),
+ "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+ "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+ mutex->count_using, mutex->count_spin_loop,
+ mutex->count_spin_rounds,
+ mutex->count_os_wait, mutex->count_os_yield,
+ mutex->lspent_time/1000);
+ if (stat_print(thd, innobase_hton.name, hton_name_len,
+ buf1, buf1len, buf2, buf2len))
{
#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
mutex_exit(&mutex_list_mutex);
@@ -6632,15 +6635,16 @@ innodb_mutex_show_status(
mutex = UT_LIST_GET_NEXT(list, mutex);
}
- my_snprintf(buf2, sizeof(buf2),
- "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
- "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
- rw_lock_count, rw_lock_count_spin_loop,
- rw_lock_count_spin_rounds,
- rw_lock_count_os_wait, rw_lock_count_os_yield,
- rw_lock_wait_time/1000);
+ buf2len= my_snprintf(buf2, sizeof(buf2),
+ "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+ "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+ rw_lock_count, rw_lock_count_spin_loop,
+ rw_lock_count_spin_rounds,
+ rw_lock_count_os_wait, rw_lock_count_os_yield,
+ rw_lock_wait_time/1000);
- if (stat_print(thd, innobase_hton.name, "rw_lock_mutexes", buf2))
+ if (stat_print(thd, innobase_hton.name, hton_name_len,
+ STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len))
{
DBUG_RETURN(1);
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 02d814a9451..6bb0c7838ee 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -55,6 +55,7 @@ static handler *myisam_create_handler(TABLE_SHARE *table);
/* MyISAM handlerton */
handlerton myisam_hton= {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"MyISAM",
SHOW_OPTION_YES,
"Default engine as of MySQL 3.23 with great performance",
@@ -82,12 +83,9 @@ handlerton myisam_hton= {
myisam_create_handler, /* Create a new handler */
NULL, /* Drop a database */
mi_panic,/* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_CAN_RECREATE
};
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 37dfe34b40c..1be4fb62fa1 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -37,6 +37,7 @@ static handler *myisammrg_create_handler(TABLE_SHARE *table);
/* MyISAM MERGE handlerton */
handlerton myisammrg_hton= {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"MRG_MYISAM",
SHOW_OPTION_YES,
"Collection of identical MyISAM tables",
@@ -60,12 +61,9 @@ handlerton myisammrg_hton= {
myisammrg_create_handler, /* Create a new handler */
NULL, /* Drop a database */
myrg_panic, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_CAN_RECREATE
};
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 75ee136c916..ebafbfa6431 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -59,6 +59,7 @@ static int ndbcluster_rollback(THD *thd, bool all);
static handler* ndbcluster_create_handler(TABLE_SHARE *table);
handlerton ndbcluster_hton = {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"ndbcluster",
SHOW_OPTION_YES,
"Clustered, fault-tolerant, memory-based tables",
@@ -82,12 +83,9 @@ handlerton ndbcluster_hton = {
ndbcluster_create_handler, /* Create a new handler */
ndbcluster_drop_database, /* Drop a database */
ndbcluster_end, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
ndbcluster_show_status, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_NO_FLAGS
};
@@ -8060,10 +8058,12 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print,
Ndb::Free_list_usage tmp; tmp.m_name= 0;
while (ndb->get_free_list_usage(&tmp))
{
- my_snprintf(buf, sizeof(buf),
+ uint buflen=
+ my_snprintf(buf, sizeof(buf),
"created=%u, free=%u, sizeof=%u",
tmp.m_created, tmp.m_free, tmp.m_sizeof);
- if (stat_print(thd, ndbcluster_hton.name, tmp.m_name, buf))
+ if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name),
+ tmp.m_name, strlen(tmp.m_name), buf, buflen))
DBUG_RETURN(TRUE);
}
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 650830832cb..2c6fde77abd 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -69,6 +69,7 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE * table);
static handler *partition_create_handler(TABLE_SHARE *share);
handlerton partition_hton = {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"partition",
SHOW_OPTION_YES,
"Partition Storage Engine Helper", /* A comment used by SHOW to describe an engine */
@@ -92,12 +93,9 @@ handlerton partition_hton = {
partition_create_handler, /* Create a new handler */
NULL, /* Drop a database */
NULL, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_NOT_USER_SELECTABLE
};
@@ -697,6 +695,7 @@ bool ha_partition::create_handler_file(const char *name)
void ha_partition::clear_handler_file()
{
my_free((char*) m_file_buffer, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) m_engine_array, MYF(MY_ALLOW_ZERO_PTR));
m_file_buffer= NULL;
m_name_buffer_ptr= NULL;
m_engine_array= NULL;
@@ -715,18 +714,19 @@ bool ha_partition::create_handlers()
for (i= 0; i < m_tot_parts; i++)
{
if (!(m_file[i]= get_new_handler(table_share, current_thd->mem_root,
- (enum db_type) m_engine_array[i])))
+ m_engine_array[i])))
DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i]));
}
m_file[m_tot_parts]= 0;
/* For the moment we only support partition over the same table engine */
- if (m_engine_array[0] == (uchar) DB_TYPE_MYISAM)
+ if (m_engine_array[0] == &myisam_hton)
{
DBUG_PRINT("info", ("MyISAM"));
m_myisam= TRUE;
}
- else if (m_engine_array[0] == (uchar) DB_TYPE_INNODB)
+ /* INNODB may not be compiled in... */
+ else if (ha_legacy_type(m_engine_array[0]) == DB_TYPE_INNODB)
{
DBUG_PRINT("info", ("InnoDB"));
m_innodb= TRUE;
@@ -761,7 +761,7 @@ bool ha_partition::new_handlers_from_part_info()
if (!(m_file[i]= get_new_handler(table_share, thd->mem_root,
part_elem->engine_type)))
goto error;
- DBUG_PRINT("info", ("engine_type: %u", (uint) part_elem->engine_type));
+ DBUG_PRINT("info", ("engine_type: %u", (uint) ha_legacy_type(part_elem->engine_type)));
if (m_is_sub_partitioned)
{
for (j= 0; j < m_part_info->no_subparts; j++)
@@ -769,11 +769,11 @@ bool ha_partition::new_handlers_from_part_info()
if (!(m_file[i]= get_new_handler(table_share, thd->mem_root,
part_elem->engine_type)))
goto error;
- DBUG_PRINT("info", ("engine_type: %u", (uint) part_elem->engine_type));
+ DBUG_PRINT("info", ("engine_type: %u", (uint) ha_legacy_type(part_elem->engine_type)));
}
}
} while (++i < m_part_info->no_parts);
- if (part_elem->engine_type == DB_TYPE_MYISAM)
+ if (part_elem->engine_type == &myisam_hton)
{
DBUG_PRINT("info", ("MyISAM"));
m_myisam= TRUE;
@@ -795,7 +795,7 @@ bool ha_partition::get_from_handler_file(const char *name)
char buff[FN_REFLEN], *address_tot_name_len;
File file;
char *file_buffer, *name_buffer_ptr;
- uchar *engine_array;
+ handlerton **engine_array;
uint i, len_bytes, len_words, tot_partition_words, tot_name_words, chksum;
DBUG_ENTER("ha_partition::get_from_handler_file");
DBUG_PRINT("enter", ("table name: '%s'", name));
@@ -824,7 +824,11 @@ bool ha_partition::get_from_handler_file(const char *name)
goto err2;
m_tot_parts= uint4korr((file_buffer) + 8);
tot_partition_words= (m_tot_parts + 3) / 4;
- engine_array= (uchar *) ((file_buffer) + 12);
+ if (!(engine_array= (handlerton **) my_malloc(m_tot_parts * sizeof(handlerton*),MYF(0))))
+ goto err2;
+ for (i= 0; i < m_tot_parts; i++)
+ engine_array[i]= ha_resolve_by_legacy_type(current_thd,
+ (enum legacy_db_type) *(uchar *) ((file_buffer) + 12 + i));
address_tot_name_len= file_buffer + 12 + 4 * tot_partition_words;
tot_name_words= (uint4korr(address_tot_name_len) + 3) / 4;
if (len_words != (tot_partition_words + tot_name_words + 4))
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index a727a278103..760f99ad8aa 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -46,7 +46,7 @@ private:
/* Data for the partition handler */
char *m_file_buffer; // Buffer with names
char *m_name_buffer_ptr; // Pointer to first partition name
- uchar *m_engine_array; // Array of types of the handlers
+ handlerton **m_engine_array; // Array of types of the handlers
handler **m_file; // Array of references to handler inst.
partition_info *m_part_info; // local reference to partition
byte *m_start_key_ref; // Reference of start key in current
diff --git a/sql/handler.cc b/sql/handler.cc
index 7f825ffda35..1a6122aebbd 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -37,11 +37,32 @@
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
#endif
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+#include "ha_innodb.h"
+#endif
extern handlerton *sys_table_types[];
-
+
/* static functions defined in this file */
+static handler *create_default(TABLE_SHARE *table);
+
+const handlerton default_hton =
+{
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
+ "DEFAULT",
+ SHOW_OPTION_YES,
+ NULL,
+ DB_TYPE_DEFAULT,
+ NULL,
+ 0, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ create_default,
+ NULL, NULL, NULL, NULL, NULL,
+ HTON_NO_FLAGS
+};
+
static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
/* number of entries in handlertons[] */
@@ -53,12 +74,12 @@ ulong savepoint_alloc_size;
struct show_table_alias_st sys_table_aliases[]=
{
- {"INNOBASE", "InnoDB"},
- {"NDB", "NDBCLUSTER"},
- {"BDB", "BERKELEYDB"},
- {"HEAP", "MEMORY"},
- {"MERGE", "MRG_MYISAM"},
- {NullS, NullS}
+ {"INNOBASE", DB_TYPE_INNODB},
+ {"NDB", DB_TYPE_NDBCLUSTER},
+ {"BDB", DB_TYPE_BERKELEY_DB},
+ {"HEAP", DB_TYPE_HEAP},
+ {"MERGE", DB_TYPE_MRG_MYISAM},
+ {NullS, DB_TYPE_UNKNOWN}
};
const char *ha_row_type[] = {
@@ -74,26 +95,22 @@ TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
uint known_extensions_id= 0;
-enum db_type ha_resolve_by_name(const char *name, uint namelen)
+handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name)
{
- THD *thd= current_thd;
show_table_alias_st *table_alias;
- handlerton **types;
+ st_plugin_int *plugin;
if (thd && !my_strnncoll(&my_charset_latin1,
- (const uchar *)name, namelen,
+ (const uchar *)name->str, name->length,
(const uchar *)"DEFAULT", 7))
- return (enum db_type) thd->variables.table_type;
+ return ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT);
-retest:
- for (types= sys_table_types; *types; types++)
+ if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN)))
{
- if ((!my_strnncoll(&my_charset_latin1,
- (const uchar *)name, namelen,
- (const uchar *)(*types)->name,
- strlen((*types)->name))) &&
- !((*types)->flags & HTON_NOT_USER_SELECTABLE))
- return (enum db_type) (*types)->db_type;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
+ return hton;
+ plugin_unlock(plugin);
}
/*
@@ -102,63 +119,99 @@ retest:
for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
{
if (!my_strnncoll(&my_charset_latin1,
- (const uchar *)name, namelen,
+ (const uchar *)name->str, name->length,
(const uchar *)table_alias->alias,
strlen(table_alias->alias)))
- {
- name= table_alias->type;
- namelen= strlen(name);
- goto retest;
- }
+ return ha_resolve_by_legacy_type(thd, table_alias->type);
}
- return DB_TYPE_UNKNOWN;
+ return NULL;
}
-const char *ha_get_storage_engine(enum db_type db_type)
+struct plugin_find_dbtype_st
{
- handlerton **types;
- for (types= sys_table_types; *types; types++)
+ enum legacy_db_type db_type;
+ handlerton *hton;
+};
+
+
+static my_bool plugin_find_dbtype(THD *unused, st_plugin_int *plugin,
+ void *arg)
+{
+ handlerton *types= (handlerton *) plugin->plugin->info;
+ if (types->db_type == ((struct plugin_find_dbtype_st *)arg)->db_type)
{
- if (db_type == (*types)->db_type)
- return (*types)->name;
+ ((struct plugin_find_dbtype_st *)arg)->hton= types;
+ return TRUE;
}
- return "*NONE*";
+ return FALSE;
}
-bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag)
+const char *ha_get_storage_engine(enum legacy_db_type db_type)
{
- handlerton **types;
- for (types= sys_table_types; *types; types++)
+ struct plugin_find_dbtype_st info;
+
+ switch (db_type)
{
- if (db_type == (*types)->db_type)
- return test((*types)->flags & flag);
+ case DB_TYPE_DEFAULT:
+ return "DEFAULT";
+ case DB_TYPE_UNKNOWN:
+ return "UNKNOWN";
+ default:
+ info.db_type= db_type;
+
+ if (!plugin_foreach(NULL, plugin_find_dbtype,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+ return "*NONE*";
+
+ return info.hton->name;
}
- return FALSE; // No matching engine
}
-my_bool ha_storage_engine_is_enabled(enum db_type database_type)
+static handler *create_default(TABLE_SHARE *table)
{
- handlerton **types;
- for (types= sys_table_types; *types; types++)
+ handlerton *hton=ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT);
+ return (hton && hton != &default_hton && hton->create) ?
+ hton->create(table) : NULL;
+}
+
+
+handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
+{
+ struct plugin_find_dbtype_st info;
+
+ switch (db_type)
{
- if (database_type == (*types)->db_type)
- return ((*types)->state == SHOW_OPTION_YES) ? TRUE : FALSE;
+ case DB_TYPE_DEFAULT:
+ return (thd->variables.table_type != NULL) ?
+ thd->variables.table_type :
+ (global_system_variables.table_type != NULL ?
+ global_system_variables.table_type : &myisam_hton);
+ case DB_TYPE_UNKNOWN:
+ return NULL;
+ default:
+ info.db_type= db_type;
+ if (!plugin_foreach(NULL, plugin_find_dbtype,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+ return NULL;
+
+ return info.hton;
}
- return FALSE;
}
/* Use other database handler if databasehandler is not compiled in */
-enum db_type ha_checktype(THD *thd, enum db_type database_type,
+handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
bool no_substitute, bool report_error)
{
- if (ha_storage_engine_is_enabled(database_type))
- return database_type;
+ handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
+ if (ha_storage_engine_is_enabled(hton))
+ return hton;
+
if (no_substitute)
{
if (report_error)
@@ -166,34 +219,28 @@ enum db_type ha_checktype(THD *thd, enum db_type database_type,
const char *engine_name= ha_get_storage_engine(database_type);
my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
}
- return DB_TYPE_UNKNOWN;
+ return NULL;
}
switch (database_type) {
#ifndef NO_HASH
case DB_TYPE_HASH:
- return (database_type);
+ return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
#endif
case DB_TYPE_MRG_ISAM:
- return (DB_TYPE_MRG_MYISAM);
+ return ha_resolve_by_legacy_type(thd, DB_TYPE_MRG_MYISAM);
default:
break;
}
-
- return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
- (enum db_type) thd->variables.table_type :
- ((enum db_type) global_system_variables.table_type !=
- DB_TYPE_UNKNOWN ?
- (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM)
- );
+
+ return ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT);
} /* ha_checktype */
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
- enum db_type db_type)
+ handlerton *db_type)
{
handler *file= NULL;
- handlerton **types;
/*
handlers are allocated with new in the handlerton create() function
we need to set the thd mem_root for these to be allocated correctly
@@ -201,20 +248,15 @@ handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
THD *thd= current_thd;
MEM_ROOT *thd_save_mem_root= thd->mem_root;
thd->mem_root= alloc;
- for (types= sys_table_types; *types; types++)
- {
- if (db_type == (*types)->db_type && (*types)->create)
- {
- file= ((*types)->state == SHOW_OPTION_YES) ?
- (*types)->create(share) : NULL;
- break;
- }
- }
+
+ if (db_type != NULL && db_type->state == SHOW_OPTION_YES && db_type->create)
+ file= db_type->create(share);
+
thd->mem_root= thd_save_mem_root;
if (!file)
{
- enum db_type def=(enum db_type) current_thd->variables.table_type;
+ handlerton *def= current_thd->variables.table_type;
/* Try first with 'default table type' */
if (db_type != def)
return get_new_handler(share, alloc, def);
@@ -341,16 +383,72 @@ static int ha_finish_errors(void)
}
-static inline void ha_was_inited_ok(handlerton **ht)
+static void ha_was_inited_ok(handlerton *ht)
{
- uint tmp= (*ht)->savepoint_offset;
- (*ht)->savepoint_offset= savepoint_alloc_size;
+ uint tmp= ht->savepoint_offset;
+ ht->savepoint_offset= savepoint_alloc_size;
savepoint_alloc_size+= tmp;
- (*ht)->slot= total_ha++;
- if ((*ht)->prepare)
+ ht->slot= total_ha++;
+ if (ht->prepare)
total_ha_2pc++;
}
+
+int ha_initialize_handlerton(handlerton *hton)
+{
+ DBUG_ENTER("ha_initialize_handlerton");
+
+ if (hton == NULL)
+ DBUG_RETURN(1);
+
+ /* check major version */
+ if ((hton->interface_version>>24) != (MYSQL_HANDLERTON_INTERFACE_VERSION>>24))
+ {
+ sql_print_error("handlerton major version incompatible");
+ DBUG_PRINT("warning", ("handlerton major version incompatible"));
+ DBUG_RETURN(1);
+ }
+
+ /* check minor version */
+ if ((hton->interface_version>>16)&0xff <
+ (MYSQL_HANDLERTON_INTERFACE_VERSION>>16)&0xff)
+ {
+ sql_print_error("handlerton minor version incompatible");
+ DBUG_PRINT("warning", ("handlerton minor version incompatible"));
+ DBUG_RETURN(1);
+ }
+
+ switch (hton->state)
+ {
+ case SHOW_OPTION_NO:
+ break;
+ case SHOW_OPTION_YES:
+ if (!hton->init || !hton->init())
+ {
+ ha_was_inited_ok(hton);
+ break;
+ }
+ /* fall through */
+ default:
+ hton->state= SHOW_OPTION_DISABLED;
+ break;
+ }
+ DBUG_RETURN(0);
+}
+
+
+static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin,
+ void *unused2)
+{
+ if (plugin->state == PLUGIN_IS_UNINITIALIZED)
+ {
+ ha_initialize_handlerton((handlerton *) plugin->plugin->info);
+ plugin->state= PLUGIN_IS_READY;
+ }
+ return FALSE;
+}
+
+
int ha_init()
{
int error= 0;
@@ -361,16 +459,8 @@ int ha_init()
if (ha_init_errors())
return 1;
- /*
- We now initialize everything here.
- */
- for (types= sys_table_types; *types; types++)
- {
- if (!(*types)->init || !(*types)->init())
- ha_was_inited_ok(types);
- else
- (*types)->state= SHOW_OPTION_DISABLED;
- }
+ if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0))
+ return 1;
DBUG_ASSERT(total_ha < MAX_HA);
/*
@@ -383,43 +473,97 @@ int ha_init()
return error;
}
+
+int ha_register_builtin_plugins()
+{
+ handlerton **hton;
+ uint size= 0;
+ struct st_mysql_plugin *plugin;
+ DBUG_ENTER("ha_register_builtin_plugins");
+
+ for (hton= sys_table_types; *hton; hton++)
+ size+= sizeof(struct st_mysql_plugin);
+
+ if (!(plugin= (struct st_mysql_plugin *)
+ my_once_alloc(size, MYF(MY_WME | MY_ZEROFILL))))
+ DBUG_RETURN(1);
+
+ for (hton= sys_table_types; *hton; hton++, plugin++)
+ {
+ plugin->type= MYSQL_STORAGE_ENGINE_PLUGIN;
+ plugin->info= *hton;
+ plugin->version= 0;
+ plugin->name= (*hton)->name;
+ plugin->author= NULL;
+ plugin->descr= (*hton)->comment;
+
+ if (plugin_register_builtin(plugin))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+
+
/* close, flush or restart databases */
/* Ignore this for other databases than ours */
-int ha_panic(enum ha_panic_function flag)
+static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin,
+ void *arg)
{
- int error=0;
- handlerton **types;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES && hton->panic)
+ ((int*)arg)[0]|= hton->panic((enum ha_panic_function)((int*)arg)[1]);
+ return FALSE;
+}
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES && (*types)->panic)
- error|= (*types)->panic(flag);
- }
- if (ha_finish_errors())
- error= 1;
- return error;
+
+int ha_panic(enum ha_panic_function flag)
+{
+ int error[2];
+
+ error[0]= 0; error[1]= (int)flag;
+ plugin_foreach(NULL, panic_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, error);
+
+ if (flag == HA_PANIC_CLOSE && ha_finish_errors())
+ error[0]= 1;
+ return error[0];
} /* ha_panic */
+static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin,
+ void *path)
+{
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES && hton->drop_database)
+ hton->drop_database((char *)path);
+ return FALSE;
+}
+
+
void ha_drop_database(char* path)
{
- handlerton **types;
+ plugin_foreach(NULL, dropdb_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, path);
+}
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES && (*types)->drop_database)
- (*types)->drop_database(path);
- }
+
+static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin,
+ void *unused)
+{
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ /* there's no need to rollback here as all transactions must
+ be rolled back already */
+ if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
+ thd->ha_data[hton->slot])
+ hton->close_connection(thd);
+ return FALSE;
}
+
/* don't bother to rollback here, it's done already */
void ha_close_connection(THD* thd)
{
- handlerton **types;
- for (types= sys_table_types; *types; types++)
- /* XXX Maybe do a rollback if close_connection == NULL ? */
- if (thd->ha_data[(*types)->slot] && (*types)->close_connection)
- (*types)->close_connection(thd);
+ plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
}
/* ========================================================================
@@ -729,21 +873,46 @@ int ha_autocommit_or_rollback(THD *thd, int error)
}
-int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+struct xahton_st {
+ XID *xid;
+ int result;
+};
+
+static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin,
+ void *arg)
{
- handlerton **types;
- int res= 1;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES && hton->recover)
+ {
+ hton->commit_by_xid(((struct xahton_st *)arg)->xid);
+ ((struct xahton_st *)arg)->result= 0;
+ }
+ return FALSE;
+}
- for (types= sys_table_types; *types; types++)
+static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin,
+ void *arg)
+{
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES && hton->recover)
{
- if ((*types)->state == SHOW_OPTION_YES && (*types)->recover)
- {
- if ((*(commit ? (*types)->commit_by_xid :
- (*types)->rollback_by_xid))(xid));
- res= 0;
- }
+ hton->rollback_by_xid(((struct xahton_st *)arg)->xid);
+ ((struct xahton_st *)arg)->result= 0;
}
- return res;
+ return FALSE;
+}
+
+
+int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+{
+ struct xahton_st xaop;
+ xaop.xid= xid;
+ xaop.result= 1;
+
+ plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
+
+ return xaop.result;
}
@@ -819,99 +988,123 @@ static char* xid_to_str(char *buf, XID *xid)
in this case commit_list==0, tc_heuristic_recover == 0
there should be no prepared transactions in this case.
*/
-int ha_recover(HASH *commit_list)
-{
- int len, got, found_foreign_xids=0, found_my_xids=0;
- handlerton **types;
- XID *list=0;
- bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
- DBUG_ENTER("ha_recover");
- /* commit_list and tc_heuristic_recover cannot be set both */
- DBUG_ASSERT(commit_list==0 || tc_heuristic_recover==0);
- /* if either is set, total_ha_2pc must be set too */
- DBUG_ASSERT(dry_run || total_ha_2pc>(ulong)opt_bin_log);
-
- if (total_ha_2pc <= (ulong)opt_bin_log)
- DBUG_RETURN(0);
-
- if (commit_list)
- sql_print_information("Starting crash recovery...");
-
-#ifndef WILL_BE_DELETED_LATER
- /*
- for now, only InnoDB supports 2pc. It means we can always safely
- rollback all pending transactions, without risking inconsistent data
- */
- DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
- tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
- dry_run=FALSE;
-#endif
-
- for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
- {
- list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
- }
- if (!list)
- {
- sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
- DBUG_RETURN(1);
- }
+struct xarecover_st
+{
+ int len, found_foreign_xids, found_my_xids;
+ XID *list;
+ HASH *commit_list;
+ bool dry_run;
+};
- for (types= sys_table_types; *types; types++)
+static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin,
+ void *arg)
+{
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ struct xarecover_st *info= (struct xarecover_st *) arg;
+ int got;
+
+ if (hton->state == SHOW_OPTION_YES && hton->recover)
{
- if ((*types)->state != SHOW_OPTION_YES || !(*types)->recover)
- continue;
- while ((got=(*(*types)->recover)(list, len)) > 0 )
+ while ((got= hton->recover(info->list, info->len)) > 0 )
{
sql_print_information("Found %d prepared transaction(s) in %s",
- got, (*types)->name);
+ got, hton->name);
for (int i=0; i < got; i ++)
{
- my_xid x=list[i].get_my_xid();
+ my_xid x=info->list[i].get_my_xid();
if (!x) // not "mine" - that is generated by external TM
{
#ifndef DBUG_OFF
char buf[XIDDATASIZE*4+6]; // see xid_to_str
- sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
+ sql_print_information("ignore xid %s", xid_to_str(buf, info->list+i));
#endif
- xid_cache_insert(list+i, XA_PREPARED);
- found_foreign_xids++;
+ xid_cache_insert(info->list+i, XA_PREPARED);
+ info->found_foreign_xids++;
continue;
}
- if (dry_run)
+ if (info->dry_run)
{
- found_my_xids++;
+ info->found_my_xids++;
continue;
}
// recovery mode
- if (commit_list ?
- hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
+ if (info->commit_list ?
+ hash_search(info->commit_list, (byte *)&x, sizeof(x)) != 0 :
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
{
#ifndef DBUG_OFF
char buf[XIDDATASIZE*4+6]; // see xid_to_str
- sql_print_information("commit xid %s", xid_to_str(buf, list+i));
+ sql_print_information("commit xid %s", xid_to_str(buf, info->list+i));
#endif
- (*(*types)->commit_by_xid)(list+i);
+ hton->commit_by_xid(info->list+i);
}
else
{
#ifndef DBUG_OFF
char buf[XIDDATASIZE*4+6]; // see xid_to_str
- sql_print_information("rollback xid %s", xid_to_str(buf, list+i));
+ sql_print_information("rollback xid %s",
+ xid_to_str(buf, info->list+i));
#endif
- (*(*types)->rollback_by_xid)(list+i);
+ hton->rollback_by_xid(info->list+i);
}
}
- if (got < len)
+ if (got < info->len)
break;
}
}
- my_free((gptr)list, MYF(0));
- if (found_foreign_xids)
- sql_print_warning("Found %d prepared XA transactions", found_foreign_xids);
- if (dry_run && found_my_xids)
+ return FALSE;
+}
+
+int ha_recover(HASH *commit_list)
+{
+ struct xarecover_st info;
+ DBUG_ENTER("ha_recover");
+ info.found_foreign_xids= info.found_my_xids= 0;
+ info.commit_list= commit_list;
+ info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
+ info.list= NULL;
+
+ /* commit_list and tc_heuristic_recover cannot be set both */
+ DBUG_ASSERT(info.commit_list==0 || tc_heuristic_recover==0);
+ /* if either is set, total_ha_2pc must be set too */
+ DBUG_ASSERT(info.dry_run || total_ha_2pc>(ulong)opt_bin_log);
+
+ if (total_ha_2pc <= (ulong)opt_bin_log)
+ DBUG_RETURN(0);
+
+ if (info.commit_list)
+ sql_print_information("Starting crash recovery...");
+
+#ifndef WILL_BE_DELETED_LATER
+ /*
+ for now, only InnoDB supports 2pc. It means we can always safely
+ rollback all pending transactions, without risking inconsistent data
+ */
+ DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
+ tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
+ info.dry_run=FALSE;
+#endif
+
+ for (info.len= MAX_XID_LIST_SIZE ;
+ info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
+ {
+ info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
+ }
+ if (!info.list)
+ {
+ sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
+ DBUG_RETURN(1);
+ }
+
+ plugin_foreach(NULL, xarecover_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &info);
+
+ my_free((gptr)info.list, MYF(0));
+ if (info.found_foreign_xids)
+ sql_print_warning("Found %d prepared XA transactions",
+ info.found_foreign_xids);
+ if (info.dry_run && info.found_my_xids)
{
sql_print_error("Found %d prepared transactions! It means that mysqld was "
"not shut down properly last time and critical recovery "
@@ -919,10 +1112,10 @@ int ha_recover(HASH *commit_list)
"after a crash. You have to start mysqld with "
"--tc-heuristic-recover switch to commit or rollback "
"pending transactions.",
- found_my_xids, opt_tc_log_file);
+ info.found_my_xids, opt_tc_log_file);
DBUG_RETURN(1);
}
- if (commit_list)
+ if (info.commit_list)
sql_print_information("Crash recovery finished.");
DBUG_RETURN(0);
}
@@ -995,32 +1188,17 @@ bool mysql_xa_recover(THD *thd)
int ha_release_temporary_latches(THD *thd)
{
- handlerton **types;
-
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES &&
- (*types)->release_temporary_latches)
- (*types)->release_temporary_latches(thd);
- }
- return 0;
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+ innobase_release_temporary_latches(thd);
+#endif
}
-/*
- Export statistics for different engines. Currently we use it only for
- InnoDB.
-*/
-
int ha_update_statistics()
{
- handlerton **types;
-
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES && (*types)->update_statistics)
- (*types)->update_statistics();
- }
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+ innodb_export_status();
+#endif
return 0;
}
@@ -1129,20 +1307,25 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
}
+static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin,
+ void *arg)
+{
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES &&
+ hton->start_consistent_snapshot)
+ {
+ hton->start_consistent_snapshot(thd);
+ *((bool *)arg)= false;
+ }
+ return FALSE;
+}
+
int ha_start_consistent_snapshot(THD *thd)
{
bool warn= true;
- handlerton **types;
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES &&
- (*types)->start_consistent_snapshot)
- {
- (*types)->start_consistent_snapshot(thd);
- warn= false; /* hope user is using engine */
- }
- }
+ plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
+
/*
Same idea as when one wants to CREATE TABLE in one engine which does not
exist:
@@ -1155,22 +1338,31 @@ int ha_start_consistent_snapshot(THD *thd)
}
-bool ha_flush_logs(enum db_type db_type)
+static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin,
+ void *arg)
{
- bool result=0;
- handlerton **types;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES && hton->flush_logs && hton->flush_logs())
+ return TRUE;
+ return FALSE;
+}
+
- for (types= sys_table_types; *types; types++)
+bool ha_flush_logs(handlerton *db_type)
+{
+ if (db_type == NULL)
{
- if ((*types)->state == SHOW_OPTION_YES &&
- (db_type == DB_TYPE_DEFAULT || db_type == (*types)->db_type) &&
- (*types)->flush_logs)
- {
- if ((*types)->flush_logs())
- result= 1;
- }
+ if (plugin_foreach(NULL, flush_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, 0))
+ return TRUE;
}
- return result;
+ else
+ {
+ if (db_type->state != SHOW_OPTION_YES ||
+ (db_type->flush_logs && db_type->flush_logs()))
+ return TRUE;
+ }
+ return FALSE;
}
/*
@@ -1178,7 +1370,7 @@ bool ha_flush_logs(enum db_type db_type)
The .frm file will be deleted only if we return 0 or ENOENT
*/
-int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
+int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
const char *db, const char *alias, bool generate_warning)
{
handler *file;
@@ -1193,7 +1385,7 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
dummy_table.s= &dummy_share;
/* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
- if (table_type == DB_TYPE_UNKNOWN ||
+ if (table_type == NULL ||
! (file=get_new_handler(&dummy_share, thd->mem_root, table_type)))
DBUG_RETURN(ENOENT);
@@ -2486,40 +2678,50 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key,
pointer pointer to TYPELIB structure
*/
+static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin,
+ void *arg)
+{
+ List<char> *found_exts= (List<char> *) arg;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ handler *file;
+ if (hton->state == SHOW_OPTION_YES && hton->create &&
+ (file= hton->create((TABLE_SHARE*) 0)))
+ {
+ List_iterator_fast<char> it(*found_exts);
+ const char **ext, *old_ext;
+
+ for (ext= file->bas_ext(); *ext; ext++)
+ {
+ while ((old_ext= it++))
+ {
+ if (!strcmp(old_ext, *ext))
+ break;
+ }
+ if (!old_ext)
+ found_exts->push_back((char *) *ext);
+
+ it.rewind();
+ }
+ delete file;
+ }
+ return FALSE;
+}
+
TYPELIB *ha_known_exts(void)
{
MEM_ROOT *mem_root= current_thd->mem_root;
if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
{
- handlerton **types;
List<char> found_exts;
- List_iterator_fast<char> it(found_exts);
const char **ext, *old_ext;
known_extensions_id= mysys_usage_id;
found_exts.push_back((char*) triggers_file_ext);
found_exts.push_back((char*) trigname_file_ext);
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES)
- {
- handler *file= get_new_handler((TABLE_SHARE*) 0, mem_root,
- (enum db_type) (*types)->db_type);
- for (ext= file->bas_ext(); *ext; ext++)
- {
- while ((old_ext= it++))
- {
- if (!strcmp(old_ext, *ext))
- break;
- }
- if (!old_ext)
- found_exts.push_back((char *) *ext);
-
- it.rewind();
- }
- delete file;
- }
- }
+
+ plugin_foreach(NULL, exts_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
+
ext= (const char **) my_once_alloc(sizeof(char *)*
(found_exts.elements+1),
MYF(MY_WME | MY_FAE));
@@ -2528,6 +2730,7 @@ TYPELIB *ha_known_exts(void)
known_extensions.count= found_exts.elements;
known_extensions.type_names= ext;
+ List_iterator_fast<char> it(found_exts);
while ((old_ext= it++))
*ext++= old_ext;
*ext= 0;
@@ -2535,24 +2738,37 @@ TYPELIB *ha_known_exts(void)
return &known_extensions;
}
-static bool stat_print(THD *thd, const char *type, const char *file,
- const char *status)
+static bool stat_print(THD *thd, const char *type, uint type_len,
+ const char *file, uint file_len,
+ const char *status, uint status_len)
{
Protocol *protocol= thd->protocol;
protocol->prepare_for_resend();
- protocol->store(type, system_charset_info);
- protocol->store(file, system_charset_info);
- protocol->store(status, system_charset_info);
+ protocol->store(type, type_len, system_charset_info);
+ protocol->store(file, file_len, system_charset_info);
+ protocol->store(status, status_len, system_charset_info);
if (protocol->write())
return TRUE;
return FALSE;
}
-bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat)
+
+static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin,
+ void *arg)
+{
+ enum ha_stat_type stat= *(enum ha_stat_type *) arg;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+ if (hton->state == SHOW_OPTION_YES && hton->show_status &&
+ hton->show_status(thd, stat_print, stat))
+ return TRUE;
+ return FALSE;
+}
+
+bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
{
- handlerton **types;
List<Item> field_list;
Protocol *protocol= thd->protocol;
+ bool result;
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
@@ -2562,25 +2778,24 @@ bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
return TRUE;
- for (types= sys_table_types; *types; types++)
+ if (db_type == NULL)
{
- if ((*types)->state == SHOW_OPTION_YES &&
- (db_type == DB_TYPE_DEFAULT || db_type == (*types)->db_type) &&
- (*types)->show_status)
- {
- if ((*types)->show_status(thd, stat_print, stat))
- return TRUE;
- }
- else if (db_type == (*types)->db_type &&
- (*types)->state != SHOW_OPTION_YES)
- {
- if (stat_print(thd, (*types)->name, "", "DISABLED"))
- return TRUE;
- }
+ result= plugin_foreach(thd, showstat_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &stat);
+ }
+ else
+ {
+ if (db_type->state != SHOW_OPTION_YES)
+ result= stat_print(thd, db_type->name, strlen(db_type->name),
+ "", 0, "DISABLED", 8) ? 1 : 0;
+ else
+ result= db_type->show_status &&
+ db_type->show_status(thd, stat_print, stat) ? 1 : 0;
}
- send_eof(thd);
- return FALSE;
+ if (!result)
+ send_eof(thd);
+ return result;
}
@@ -2606,19 +2821,10 @@ bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat)
int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
my_off_t end_offset)
{
- int result= 0;
- handlerton **types;
-
- for (types= sys_table_types; *types; types++)
- {
- if ((*types)->state == SHOW_OPTION_YES &&
- (*types)->repl_report_sent_binlog)
- {
- (*types)->repl_report_sent_binlog(thd,log_file_name,end_offset);
- result= 0;
- }
- }
- return result;
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+ innobase_repl_report_sent_binlog(thd, log_file_name, end_offset);
+#endif
+ return 0;
}
@@ -2643,3 +2849,4 @@ int ha_repl_report_replication_stop(THD *thd)
return 0;
}
#endif /* HAVE_REPLICATION */
+
diff --git a/sql/handler.h b/sql/handler.h
index b4b90cbfaa8..9519ba06390 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -178,7 +178,7 @@
/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
-enum db_type
+enum legacy_db_type
{
DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
@@ -191,7 +191,7 @@ enum db_type
DB_TYPE_BLACKHOLE_DB,
DB_TYPE_PARTITION_DB,
DB_TYPE_BINLOG,
- DB_TYPE_DEFAULT // Must be last
+ DB_TYPE_DEFAULT=127 // Must be last
};
enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
@@ -315,8 +315,9 @@ typedef struct st_table TABLE;
typedef struct st_table_share TABLE_SHARE;
struct st_foreign_key_info;
typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
-typedef bool (stat_print_fn)(THD *thd, const char *type, const char *file,
- const char *status);
+typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
+ const char *file, uint file_len,
+ const char *status, uint status_len);
enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
/*
@@ -333,6 +334,13 @@ enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
typedef struct
{
/*
+ handlerton structure version
+ */
+ const int interface_version;
+#define MYSQL_HANDLERTON_INTERFACE_VERSION 0x00000000
+
+
+ /*
storage engine name as it should be printed to a user
*/
const char *name;
@@ -351,7 +359,7 @@ typedef struct
Historical number used for frm file to determine the correct storage engine.
This is going away and new engines will just use "name" for this.
*/
- enum db_type db_type;
+ enum legacy_db_type db_type;
/*
Method that initizlizes a storage engine
*/
@@ -416,19 +424,17 @@ typedef struct
handler *(*create)(TABLE_SHARE *table);
void (*drop_database)(char* path);
int (*panic)(enum ha_panic_function flag);
- int (*release_temporary_latches)(THD *thd);
- int (*update_statistics)();
int (*start_consistent_snapshot)(THD *thd);
bool (*flush_logs)();
bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat);
- int (*repl_report_sent_binlog)(THD *thd, char *log_file_name,
- my_off_t end_offset);
uint32 flags; /* global handler flags */
} handlerton;
+extern const handlerton default_hton;
+
struct show_table_alias_st {
const char *alias;
- const char *type;
+ enum legacy_db_type type;
};
/* Possible flags of a handlerton */
@@ -496,7 +502,7 @@ public:
char* part_comment;
char* data_file_name;
char* index_file_name;
- enum db_type engine_type;
+ handlerton *engine_type;
enum partition_state part_state;
uint16 nodegroup_id;
@@ -504,7 +510,7 @@ public:
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
tablespace_name(NULL), range_value(0), part_comment(NULL),
data_file_name(NULL), index_file_name(NULL),
- engine_type(DB_TYPE_UNKNOWN),part_state(PART_NORMAL),
+ engine_type(NULL),part_state(PART_NORMAL),
nodegroup_id(UNDEF_NODEGROUP)
{
subpartitions.empty();
@@ -567,7 +573,7 @@ public:
key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF;
key_map some_fields_in_PF;
- enum db_type default_engine_type;
+ handlerton *default_engine_type;
Item_result part_result_type;
partition_type part_type;
partition_type subpart_type;
@@ -608,7 +614,7 @@ public:
part_info_string(NULL),
part_func_string(NULL), subpart_func_string(NULL),
curr_part_elem(NULL), current_partition(NULL),
- default_engine_type(DB_TYPE_UNKNOWN),
+ default_engine_type(NULL),
part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
part_info_len(0), part_func_len(0), subpart_func_len(0),
@@ -683,7 +689,7 @@ typedef struct st_ha_create_information
ulong raid_chunksize;
ulong used_fields;
SQL_LIST merge_list;
- enum db_type db_type;
+ handlerton *db_type;
enum row_type row_type;
uint null_bits; /* NULL bits at start of record */
uint options; /* OR of HA_CREATE_ options */
@@ -727,7 +733,7 @@ int get_parts_for_update(const byte *old_data, byte *new_data,
uint32 *old_part_id, uint32 *new_part_id);
int get_part_for_delete(const byte *buf, const byte *rec0,
partition_info *part_info, uint32 *part_id);
-bool check_partition_info(partition_info *part_info,enum db_type eng_type,
+bool check_partition_info(partition_info *part_info,handlerton *eng_type,
handler *file, ulonglong max_rows);
bool fix_partition_func(THD *thd, const char *name, TABLE *table);
char *generate_partition_syntax(partition_info *part_info,
@@ -743,7 +749,7 @@ void get_full_part_id_from_key(const TABLE *table, byte *buf,
part_id_range *part_spec);
bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
uint part_info_len, TABLE *table,
- enum db_type default_db_type);
+ handlerton *default_db_type);
#endif
@@ -1413,32 +1419,56 @@ extern ulong total_ha, total_ha_2pc;
#define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
/* lookups */
-enum db_type ha_resolve_by_name(const char *name, uint namelen);
-const char *ha_get_storage_engine(enum db_type db_type);
+handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name);
+handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type);
+const char *ha_get_storage_engine(enum legacy_db_type db_type);
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
- enum db_type db_type);
-enum db_type ha_checktype(THD *thd, enum db_type database_type,
+ handlerton *db_type);
+handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
bool no_substitute, bool report_error);
-bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag);
+
+
+inline enum legacy_db_type ha_legacy_type(const handlerton *db_type)
+{
+ return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
+}
+
+inline const char *ha_resolve_storage_engine_name(const handlerton *db_type)
+{
+ return db_type == NULL ? "UNKNOWN" : db_type->name;
+}
+
+inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
+{
+ return db_type == NULL ? FALSE : test(db_type->flags & flag);
+}
+
+inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
+{
+ return (db_type && db_type->create) ?
+ (db_type->state == SHOW_OPTION_YES) : FALSE;
+}
/* basic stuff */
int ha_init(void);
+int ha_register_builtin_plugins();
+int ha_initialize_handlerton(handlerton *hton);
+
TYPELIB *ha_known_exts(void);
int ha_panic(enum ha_panic_function flag);
int ha_update_statistics();
void ha_close_connection(THD* thd);
-my_bool ha_storage_engine_is_enabled(enum db_type database_type);
-bool ha_flush_logs(enum db_type db_type=DB_TYPE_DEFAULT);
+bool ha_flush_logs(handlerton *db_type);
void ha_drop_database(char* path);
int ha_create_table(THD *thd, const char *path,
const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
bool update_create_info);
-int ha_delete_table(THD *thd, enum db_type db_type, const char *path,
+int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
const char *db, const char *alias, bool generate_warning);
/* statistics and info */
-bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat);
+bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
/* discovery */
int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 03050a99ff1..9425351e682 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -2321,7 +2321,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1;
- if (table->s->db_type == DB_TYPE_HEAP)
+ if (table->s->db_type == &heap_hton)
{
/*
No blobs, otherwise it would have been MyISAM: set up a compare
diff --git a/sql/log.cc b/sql/log.cc
index 1fc7ba1f1fd..d30cf3266f9 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -48,6 +48,7 @@ static int binlog_rollback(THD *thd, bool all);
static int binlog_prepare(THD *thd, bool all);
handlerton binlog_hton = {
+ MYSQL_HANDLERTON_INTERFACE_VERSION,
"binlog",
SHOW_OPTION_YES,
"This is a meta storage engine to represent the binlog in a transaction",
@@ -71,12 +72,9 @@ handlerton binlog_hton = {
NULL, /* Create a new handler */
NULL, /* Drop a database */
NULL, /* Panic call */
- NULL, /* Release temporary latches */
- NULL, /* Update Statistics */
NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */
NULL, /* Show status */
- NULL, /* Replication Report Sent Binlog */
HTON_NOT_USER_SELECTABLE | HTON_HIDDEN
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4b7a1fc00a8..4a7c6e8bbcf 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -602,7 +602,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
bool if_exists, bool drop_temporary,
bool log_query);
-bool quick_rm_table(enum db_type base,const char *db,
+bool quick_rm_table(handlerton *base,const char *db,
const char *table_name);
void close_cached_table(THD *thd, TABLE *table);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
@@ -748,7 +748,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
HA_CREATE_INFO *create_info,
Table_ident *src_table);
-bool mysql_rename_table(enum db_type base,
+bool mysql_rename_table(handlerton *base,
const char *old_db,
const char * old_name,
const char *new_db,
@@ -1001,7 +1001,7 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
-bool rm_temporary_table(enum db_type base, char *path);
+bool rm_temporary_table(handlerton *base, char *path);
void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr);
@@ -1329,6 +1329,10 @@ extern handlerton partition_hton;
extern SHOW_COMP_OPTION have_partition_db;
#endif
+extern handlerton myisam_hton;
+extern handlerton myisammrg_hton;
+extern handlerton heap_hton;
+
extern SHOW_COMP_OPTION have_isam;
extern SHOW_COMP_OPTION have_raid, have_openssl, have_symlink;
extern SHOW_COMP_OPTION have_query_cache;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f344becffde..544fe23e270 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2622,6 +2622,18 @@ static int init_common_variables(const char *conf_file_name, int argc,
strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
+ if (plugin_init())
+ {
+ sql_print_error("Failed to init plugins.");
+ return 1;
+ }
+
+ if (ha_register_builtin_plugins())
+ {
+ sql_print_error("Failed to register built-in storage engines.");
+ return 1;
+ }
+
load_defaults(conf_file_name, groups, &argc, &argv);
defaults_argv=argv;
get_options(argc,argv);
@@ -3105,17 +3117,15 @@ server.");
/*
Check that the default storage engine is actually available.
*/
- if (!ha_storage_engine_is_enabled((enum db_type)
- global_system_variables.table_type))
+ if (!ha_storage_engine_is_enabled(global_system_variables.table_type))
{
if (!opt_bootstrap)
{
sql_print_error("Default storage engine (%s) is not available",
- ha_get_storage_engine((enum db_type)
- global_system_variables.table_type));
+ global_system_variables.table_type->name);
unireg_abort(1);
}
- global_system_variables.table_type= DB_TYPE_MYISAM;
+ global_system_variables.table_type= &myisam_hton;
}
tc_log= (total_ha_2pc > 1 ? (opt_bin_log ?
@@ -3470,7 +3480,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
if (!opt_noacl)
{
- plugin_init();
+ plugin_load();
#ifdef HAVE_DLOPEN
udf_init();
#endif
@@ -6102,6 +6112,7 @@ struct show_var_st status_vars[]= {
{"Com_show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
{"Com_show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
{"Com_show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
+ {"Com_show_plugins", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
{"Com_show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
{"Com_show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
{"Com_show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
@@ -6412,7 +6423,7 @@ static void mysql_init_variables(void)
/* Set default values for some option variables */
- global_system_variables.table_type= DB_TYPE_MYISAM;
+ global_system_variables.table_type= &myisam_hton;
global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
@@ -6805,9 +6816,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case OPT_STORAGE_ENGINE:
{
- if ((enum db_type)((global_system_variables.table_type=
- ha_resolve_by_name(argument, strlen(argument)))) ==
- DB_TYPE_UNKNOWN)
+ LEX_STRING name= { argument, strlen(argument) };
+ if ((global_system_variables.table_type=
+ ha_resolve_by_name(current_thd, &name)) == NULL)
{
fprintf(stderr,"Unknown/unsupported table type: %s\n",argument);
exit(1);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 19dc2265347..735dc82dbed 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -3034,11 +3034,12 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
if (var->value->result_type() == STRING_RESULT)
{
- enum db_type db_type;
+ LEX_STRING name;
+ handlerton *db_type;
if (!(res=var->value->val_str(&str)) ||
- !(var->save_result.ulong_value=
- (ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) ||
- ha_checktype(thd, db_type, 1, 0) != db_type)
+ !(name.str= (char *)res->ptr()) || !(name.length= res->length()) ||
+ !(var->save_result.hton= db_type= ha_resolve_by_name(thd, &name)) ||
+ ha_checktype(thd, ha_legacy_type(db_type), 1, 0) != db_type)
{
value= res ? res->c_ptr() : "NULL";
goto err;
@@ -3056,29 +3057,28 @@ err:
byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
- ulong val;
- val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
- thd->variables.*offset);
- const char *table_type= ha_get_storage_engine((enum db_type)val);
- return (byte *) table_type;
+ handlerton *val;
+ val= (type == OPT_GLOBAL) ? global_system_variables.*offset :
+ thd->variables.*offset;
+ return (byte *) val->name;
}
void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
- global_system_variables.*offset= (ulong) DB_TYPE_MYISAM;
+ global_system_variables.*offset= &myisam_hton;
else
- thd->variables.*offset= (ulong) (global_system_variables.*offset);
+ thd->variables.*offset= global_system_variables.*offset;
}
bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
{
- if (var->type == OPT_GLOBAL)
- global_system_variables.*offset= var->save_result.ulong_value;
- else
- thd->variables.*offset= var->save_result.ulong_value;
+ handlerton **value= &(global_system_variables.*offset);
+ if (var->type != OPT_GLOBAL)
+ value= &(thd->variables.*offset);
+ *value= var->save_result.hton;
return 0;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index 14059f7e9b7..838037b6e20 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -379,9 +379,9 @@ public:
class sys_var_thd_storage_engine :public sys_var_thd
{
protected:
- ulong SV::*offset;
+ handlerton *SV::*offset;
public:
- sys_var_thd_storage_engine(const char *name_arg, ulong SV::*offset_arg)
+ sys_var_thd_storage_engine(const char *name_arg, handlerton *SV::*offset_arg)
:sys_var_thd(name_arg), offset(offset_arg)
{}
bool check(THD *thd, set_var *var);
@@ -398,7 +398,7 @@ SHOW_TYPE type() { return SHOW_CHAR; }
class sys_var_thd_table_type :public sys_var_thd_storage_engine
{
public:
- sys_var_thd_table_type(const char *name_arg, ulong SV::*offset_arg)
+ sys_var_thd_table_type(const char *name_arg, handlerton *SV::*offset_arg)
:sys_var_thd_storage_engine(name_arg, offset_arg)
{}
void warn_deprecated(THD *thd);
@@ -812,6 +812,7 @@ public:
CHARSET_INFO *charset;
ulong ulong_value;
ulonglong ulonglong_value;
+ handlerton *hton;
DATE_TIME_FORMAT *date_time_format;
Time_zone *time_zone;
} save_result;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 4ced556fd11..5baf7cbd80b 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1433,7 +1433,7 @@ void close_temporary_table(THD *thd, TABLE *table,
void close_temporary(TABLE *table, bool free_share, bool delete_table)
{
- db_type table_type= table->s->db_type;
+ handlerton *table_type= table->s->db_type;
DBUG_ENTER("close_temporary");
free_io_cache(table);
@@ -1802,7 +1802,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
*/
{
char path[FN_REFLEN];
- db_type not_used;
+ enum legacy_db_type not_used;
strxnmov(path, FN_REFLEN-1, mysql_data_home, "/", table_list->db, "/",
table_list->table_name, reg_ext, NullS);
(void) unpack_filename(path, path);
@@ -3278,7 +3278,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
}
-bool rm_temporary_table(enum db_type base, char *path)
+bool rm_temporary_table(handlerton *base, char *path)
{
bool error=0;
handler *file;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 0f45b348d11..9a8e1d26ebd 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -2232,7 +2232,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
tables_used->engine_data))
DBUG_RETURN(0);
- if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
+ if (tables_used->table->s->db_type == &myisammrg_hton)
{
ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
@@ -2860,7 +2860,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used,
"other non-cacheable table(s)"));
DBUG_RETURN(0);
}
- if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
+ if (tables_used->table->s->db_type == &myisammrg_hton)
{
ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 3ac95bc1ad8..84670e97b19 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -527,7 +527,7 @@ struct system_variables
ulong read_rnd_buff_size;
ulong div_precincrement;
ulong sortbuff_size;
- ulong table_type;
+ handlerton *table_type;
ulong tmp_table_size;
ulong tx_isolation;
ulong completion_type;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index d5543ac4e06..c58aa9d9e4f 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -822,7 +822,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
/* If it is a temporary table, close and regenerate it */
if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
{
- db_type table_type= table->s->db_type;
+ handlerton *table_type= table->s->db_type;
TABLE_SHARE *share= table->s;
if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
goto trunc_by_del;
@@ -852,7 +852,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!dont_send_ok)
{
- db_type table_type;
+ enum legacy_db_type table_type;
mysql_frm_type(thd, path, &table_type);
if (table_type == DB_TYPE_UNKNOWN)
{
@@ -860,7 +860,8 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
table_list->db, table_list->table_name);
DBUG_RETURN(TRUE);
}
- if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE)
+ if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
+ HTON_CAN_RECREATE)
|| thd->lex->sphead)
goto trunc_by_del;
if (lock_and_wait_for_table_name(thd, table_list))
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 85c8fad40d4..d23ad54b3f1 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2585,7 +2585,7 @@ void select_create::abort()
if (table)
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
- enum db_type table_type=table->s->db_type;
+ handlerton *table_type=table->s->db_type;
if (!table->s->tmp_table)
{
ulong version= table->s->version;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d7ad28a95f5..f2618dd8bce 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -93,7 +93,7 @@ enum enum_sql_command {
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
- SQLCOM_SHOW_AUTHORS,
+ SQLCOM_SHOW_AUTHORS, SQLCOM_SHOW_PLUGINS,
/* This should be the last !!! */
SQLCOM_END
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2e2a6f4d1b1..8dbce3cb78e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6788,7 +6788,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
rotate_relay_log(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
#endif
- if (ha_flush_logs())
+ if (ha_flush_logs(NULL))
result=1;
if (flush_error_log())
result=1;
@@ -7104,7 +7104,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
@@ -7120,7 +7120,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
alter_info->clear();
alter_info->flags= ALTER_DROP_INDEX;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index dd4f2d9246a..cc2eb468662 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -599,7 +599,7 @@ static bool set_up_default_partitions(partition_info *part_info,
partition_element *part_elem= new partition_element();
if (likely(part_elem != 0))
{
- part_elem->engine_type= DB_TYPE_UNKNOWN;
+ part_elem->engine_type= NULL;
part_elem->partition_name= default_name;
default_name+=MAX_PART_NAME_SIZE;
part_info->partitions.push_back(part_elem);
@@ -671,7 +671,7 @@ static bool set_up_default_subpartitions(partition_info *part_info,
partition_element *subpart_elem= new partition_element();
if (likely(subpart_elem != 0))
{
- subpart_elem->engine_type= DB_TYPE_UNKNOWN;
+ subpart_elem->engine_type= NULL;
subpart_elem->partition_name= name_ptr;
name_ptr+= MAX_PART_NAME_SIZE;
part_elem->subpartitions.push_back(subpart_elem);
@@ -731,7 +731,7 @@ bool set_up_defaults_for_partitioning(partition_info *part_info,
FALSE Ok, no mixed engines
*/
-static bool check_engine_mix(u_char *engine_array, uint no_parts)
+static bool check_engine_mix(handlerton **engine_array, uint no_parts)
{
/*
Current check verifies only that all handlers are the same.
@@ -772,10 +772,10 @@ static bool check_engine_mix(u_char *engine_array, uint no_parts)
This code is used early in the CREATE TABLE and ALTER TABLE process.
*/
-bool check_partition_info(partition_info *part_info,enum db_type eng_type,
+bool check_partition_info(partition_info *part_info,handlerton *eng_type,
handler *file, ulonglong max_rows)
{
- u_char *engine_array= NULL;
+ handlerton **engine_array= NULL;
uint part_count= 0, i, no_parts, tot_partitions;
bool result= TRUE;
List_iterator<partition_element> part_it(part_info->partitions);
@@ -803,7 +803,8 @@ bool check_partition_info(partition_info *part_info,enum db_type eng_type,
my_error(ER_SAME_NAME_PARTITION, MYF(0));
goto end;
}
- engine_array= (u_char*)my_malloc(tot_partitions, MYF(MY_WME));
+ engine_array= (handlerton**)my_malloc(tot_partitions * sizeof(handlerton *),
+ MYF(MY_WME));
if (unlikely(!engine_array))
goto end;
i= 0;
@@ -813,10 +814,10 @@ bool check_partition_info(partition_info *part_info,enum db_type eng_type,
partition_element *part_elem= part_it++;
if (!is_sub_partitioned(part_info))
{
- if (part_elem->engine_type == DB_TYPE_UNKNOWN)
+ if (part_elem->engine_type == NULL)
part_elem->engine_type= eng_type;
- DBUG_PRINT("info", ("engine = %u",(uint)part_elem->engine_type));
- engine_array[part_count++]= (u_char)part_elem->engine_type;
+ DBUG_PRINT("info", ("engine = %s", part_elem->engine_type->name));
+ engine_array[part_count++]= part_elem->engine_type;
}
else
{
@@ -825,10 +826,10 @@ bool check_partition_info(partition_info *part_info,enum db_type eng_type,
do
{
part_elem= sub_it++;
- if (part_elem->engine_type == DB_TYPE_UNKNOWN)
+ if (part_elem->engine_type == NULL)
part_elem->engine_type= eng_type;
- DBUG_PRINT("info", ("engine = %u",(uint)part_elem->engine_type));
- engine_array[part_count++]= (u_char)part_elem->engine_type;
+ DBUG_PRINT("info", ("engine = %s", part_elem->engine_type->name));
+ engine_array[part_count++]= part_elem->engine_type;
} while (++j < no_subparts);
}
} while (++i < part_info->no_parts);
@@ -1895,9 +1896,9 @@ static int add_keyword_int(File fptr, const char *keyword, longlong num)
return err + add_space(fptr);
}
-static int add_engine(File fptr, enum db_type engine_type)
+static int add_engine(File fptr, handlerton *engine_type)
{
- const char *engine_str= ha_get_storage_engine(engine_type);
+ const char *engine_str= engine_type->name;
int err= add_string(fptr, "ENGINE = ");
return err + add_string(fptr, engine_str);
return err;
@@ -3092,7 +3093,7 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
uint part_info_len, TABLE* table,
- enum db_type default_db_type)
+ handlerton *default_db_type)
{
Item *thd_free_list= thd->free_list;
bool result= TRUE;
@@ -3129,7 +3130,7 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
part_info= lex.part_info;
table->part_info= part_info;
table->file->set_part_info(part_info);
- if (part_info->default_engine_type == DB_TYPE_UNKNOWN)
+ if (part_info->default_engine_type == NULL)
part_info->default_engine_type= default_db_type;
else
{
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 7e78b58e6cf..591289f6ee1 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -33,7 +33,6 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
static rw_lock_t THR_LOCK_plugin;
static bool initialized= 0;
-
static struct st_plugin_dl *plugin_dl_find(LEX_STRING *dl)
{
uint i;
@@ -348,6 +347,43 @@ void plugin_unlock(struct st_plugin_int *plugin)
}
+static int plugin_initialize(struct st_plugin_int *plugin)
+{
+ DBUG_ENTER("plugin_initialize");
+
+ if (plugin->plugin->init)
+ {
+ if (plugin->plugin->init())
+ {
+ sql_print_error("Plugin '%s' init function returned error.",
+ plugin->name.str);
+ DBUG_PRINT("warning", ("Plugin '%s' init function returned error.",
+ plugin->name.str))
+ goto err;
+ }
+ }
+
+ switch (plugin->plugin->type)
+ {
+ case MYSQL_STORAGE_ENGINE_PLUGIN:
+ if (ha_initialize_handlerton((handlerton*) plugin->plugin->info))
+ {
+ sql_print_error("Plugin '%s' handlerton init returned error.",
+ plugin->name.str);
+ DBUG_PRINT("warning", ("Plugin '%s' handlerton init returned error.",
+ plugin->name.str))
+ goto err;
+ }
+ break;
+ default:
+ break;
+ }
+
+ DBUG_RETURN(0);
+err:
+ DBUG_RETURN(1);
+}
+
static void plugin_call_initializer(void)
{
uint i;
@@ -356,20 +392,13 @@ static void plugin_call_initializer(void)
{
struct st_plugin_int *tmp= dynamic_element(&plugin_array, i,
struct st_plugin_int *);
- if (tmp->state == PLUGIN_IS_UNINITIALIZED && tmp->plugin->init)
+ if (tmp->state == PLUGIN_IS_UNINITIALIZED)
{
- DBUG_PRINT("info", ("Initializing plugin: '%s'", tmp->name.str));
- if (tmp->plugin->init())
- {
- sql_print_error("Plugin '%s' init function returned error.",
- tmp->name.str);
- DBUG_PRINT("warning", ("Plugin '%s' init function returned error.",
- tmp->name.str))
+ if (plugin_initialize(tmp))
plugin_del(&tmp->name);
- }
+ else
+ tmp->state= PLUGIN_IS_READY;
}
- if (tmp->state == PLUGIN_IS_UNINITIALIZED)
- tmp->state= PLUGIN_IS_READY;
}
DBUG_VOID_RETURN;
}
@@ -410,42 +439,84 @@ static byte *get_hash_key(const byte *buff, uint *length,
}
-void plugin_init(void)
+int plugin_init(void)
+{
+ int i;
+ DBUG_ENTER("plugin_init");
+
+ if (initialized)
+ DBUG_RETURN(0);
+
+ my_rwlock_init(&THR_LOCK_plugin, NULL);
+
+ if (my_init_dynamic_array(&plugin_dl_array,
+ sizeof(struct st_plugin_dl),16,16) ||
+ my_init_dynamic_array(&plugin_array,
+ sizeof(struct st_plugin_int),16,16))
+ goto err;
+
+ for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+ {
+ if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
+ get_hash_key, NULL, 0))
+ goto err;
+ }
+
+ initialized= 1;
+
+ DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(1);
+}
+
+
+my_bool plugin_register_builtin(struct st_mysql_plugin *plugin)
+{
+ struct st_plugin_int tmp;
+ DBUG_ENTER("plugin_register_builtin");
+
+ tmp.plugin= plugin;
+ tmp.name.str= (char *)plugin->name;
+ tmp.name.length= strlen(plugin->name);
+ tmp.state= PLUGIN_IS_UNINITIALIZED;
+
+ /* Cannot be unloaded */
+ tmp.ref_count= 1;
+ tmp.plugin_dl= 0;
+
+ if (insert_dynamic(&plugin_array, (gptr)&tmp))
+ DBUG_RETURN(1);
+
+ if (my_hash_insert(&plugin_hash[plugin->type],
+ (byte*)dynamic_element(&plugin_array,
+ plugin_array.elements - 1,
+ struct st_plugin_int *)))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+
+void plugin_load(void)
{
TABLE_LIST tables;
TABLE *table;
READ_RECORD read_record_info;
int error, i;
MEM_ROOT mem;
- DBUG_ENTER("plugin_init");
- if (initialized)
- DBUG_VOID_RETURN;
- my_rwlock_init(&THR_LOCK_plugin, NULL);
- THD *new_thd = new THD;
- if (!new_thd ||
- my_init_dynamic_array(&plugin_dl_array,sizeof(struct st_plugin_dl),16,16) ||
- my_init_dynamic_array(&plugin_array,sizeof(struct st_plugin_int),16,16))
+ THD *new_thd;
+ DBUG_ENTER("plugin_load");
+
+ DBUG_ASSERT(initialized);
+
+ if (!(new_thd= new THD))
{
sql_print_error("Can't allocate memory for plugin structures");
delete new_thd;
- delete_dynamic(&plugin_dl_array);
- delete_dynamic(&plugin_array);
DBUG_VOID_RETURN;
}
- for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
- {
- if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
- get_hash_key, NULL, 0))
- {
- sql_print_error("Can't allocate memory for plugin structures");
- delete new_thd;
- delete_dynamic(&plugin_dl_array);
- delete_dynamic(&plugin_array);
- DBUG_VOID_RETURN;
- }
- }
init_sql_alloc(&mem, 1024, 0);
- initialized= 1;
new_thd->thread_stack= (char*) &tables;
new_thd->store_globals();
new_thd->db= my_strdup("mysql", MYF(0));
@@ -458,10 +529,6 @@ void plugin_init(void)
{
DBUG_PRINT("error",("Can't open plugin table"));
sql_print_error("Can't open the mysql.plugin table. Please run the mysql_install_db script to create it.");
- delete_dynamic(&plugin_dl_array);
- delete_dynamic(&plugin_array);
- for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
- hash_free(&plugin_hash[i]);
goto end;
}
table= tables.table;
@@ -530,27 +597,31 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl)
int error;
struct st_plugin_int *tmp;
DBUG_ENTER("mysql_install_plugin");
+
bzero(&tables, sizeof(tables));
tables.db= (char *)"mysql";
tables.table_name= tables.alias= (char *)"plugin";
if (check_table_access(thd, INSERT_ACL, &tables, 0))
DBUG_RETURN(TRUE);
+
+ /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
+ if (! (table = open_ltable(thd, &tables, TL_WRITE)))
+ DBUG_RETURN(TRUE);
+
rw_wrlock(&THR_LOCK_plugin);
if (plugin_add(name, dl, REPORT_TO_USER))
goto err;
tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
- if (tmp->plugin->init)
+
+ if (plugin_initialize(tmp))
{
- if (tmp->plugin->init())
- {
- my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
- "Plugin initialization function failed.");
- goto err;
- }
- tmp->state= PLUGIN_IS_READY;
+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
+ "Plugin initialization function failed.");
+ goto err;
}
- if (! (table = open_ltable(thd, &tables, TL_WRITE)))
- goto deinit;
+
+ tmp->state= PLUGIN_IS_READY;
+
restore_record(table, s->default_values);
table->field[0]->store(name->str, name->length, system_charset_info);
table->field[1]->store(dl->str, dl->length, files_charset_info);
@@ -560,6 +631,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl)
table->file->print_error(error, MYF(0));
goto deinit;
}
+
rw_unlock(&THR_LOCK_plugin);
DBUG_RETURN(FALSE);
deinit:
@@ -578,12 +650,29 @@ my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name)
TABLE_LIST tables;
struct st_plugin_int *plugin;
DBUG_ENTER("mysql_uninstall_plugin");
+
+ bzero(&tables, sizeof(tables));
+ tables.db= (char *)"mysql";
+ tables.table_name= tables.alias= (char *)"plugin";
+
+ /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
+ if (! (table= open_ltable(thd, &tables, TL_WRITE)))
+ DBUG_RETURN(TRUE);
+
rw_wrlock(&THR_LOCK_plugin);
- if (! (plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+ if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
goto err;
}
+ if (!plugin->plugin_dl)
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Built-in plugins cannot be deleted,.");
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
+ goto err;
+ }
+
if (plugin->ref_count)
{
plugin->state= PLUGIN_IS_DELETED;
@@ -596,11 +685,7 @@ my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name)
plugin->plugin->deinit();
plugin_del(name);
}
- bzero(&tables, sizeof(tables));
- tables.db= (char *)"mysql";
- tables.table_name= tables.alias= (char *)"plugin";
- if (! (table= open_ltable(thd, &tables, TL_WRITE)))
- goto err;
+
table->field[0]->store(name->str, name->length, system_charset_info);
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (! table->file->index_read_idx(table->record[0], 0,
@@ -621,3 +706,44 @@ err:
rw_unlock(&THR_LOCK_plugin);
DBUG_RETURN(TRUE);
}
+
+
+my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
+ int type, void *arg)
+{
+ uint idx;
+ struct st_plugin_int *plugin;
+ DBUG_ENTER("mysql_uninstall_plugin");
+ rw_rdlock(&THR_LOCK_plugin);
+
+ if (type == MYSQL_ANY_PLUGIN)
+ {
+ for (idx= 0; idx < plugin_array.elements; idx++)
+ {
+ plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
+
+ /* FREED records may have garbage pointers */
+ if ((plugin->state != PLUGIN_IS_FREED) &&
+ func(thd, plugin, arg))
+ goto err;
+ }
+ }
+ else
+ {
+ HASH *hash= &plugin_hash[type];
+ for (idx= 0; idx < hash->records; idx++)
+ {
+ plugin= (struct st_plugin_int *) hash_element(hash, idx);
+ if ((plugin->state != PLUGIN_IS_FREED) &&
+ (plugin->state != PLUGIN_IS_DELETED) &&
+ func(thd, plugin, arg))
+ goto err;
+ }
+ }
+
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(FALSE);
+err:
+ rw_unlock(&THR_LOCK_plugin);
+ DBUG_RETURN(TRUE);
+}
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 8fb186b62de..24ba02367f5 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -53,11 +53,20 @@ struct st_plugin_int
extern char *opt_plugin_dir_ptr;
extern char opt_plugin_dir[FN_REFLEN];
-extern void plugin_init(void);
+extern int plugin_init(void);
+extern void plugin_load(void);
extern void plugin_free(void);
extern my_bool plugin_is_ready(LEX_STRING *name, int type);
extern st_plugin_int *plugin_lock(LEX_STRING *name, int type);
extern void plugin_unlock(struct st_plugin_int *plugin);
extern my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl);
extern my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name);
+
+extern my_bool plugin_register_builtin(struct st_mysql_plugin *plugin);
+
+typedef my_bool (plugin_foreach_func)(THD *thd,
+ st_plugin_int *plugin,
+ void *arg);
+extern my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
+ int type, void *arg);
#endif
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 80fcb973028..2c8c732fe86 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -134,7 +134,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
{
TABLE_LIST *ren_table,*new_table;
frm_type_enum frm_type;
- db_type table_type;
+ enum legacy_db_type table_type;
DBUG_ENTER("rename_tables");
@@ -176,7 +176,8 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
if (table_type == DB_TYPE_UNKNOWN)
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
else
- rc= mysql_rename_table(table_type, ren_table->db, old_alias,
+ rc= mysql_rename_table(ha_resolve_by_legacy_type(thd, table_type),
+ ren_table->db, old_alias,
new_table->db, new_alias);
break;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c6f0ca03538..b221706d1f8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8589,7 +8589,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM))
{
table->file= get_new_handler(share, &table->mem_root,
- share->db_type= DB_TYPE_MYISAM);
+ share->db_type= &myisam_hton);
if (group &&
(param->group_parts > table->file->max_key_parts() ||
param->group_length > table->file->max_key_length()))
@@ -8598,7 +8598,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
else
{
table->file= get_new_handler(share, &table->mem_root,
- share->db_type= DB_TYPE_HEAP);
+ share->db_type= &heap_hton);
}
if (!table->file)
goto err;
@@ -8728,7 +8728,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit
share->max_rows= ~(ha_rows) 0;
else
- share->max_rows= (((share->db_type == DB_TYPE_HEAP) ?
+ share->max_rows= (((share->db_type == &heap_hton) ?
min(thd->variables.tmp_table_size,
thd->variables.max_heap_table_size) :
thd->variables.tmp_table_size)/ share->reclength);
@@ -8868,7 +8868,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (thd->is_fatal_error) // If end of memory
goto err; /* purecov: inspected */
share->db_record_offset= 1;
- if (share->db_type == DB_TYPE_MYISAM)
+ if (share->db_type == &myisam_hton)
{
if (create_myisam_tmp_table(table,param,select_options))
goto err;
@@ -9175,7 +9175,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
int write_err;
DBUG_ENTER("create_myisam_from_heap");
- if (table->s->db_type != DB_TYPE_HEAP || error != HA_ERR_RECORD_FILE_FULL)
+ if (table->s->db_type != &heap_hton ||
+ error != HA_ERR_RECORD_FILE_FULL)
{
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
@@ -9183,9 +9184,9 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
new_table= *table;
share= *table->s;
new_table.s= &share;
- new_table.s->db_type= DB_TYPE_MYISAM;
+ new_table.s->db_type= &myisam_hton;
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
- DB_TYPE_MYISAM)))
+ &myisam_hton)))
DBUG_RETURN(1); // End of memory
save_proc_info=thd->proc_info;
@@ -11615,7 +11616,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
free_io_cache(entry); // Safety
entry->file->info(HA_STATUS_VARIABLE);
- if (entry->s->db_type == DB_TYPE_HEAP ||
+ if (entry->s->db_type == &heap_hton ||
(!entry->s->blob_fields &&
((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records <
thd->variables.sortbuff_size)))
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index eaf10a3b074..a26892654b7 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -48,6 +48,32 @@ static bool schema_table_store_record(THD *thd, TABLE *table);
** List all table types supported
***************************************************************************/
+static my_bool show_handlerton(THD *thd, st_plugin_int *plugin,
+ void *arg)
+{
+ handlerton *default_type= (handlerton *) arg;
+ Protocol *protocol= thd->protocol;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
+
+ if (!(hton->flags & HTON_HIDDEN))
+ {
+ protocol->prepare_for_resend();
+ protocol->store(hton->name, system_charset_info);
+ const char *option_name= show_comp_option_name[(int) hton->state];
+
+ if (hton->state == SHOW_OPTION_YES && default_type == hton)
+ option_name= "DEFAULT";
+ protocol->store(option_name, system_charset_info);
+ protocol->store(hton->comment, system_charset_info);
+ protocol->store(hton->commit ? "YES" : "NO", system_charset_info);
+ protocol->store(hton->prepare ? "YES" : "NO", system_charset_info);
+ protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info);
+
+ return protocol->write() ? 1 : 0;
+ }
+ return 0;
+}
+
bool mysqld_show_storage_engines(THD *thd)
{
List<Item> field_list;
@@ -65,34 +91,126 @@ bool mysqld_show_storage_engines(THD *thd)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- const char *default_type_name=
- ha_get_storage_engine((enum db_type)thd->variables.table_type);
+ if (plugin_foreach(thd, show_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type))
+ DBUG_RETURN(TRUE);
- handlerton **types;
- for (types= sys_table_types; *types; types++)
- {
- if (!((*types)->flags & HTON_HIDDEN))
- {
- protocol->prepare_for_resend();
- protocol->store((*types)->name, system_charset_info);
- const char *option_name= show_comp_option_name[(int) (*types)->state];
-
- if ((*types)->state == SHOW_OPTION_YES &&
- !my_strcasecmp(system_charset_info, default_type_name, (*types)->name))
- option_name= "DEFAULT";
- protocol->store(option_name, system_charset_info);
- protocol->store((*types)->comment, system_charset_info);
- protocol->store((*types)->commit ? "YES" : "NO", system_charset_info);
- protocol->store((*types)->prepare ? "YES" : "NO", system_charset_info);
- protocol->store((*types)->savepoint_set ? "YES" : "NO", system_charset_info);
- if (protocol->write())
- DBUG_RETURN(TRUE);
- }
- }
send_eof(thd);
DBUG_RETURN(FALSE);
}
+static int make_version_string(char *buf, int buf_length, uint version)
+{
+ return my_snprintf(buf, buf_length, "%d.%d.%d",
+ (version>>24)&0xff, (version>>16)&0xff,version&0xffff);
+}
+
+static my_bool show_plugins(THD *thd, st_plugin_int *plugin,
+ void *arg)
+{
+ TABLE *table= (TABLE*) arg;
+ struct st_mysql_plugin *plug= plugin->plugin;
+ Protocol *protocol= thd->protocol;
+ CHARSET_INFO *cs= system_charset_info;
+ char version_buf[20];
+
+ restore_record(table, s->default_values);
+
+ table->field[0]->store(plugin->name.str, plugin->name.length, cs);
+
+ switch (plugin->state)
+ {
+ /* case PLUGIN_IS_FREED: does not happen */
+ case PLUGIN_IS_DELETED:
+ table->field[1]->store(STRING_WITH_LEN("DELETED"), cs);
+ break;
+ case PLUGIN_IS_UNINITIALIZED:
+ table->field[1]->store(STRING_WITH_LEN("INACTIVE"), cs);
+ break;
+ case PLUGIN_IS_READY:
+ table->field[1]->store(STRING_WITH_LEN("ACTIVE"), cs);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+
+ switch (plug->type)
+ {
+ case MYSQL_UDF_PLUGIN:
+ table->field[2]->store(STRING_WITH_LEN("UDF"), cs);
+ break;
+ case MYSQL_STORAGE_ENGINE_PLUGIN:
+ table->field[2]->store(STRING_WITH_LEN("STORAGE"), cs);
+ break;
+ case MYSQL_FTPARSER_PLUGIN:
+ table->field[2]->store(STRING_WITH_LEN("FTPARSER"), cs);
+ break;
+ default:
+ table->field[2]->store(STRING_WITH_LEN("UNKNOWN"), cs);
+ break;
+ }
+
+ if (plug->version)
+ {
+ table->field[3]->store(version_buf,
+ make_version_string(version_buf, sizeof(version_buf), plug->version),
+ cs);
+ table->field[3]->set_notnull();
+ }
+ else
+ table->field[3]->set_null();
+
+ if (plug->info)
+ {
+ table->field[4]->store(version_buf,
+ make_version_string(version_buf, sizeof(version_buf),
+ *(uint *)plug->info), cs);
+ table->field[4]->set_notnull();
+ }
+ else
+ table->field[4]->set_null();
+
+ if (plugin->plugin_dl)
+ {
+ table->field[5]->store(plugin->plugin_dl->dl.str,
+ plugin->plugin_dl->dl.length, cs);
+ table->field[5]->set_notnull();
+ }
+ else
+ table->field[5]->set_null();
+
+ if (plug->author)
+ {
+ table->field[6]->store(plug->author, strlen(plug->author), cs);
+ table->field[6]->set_notnull();
+ }
+ else
+ table->field[6]->set_null();
+
+ if (plug->descr)
+ {
+ table->field[7]->store(plug->descr, strlen(plug->descr), cs);
+ table->field[7]->set_notnull();
+ }
+ else
+ table->field[7]->set_null();
+
+ return schema_table_store_record(thd, table);
+}
+
+
+int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ DBUG_ENTER("fill_plugins");
+ TABLE *table= tables->table;
+
+ if (plugin_foreach(thd, show_plugins, MYSQL_ANY_PLUGIN, table))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
+}
+
+
/***************************************************************************
** List all Authors.
** If you can update it, you get to be in it :)
@@ -1005,8 +1123,8 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
packet->append(STRING_WITH_LEN(" ENGINE="));
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->part_info)
- packet->append(ha_get_storage_engine(table->part_info->
- default_engine_type));
+ packet->append(ha_resolve_storage_engine_name(
+ table->part_info->default_engine_type));
else
packet->append(file->table_type());
#else
@@ -2090,7 +2208,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
Security_context *sctx= thd->security_ctx;
uint derived_tables= lex->derived_tables;
int error= 1;
- db_type not_used;
+ enum legacy_db_type not_used;
Open_tables_state open_tables_state_backup;
DBUG_ENTER("get_all_tables");
@@ -4172,6 +4290,20 @@ ST_FIELD_INFO variables_fields_info[]=
};
+ST_FIELD_INFO plugin_fields_info[]=
+{
+ {"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+ {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status"},
+ {"PLUGIN_TYPE", 10, MYSQL_TYPE_STRING, 0, 0, "Type"},
+ {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Library"},
+ {"PLUGIN_AUTHOR", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
/*
Description of ST_FIELD_INFO in table.h
*/
@@ -4192,6 +4324,8 @@ ST_SCHEMA_TABLE schema_tables[]=
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
{"OPEN_TABLES", open_tables_fields_info, create_schema_table,
fill_open_tables, make_old_format, 0, -1, -1, 1},
+ {"PLUGINS", plugin_fields_info, create_schema_table,
+ fill_plugins, make_old_format, 0, -1, -1, 0},
{"ROUTINES", proc_fields_info, create_schema_table,
fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
{"SCHEMATA", schema_fields_info, create_schema_table,
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ff562cf2a39..c9a997a33db 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -27,7 +27,6 @@
#include <io.h>
#endif
-
const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
@@ -40,7 +39,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
ha_rows *copied,ha_rows *deleted);
static bool prepare_blob_field(THD *thd, create_field *sql_field);
static bool check_engine(THD *thd, const char *table_name,
- enum db_type *new_engine);
+ handlerton **new_engine);
/*
SYNOPSIS
@@ -290,7 +289,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table= tables; table; table= table->next_local)
{
TABLE_SHARE *share;
- table->db_type= DB_TYPE_UNKNOWN;
+ table->db_type= NULL;
if ((share= get_cached_table_share(table->db, table->table_name)))
table->db_type= share->db_type;
}
@@ -304,7 +303,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table= tables; table; table= table->next_local)
{
char *db=table->db;
- db_type table_type;
+ handlerton *table_type;
+ enum legacy_db_type frm_db_type;
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
if (!close_temporary_table(thd, table))
@@ -331,12 +331,12 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
/* remove .frm file and engine files */
build_table_path(path, sizeof(path), db, alias, reg_ext);
}
- if (table_type == DB_TYPE_UNKNOWN &&
+ if (table_type == NULL &&
(drop_temporary ||
(access(path, F_OK) &&
ha_create_table_from_engine(thd, db, alias)) ||
(!drop_view &&
- mysql_frm_type(thd, path, &table_type) != FRMTYPE_TABLE)))
+ mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
{
// Table was not found on disk and table can't be created from engine
if (if_exists)
@@ -349,13 +349,16 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
else
{
char *end;
- if (table_type == DB_TYPE_UNKNOWN)
- mysql_frm_type(thd, path, &table_type);
+ if (table_type == NULL)
+ {
+ mysql_frm_type(thd, path, &frm_db_type);
+ table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
+ }
*(end=fn_ext(path))=0; // Remove extension for delete
error= ha_delete_table(thd, table_type, path, db, table->table_name,
!dont_log_query);
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
- (if_exists || table_type == DB_TYPE_UNKNOWN))
+ (if_exists || table_type == NULL))
error= 0;
if (error == HA_ERR_ROW_IS_REFERENCED)
{
@@ -413,7 +416,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
-bool quick_rm_table(enum db_type base,const char *db,
+bool quick_rm_table(handlerton *base,const char *db,
const char *table_name)
{
char path[FN_REFLEN];
@@ -1670,10 +1673,10 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
this information in the default_db_type variable, it is either
DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
*/
- enum db_type part_engine_type= create_info->db_type;
+ handlerton *part_engine_type= create_info->db_type;
char *part_syntax_buf;
uint syntax_len;
- if (part_engine_type == DB_TYPE_PARTITION_DB)
+ if (part_engine_type == &partition_hton)
{
/*
This only happens at ALTER TABLE.
@@ -1681,7 +1684,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
TABLE command.
*/
part_engine_type= ha_checktype(thd,
- part_info->default_engine_type, 0, 0);
+ ha_legacy_type(part_info->default_engine_type), 0, 0);
}
else
{
@@ -1702,7 +1705,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
if ((!(file->partition_flags() & HA_CAN_PARTITION)) ||
- create_info->db_type == DB_TYPE_PARTITION_DB)
+ create_info->db_type == &partition_hton)
{
/*
The handler assigned to the table cannot handle partitioning.
@@ -1711,7 +1714,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_PRINT("info", ("db_type: %d part_flag: %d",
create_info->db_type,file->partition_flags()));
delete file;
- create_info->db_type= DB_TYPE_PARTITION_DB;
+ create_info->db_type= &partition_hton;
if (!(file= get_ha_partition(part_info)))
{
DBUG_RETURN(TRUE);
@@ -1928,8 +1931,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
tmp_table.s->db_create_options=0;
tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
- tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
- create_info->db_type == DB_TYPE_HEAP);
+ tmp_table.s->db_low_byte_first=
+ test(create_info->db_type == &myisam_hton ||
+ create_info->db_type == &heap_hton);
tmp_table.null_row=tmp_table.maybe_null=0;
while ((item=it++))
@@ -2006,7 +2010,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
****************************************************************************/
bool
-mysql_rename_table(enum db_type base,
+mysql_rename_table(handlerton *base,
const char *old_db,
const char *old_name,
const char *new_db,
@@ -2020,7 +2024,7 @@ mysql_rename_table(enum db_type base,
int error=0;
DBUG_ENTER("mysql_rename_table");
- file= (base == DB_TYPE_UNKNOWN ? 0 :
+ file= (base == NULL ? 0 :
get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
build_table_path(from, sizeof(from), old_db, old_name, "");
@@ -2865,7 +2869,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
char *src_table= table_ident->table.str;
int err;
bool res= TRUE;
- db_type not_used;
+ enum legacy_db_type not_used;
TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
@@ -3153,7 +3157,7 @@ int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
fields.push_back(c_fld);
}
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
db_options= 0;
if (mysql_prepare_table(thd, &create_info, &fields,
@@ -3177,7 +3181,7 @@ int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
/* Re-initialize the create_info, which was changed by prepare table. */
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
/* Cleanup the fields list. We do not want to create existing fields. */
fields.delete_elements();
@@ -3272,7 +3276,7 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
}
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
if ((drop_key)|| (drop.elements<= 0))
@@ -3488,13 +3492,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
ha_rows copied,deleted;
ulonglong next_insert_id;
uint db_create_options, used_fields;
- enum db_type old_db_type,new_db_type;
+ handlerton *old_db_type, *new_db_type;
uint need_copy_table= 0;
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool online_add_empty_partition= FALSE;
bool online_drop_partition= FALSE;
bool partition_changed= FALSE;
- enum db_type default_engine_type;
+ handlerton *default_engine_type;
#endif
DBUG_ENTER("mysql_alter_table");
@@ -3571,7 +3575,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
old_db_type= table->s->db_type;
- if (create_info->db_type == DB_TYPE_DEFAULT)
+ if (create_info->db_type == (handlerton*) &default_hton)
create_info->db_type= old_db_type;
#ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -3675,7 +3679,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(TRUE);
}
}
- create_info->db_type= DB_TYPE_PARTITION_DB;
+ create_info->db_type= &partition_hton;
thd->lex->part_info= tab_part_info;
if (table->file->alter_table_flags() & HA_ONLINE_ADD_EMPTY_PARTITION &&
(tab_part_info->part_type == RANGE_PARTITION ||
@@ -3905,7 +3909,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
}
partition_changed= TRUE;
- create_info->db_type= DB_TYPE_PARTITION_DB;
+ create_info->db_type= &partition_hton;
thd->lex->part_info= tab_part_info;
if (alter_info->flags == ALTER_ADD_PARTITION ||
alter_info->flags == ALTER_REORGANISE_PARTITION)
@@ -3976,9 +3980,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
if (thd->lex->part_info != table->part_info)
partition_changed= TRUE;
- if (create_info->db_type != DB_TYPE_PARTITION_DB)
+ if (create_info->db_type != &partition_hton)
thd->lex->part_info->default_engine_type= create_info->db_type;
- create_info->db_type= DB_TYPE_PARTITION_DB;
+ create_info->db_type= &partition_hton;
}
}
#endif
@@ -4669,7 +4673,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
error=0;
if (!need_copy_table)
- new_db_type=old_db_type=DB_TYPE_UNKNOWN; // this type cannot happen in regular ALTER
+ new_db_type=old_db_type= NULL; // this type cannot happen in regular ALTER
if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
{
error=1;
@@ -4999,7 +5003,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
lex->col_list.empty();
lex->alter_info.reset();
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.db_type= (handlerton*) &default_hton;
create_info.row_type=ROW_TYPE_NOT_USED;
create_info.default_table_charset=default_charset_info;
/* Force alter table to recreate table */
@@ -5131,21 +5135,21 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
}
static bool check_engine(THD *thd, const char *table_name,
- enum db_type *new_engine)
+ handlerton **new_engine)
{
- enum db_type req_engine= *new_engine;
+ handlerton *req_engine= *new_engine;
bool no_substitution=
test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
- if ((*new_engine=
- ha_checktype(thd, req_engine, no_substitution, 1)) == DB_TYPE_UNKNOWN)
+ if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
+ no_substitution, 1)))
return TRUE;
- if (req_engine != *new_engine)
+ if (req_engine != (handlerton*) &default_hton && req_engine != *new_engine)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER),
- ha_get_storage_engine(*new_engine),
+ ha_resolve_storage_engine_name(*new_engine),
table_name);
}
return FALSE;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 02bbe2bc3dc..0f9393f8857 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1169,7 +1169,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
{
char path[FN_REFLEN];
TABLE_LIST *view;
- db_type not_used;
+ enum legacy_db_type not_used;
DBUG_ENTER("mysql_drop_view");
for (view= views; view; view= view->next_local)
@@ -1242,7 +1242,7 @@ err:
FRMTYPE_VIEW view
*/
-frm_type_enum mysql_frm_type(THD *thd, char *path, db_type *dbt)
+frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
{
File file;
uchar header[10]; //"TYPE=VIEW\n" it is 10 characters
@@ -1271,7 +1271,7 @@ frm_type_enum mysql_frm_type(THD *thd, char *path, db_type *dbt)
(header[2] < FRM_VER+3 || header[2] > FRM_VER+4)))
DBUG_RETURN(FRMTYPE_TABLE);
- *dbt= ha_checktype(thd, (enum db_type) (uint) *(header + 3), 0, 0);
+ *dbt= (enum legacy_db_type) (uint) *(header + 3);
DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table
}
diff --git a/sql/sql_view.h b/sql/sql_view.h
index cd61d7e9e71..1e3e5f4aa73 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -27,7 +27,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view);
bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view);
-frm_type_enum mysql_frm_type(THD *thd, char *path, db_type *dbt);
+frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt);
int view_checksum(THD *thd, TABLE_LIST *view);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c79ad97be4e..01491ba8795 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -92,7 +92,7 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2)
enum enum_var_type var_type;
Key::Keytype key_type;
enum ha_key_alg key_alg;
- enum db_type db_type;
+ handlerton *db_type;
enum row_type row_type;
enum ha_rkey_function ha_rkey_mode;
enum enum_tx_isolation tx_isolation;
@@ -1174,7 +1174,7 @@ create:
lex->change=NullS;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
- lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
+ lex->create_info.db_type= lex->thd->variables.table_type;
lex->create_info.default_table_charset= NULL;
lex->name=0;
}
@@ -2781,7 +2781,7 @@ part_definition:
part_info->current_partition= p_elem;
part_info->use_default_partitions= FALSE;
part_info->partitions.push_back(p_elem);
- p_elem->engine_type= DB_TYPE_UNKNOWN;
+ p_elem->engine_type= NULL;
part_info->count_curr_parts++;
}
part_name {}
@@ -2964,7 +2964,7 @@ sub_part_definition:
part_info->current_partition->subpartitions.push_back(p_elem);
part_info->use_default_subpartitions= FALSE;
part_info->count_curr_subparts++;
- p_elem->engine_type= DB_TYPE_UNKNOWN;
+ p_elem->engine_type= NULL;
}
sub_name opt_part_options {}
;
@@ -3193,8 +3193,8 @@ default_collation:
storage_engines:
ident_or_text
{
- $$ = ha_resolve_by_name($1.str,$1.length);
- if ($$ == DB_TYPE_UNKNOWN &&
+ $$ = ha_resolve_by_name(YYTHD, &$1);
+ if ($$ == NULL &&
test(YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION))
{
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
@@ -3845,7 +3845,7 @@ alter:
lex->select_lex.init_order();
lex->select_lex.db=lex->name=0;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
- lex->create_info.db_type= DB_TYPE_DEFAULT;
+ lex->create_info.db_type= (handlerton*) &default_hton;
lex->create_info.default_table_charset= NULL;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_info.reset();
@@ -7010,11 +7010,19 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
YYABORT;
}
+ | PLUGIN_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_PLUGINS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
+ YYABORT;
+ }
| ENGINE_SYM storage_engines
{ Lex->create_info.db_type= $2; }
show_engine_param
| ENGINE_SYM ALL
- { Lex->create_info.db_type= DB_TYPE_DEFAULT; }
+ { Lex->create_info.db_type= NULL; }
show_engine_param
| opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
{
@@ -7106,14 +7114,24 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_ENGINE_STATUS;
- lex->create_info.db_type= DB_TYPE_INNODB;
+ if (!(lex->create_info.db_type=
+ ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB)))
+ {
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB");
+ YYABORT;
+ }
WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS");
}
| MUTEX_SYM STATUS_SYM
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_ENGINE_MUTEX;
- lex->create_info.db_type= DB_TYPE_INNODB;
+ if (!(lex->create_info.db_type=
+ ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB)))
+ {
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB");
+ YYABORT;
+ }
WARN_DEPRECATED("SHOW MUTEX STATUS", "SHOW ENGINE INNODB MUTEX");
}
| opt_full PROCESSLIST_SYM
@@ -7147,14 +7165,24 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS;
- lex->create_info.db_type= DB_TYPE_BERKELEY_DB;
+ if (!(lex->create_info.db_type=
+ ha_resolve_by_legacy_type(YYTHD, DB_TYPE_BERKELEY_DB)))
+ {
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "BerkeleyDB");
+ YYABORT;
+ }
WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS");
}
| LOGS_SYM
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS;
- lex->create_info.db_type= DB_TYPE_BERKELEY_DB;
+ if (!(lex->create_info.db_type=
+ ha_resolve_by_legacy_type(YYTHD, DB_TYPE_BERKELEY_DB)))
+ {
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "BerkeleyDB");
+ YYABORT;
+ }
WARN_DEPRECATED("SHOW LOGS", "SHOW ENGINE BDB LOGS");
}
| GRANTS
@@ -9828,7 +9856,7 @@ opt_migrate:
;
install:
- INSTALL_SYM PLUGIN_SYM IDENT_sys SONAME_SYM TEXT_STRING_sys
+ INSTALL_SYM PLUGIN_SYM ident SONAME_SYM TEXT_STRING_sys
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_INSTALL_PLUGIN;
@@ -9837,7 +9865,7 @@ install:
};
uninstall:
- UNINSTALL_SYM PLUGIN_SYM IDENT_sys
+ UNINSTALL_SYM PLUGIN_SYM ident
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
diff --git a/sql/table.cc b/sql/table.cc
index ff29a33ef03..91fbf915dc5 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -327,6 +327,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
SQL_CRYPT *crypted=0;
Field **field_ptr, *reg_field;
const char **interval_array;
+ enum legacy_db_type legacy_db_type;
DBUG_ENTER("open_binary_frm");
new_field_pack_flag= head[27];
@@ -349,11 +350,11 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
share->frm_version= FRM_VER_TRUE_VARCHAR;
#ifdef WITH_PARTITION_STORAGE_ENGINE
- share->default_part_db_type= ha_checktype(thd,
- (enum db_type) (uint) *(head+61),0,
- 0);
+ share->default_part_db_type=
+ ha_checktype(thd, (enum legacy_db_type) (uint) *(head+61), 0, 0);
#endif
- share->db_type= ha_checktype(thd, (enum db_type) (uint) *(head+3),0,0);
+ legacy_db_type= (enum legacy_db_type) (uint) *(head+3);
+ share->db_type= ha_checktype(thd, legacy_db_type, 0, 0);
share->db_create_options= db_create_options= uint2korr(head+30);
share->db_options_in_use= share->db_create_options;
share->mysql_version= uint4korr(head+51);
@@ -385,7 +386,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
share->blob_ptr_size= portable_sizeof_char_ptr;
/* Set temporarily a good value for db_low_byte_first */
- share->db_low_byte_first= test(share->db_type != DB_TYPE_ISAM);
+ share->db_low_byte_first= test(legacy_db_type != DB_TYPE_ISAM);
error=4;
share->max_rows= uint4korr(head+18);
share->min_rows= uint4korr(head+22);
@@ -513,14 +514,14 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (next_chunk + 2 < buff_end)
{
uint str_db_type_length= uint2korr(next_chunk);
- enum db_type tmp_db_type= ha_resolve_by_name(next_chunk + 2,
- str_db_type_length);
- if (tmp_db_type != DB_TYPE_UNKNOWN)
+ LEX_STRING name= { next_chunk + 2, str_db_type_length };
+ handlerton *tmp_db_type= ha_resolve_by_name(thd, &name);
+ if (tmp_db_type != NULL)
{
share->db_type= tmp_db_type;
DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
str_db_type_length, next_chunk + 2,
- share->db_type));
+ ha_legacy_type(share->db_type)));
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
else
@@ -528,10 +529,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (!strncmp(next_chunk + 2, "partition", str_db_type_length))
{
/* Use partition handler */
- share->db_type= DB_TYPE_PARTITION_DB;
+ share->db_type= &partition_hton;
DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
str_db_type_length, next_chunk + 2,
- share->db_type));
+ ha_legacy_type(share->db_type)));
}
}
#endif
@@ -1634,7 +1635,7 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg)
handler *file= 0;
const char *datext= "";
- if (share->db_type != DB_TYPE_UNKNOWN)
+ if (share->db_type != NULL)
{
if ((file= get_new_handler(share, current_thd->mem_root,
share->db_type)))
@@ -1900,7 +1901,8 @@ File create_frm(THD *thd, const char *name, const char *db,
fileinfo[1]= 1;
fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
- fileinfo[3]= (uchar) ha_checktype(thd,create_info->db_type,0,0);
+ fileinfo[3]= (uchar) ha_legacy_type(
+ ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0));
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
diff --git a/sql/table.h b/sql/table.h
index 81c13552a04..ef8ef5242d0 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -153,7 +153,7 @@ typedef struct st_table_share
ulong timestamp_offset; /* Set to offset+1 of record */
ulong reclength; /* Recordlength */
- enum db_type db_type; /* table_type for handler */
+ handlerton *db_type; /* table_type for handler */
enum row_type row_type; /* How rows are stored */
enum tmp_table_type tmp_table;
@@ -200,7 +200,7 @@ typedef struct st_table_share
#ifdef WITH_PARTITION_STORAGE_ENGINE
const uchar *partition_info;
uint partition_info_len;
- enum db_type default_part_db_type;
+ handlerton *default_part_db_type;
#endif
} TABLE_SHARE;
@@ -324,6 +324,7 @@ enum enum_schema_tables
SCH_COLUMN_PRIVILEGES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
+ SCH_PLUGINS,
SCH_PROCEDURES,
SCH_SCHEMATA,
SCH_SCHEMA_PRIVILEGES,
@@ -642,7 +643,7 @@ typedef struct st_table_list
bool where_processed;
/* FRMTYPE_ERROR if any type is acceptable */
enum frm_type_enum required_type;
- enum db_type db_type; /* table_type for handler */
+ handlerton *db_type; /* table_type for handler */
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
/*
This TABLE_LIST object is just placeholder for prelocking, it will be
diff --git a/sql/unireg.cc b/sql/unireg.cc
index ebbf1177953..66be20736e8 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -35,7 +35,7 @@ static uchar * pack_screens(List<create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
ulong data_offset);
-static bool pack_header(uchar *forminfo,enum db_type table_type,
+static bool pack_header(uchar *forminfo,enum legacy_db_type table_type,
List<create_field> &create_fields,
uint info_length, uint screens, uint table_options,
ulong data_offset, handler *file);
@@ -43,7 +43,7 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
create_field *last_field);
static bool pack_fields(File file, List<create_field> &create_fields,
ulong data_offset);
-static bool make_empty_rec(THD *thd, int file, enum db_type table_type,
+static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type,
uint table_options,
List<create_field> &create_fields,
uint reclength, ulong data_offset,
@@ -103,7 +103,8 @@ bool mysql_create_frm(THD *thd, const char *file_name,
create_info->null_bits++;
data_offset= (create_info->null_bits + 7) / 8;
- if (pack_header(forminfo, create_info->db_type,create_fields,info_length,
+ if (pack_header(forminfo, ha_legacy_type(create_info->db_type),
+ create_fields,info_length,
screens, create_info->table_options,
data_offset, db_file))
{
@@ -115,7 +116,8 @@ bool mysql_create_frm(THD *thd, const char *file_name,
thd->net.last_error[0]=0;
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
DBUG_RETURN(1);
- if (pack_header(forminfo, create_info->db_type, create_fields,info_length,
+ if (pack_header(forminfo, ha_legacy_type(create_info->db_type),
+ create_fields,info_length,
screens, create_info->table_options, data_offset, db_file))
{
my_free((gptr) screen_buff,MYF(0));
@@ -125,7 +127,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
reclength=uint2korr(forminfo+266);
/* Calculate extra data segment length */
- str_db_type.str= (char *) ha_get_storage_engine(create_info->db_type);
+ str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type);
str_db_type.length= strlen(str_db_type.str);
/* str_db_type */
create_info->extra_size= (2 + str_db_type.length +
@@ -168,7 +170,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (part_info)
- fileinfo[61]= (uchar) part_info->default_engine_type;
+ fileinfo[61]= (uchar) ha_legacy_type(part_info->default_engine_type);
#endif
int2store(fileinfo+59,db_file->extra_rec_buf_length());
if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) ||
@@ -178,7 +180,8 @@ bool mysql_create_frm(THD *thd, const char *file_name,
VOID(my_seek(file,
(ulong) uint2korr(fileinfo+6)+ (ulong) key_buff_length,
MY_SEEK_SET,MYF(0)));
- if (make_empty_rec(thd,file,create_info->db_type,create_info->table_options,
+ if (make_empty_rec(thd,file,ha_legacy_type(create_info->db_type),
+ create_info->table_options,
create_fields,reclength, data_offset, db_file))
goto err;
@@ -480,7 +483,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
/* Make formheader */
-static bool pack_header(uchar *forminfo, enum db_type table_type,
+static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
List<create_field> &create_fields,
uint info_length, uint screens, uint table_options,
ulong data_offset, handler *file)
@@ -739,7 +742,7 @@ static bool pack_fields(File file, List<create_field> &create_fields,
/* save an empty record on start of formfile */
-static bool make_empty_rec(THD *thd, File file,enum db_type table_type,
+static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type,
uint table_options,
List<create_field> &create_fields,
uint reclength,