summaryrefslogtreecommitdiff
path: root/sql/examples
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/examples
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/examples')
-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
4 files changed, 0 insertions, 1935 deletions
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);
-