00001 /* Copyright (C) 2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* 00018 ha_example is a stubbed storage engine. It does nothing at this point. It 00019 will let you create/open/delete tables but that is all. You can enable it 00020 in your buld by doing the following during your build process: 00021 ./configure --with-example-storage-engine 00022 00023 Once this is done mysql will let you create tables with: 00024 CREATE TABLE A (...) ENGINE=EXAMPLE; 00025 00026 The example is setup to use table locks. It implements an example "SHARE" 00027 that is inserted into a hash by table name. You can use this to store 00028 information of state that any example handler object will be able to see 00029 if it is using the same table. 00030 00031 Please read the object definition in ha_example.h before reading the rest 00032 if this file. 00033 00034 To get an idea of what occurs here is an example select that would do a 00035 scan of an entire table: 00036 ha_example::store_lock 00037 ha_example::external_lock 00038 ha_example::info 00039 ha_example::rnd_init 00040 ha_example::extra 00041 ENUM HA_EXTRA_CACHE Cash record in HA_rrnd() 00042 ha_example::rnd_next 00043 ha_example::rnd_next 00044 ha_example::rnd_next 00045 ha_example::rnd_next 00046 ha_example::rnd_next 00047 ha_example::rnd_next 00048 ha_example::rnd_next 00049 ha_example::rnd_next 00050 ha_example::rnd_next 00051 ha_example::extra 00052 ENUM HA_EXTRA_NO_CACHE End cacheing of records (def) 00053 ha_example::external_lock 00054 ha_example::extra 00055 ENUM HA_EXTRA_RESET Reset database to after open 00056 00057 In the above example has 9 row called before rnd_next signalled that it was 00058 at the end of its data. In the above example the table was already opened 00059 (or you would have seen a call to ha_example::open(). Calls to 00060 ha_example::extra() are hints as to what will be occuring to the request. 00061 00062 Happy coding! 00063 -Brian 00064 */ 00065 00066 #ifdef USE_PRAGMA_IMPLEMENTATION 00067 #pragma implementation // gcc: Class implementation 00068 #endif 00069 00070 #include "mysql_priv.h" 00071 #include "ha_example.h" 00072 00073 #include <mysql/plugin.h> 00074 00075 static handler *example_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root); 00076 static int example_init_func(); 00077 static bool example_init_func_for_handlerton(); 00078 static int example_panic(enum ha_panic_function flag); 00079 00080 handlerton example_hton; 00081 00082 /* Variables for example share methods */ 00083 static HASH example_open_tables; // Hash used to track open tables 00084 pthread_mutex_t example_mutex; // This is the mutex we use to init the hash 00085 static int example_init= 0; // Variable for checking the init state of hash 00086 00087 00088 /* 00089 Function we use in the creation of our hash to get key. 00090 */ 00091 static byte* example_get_key(EXAMPLE_SHARE *share,uint *length, 00092 my_bool not_used __attribute__((unused))) 00093 { 00094 *length=share->table_name_length; 00095 return (byte*) share->table_name; 00096 } 00097 00098 static int example_init_func() 00099 { 00100 DBUG_ENTER("example_init_func"); 00101 if (!example_init) 00102 { 00103 example_init= 1; 00104 VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST)); 00105 (void) hash_init(&example_open_tables,system_charset_info,32,0,0, 00106 (hash_get_key) example_get_key,0,0); 00107 00108 example_hton.state= SHOW_OPTION_YES; 00109 example_hton.db_type= DB_TYPE_EXAMPLE_DB; 00110 example_hton.create= example_create_handler; 00111 example_hton.flags= HTON_CAN_RECREATE; 00112 } 00113 DBUG_RETURN(0); 00114 } 00115 00116 static int example_done_func() 00117 { 00118 int error= 0; 00119 DBUG_ENTER("example_done_func"); 00120 00121 if (example_init) 00122 { 00123 example_init= 0; 00124 if (example_open_tables.records) 00125 error= 1; 00126 hash_free(&example_open_tables); 00127 pthread_mutex_destroy(&example_mutex); 00128 } 00129 DBUG_RETURN(0); 00130 } 00131 00132 /* 00133 Example of simple lock controls. The "share" it creates is structure we will 00134 pass to each example handler. Do you have to have one of these? Well, you have 00135 pieces that are used for locking, and they are needed to function. 00136 */ 00137 static EXAMPLE_SHARE *get_share(const char *table_name, TABLE *table) 00138 { 00139 EXAMPLE_SHARE *share; 00140 uint length; 00141 char *tmp_name; 00142 00143 pthread_mutex_lock(&example_mutex); 00144 length=(uint) strlen(table_name); 00145 00146 if (!(share=(EXAMPLE_SHARE*) hash_search(&example_open_tables, 00147 (byte*) table_name, 00148 length))) 00149 { 00150 if (!(share=(EXAMPLE_SHARE *) 00151 my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), 00152 &share, sizeof(*share), 00153 &tmp_name, length+1, 00154 NullS))) 00155 { 00156 pthread_mutex_unlock(&example_mutex); 00157 return NULL; 00158 } 00159 00160 share->use_count=0; 00161 share->table_name_length=length; 00162 share->table_name=tmp_name; 00163 strmov(share->table_name,table_name); 00164 if (my_hash_insert(&example_open_tables, (byte*) share)) 00165 goto error; 00166 thr_lock_init(&share->lock); 00167 pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); 00168 } 00169 share->use_count++; 00170 pthread_mutex_unlock(&example_mutex); 00171 00172 return share; 00173 00174 error: 00175 pthread_mutex_destroy(&share->mutex); 00176 my_free((gptr) share, MYF(0)); 00177 00178 return NULL; 00179 } 00180 00181 00182 /* 00183 Free lock controls. We call this whenever we close a table. If the table had 00184 the last reference to the share then we free memory associated with it. 00185 */ 00186 static int free_share(EXAMPLE_SHARE *share) 00187 { 00188 pthread_mutex_lock(&example_mutex); 00189 if (!--share->use_count) 00190 { 00191 hash_delete(&example_open_tables, (byte*) share); 00192 thr_lock_delete(&share->lock); 00193 pthread_mutex_destroy(&share->mutex); 00194 my_free((gptr) share, MYF(0)); 00195 } 00196 pthread_mutex_unlock(&example_mutex); 00197 00198 return 0; 00199 } 00200 00201 00202 static handler* example_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root) 00203 { 00204 return new (mem_root) ha_example(table); 00205 } 00206 00207 00208 ha_example::ha_example(TABLE_SHARE *table_arg) 00209 :handler(&example_hton, table_arg) 00210 {} 00211 00212 /* 00213 If frm_error() is called then we will use this to to find out what file extentions 00214 exist for the storage engine. This is also used by the default rename_table and 00215 delete_table method in handler.cc. 00216 */ 00217 static const char *ha_example_exts[] = { 00218 NullS 00219 }; 00220 00221 const char **ha_example::bas_ext() const 00222 { 00223 return ha_example_exts; 00224 } 00225 00226 00227 /* 00228 Used for opening tables. The name will be the name of the file. 00229 A table is opened when it needs to be opened. For instance 00230 when a request comes in for a select on the table (tables are not 00231 open and closed for each request, they are cached). 00232 00233 Called from handler.cc by handler::ha_open(). The server opens all tables by 00234 calling ha_open() which then calls the handler specific open(). 00235 */ 00236 int ha_example::open(const char *name, int mode, uint test_if_locked) 00237 { 00238 DBUG_ENTER("ha_example::open"); 00239 00240 if (!(share = get_share(name, table))) 00241 DBUG_RETURN(1); 00242 thr_lock_data_init(&share->lock,&lock,NULL); 00243 00244 DBUG_RETURN(0); 00245 } 00246 00247 00248 /* 00249 Closes a table. We call the free_share() function to free any resources 00250 that we have allocated in the "shared" structure. 00251 00252 Called from sql_base.cc, sql_select.cc, and table.cc. 00253 In sql_select.cc it is only used to close up temporary tables or during 00254 the process where a temporary table is converted over to being a 00255 myisam table. 00256 For sql_base.cc look at close_data_tables(). 00257 */ 00258 int ha_example::close(void) 00259 { 00260 DBUG_ENTER("ha_example::close"); 00261 DBUG_RETURN(free_share(share)); 00262 } 00263 00264 00265 /* 00266 write_row() inserts a row. No extra() hint is given currently if a bulk load 00267 is happeneding. buf() is a byte array of data. You can use the field 00268 information to extract the data from the native byte array type. 00269 Example of this would be: 00270 for (Field **field=table->field ; *field ; field++) 00271 { 00272 ... 00273 } 00274 00275 See ha_tina.cc for an example of extracting all of the data as strings. 00276 ha_berekly.cc has an example of how to store it intact by "packing" it 00277 for ha_berkeley's own native storage type. 00278 00279 See the note for update_row() on auto_increments and timestamps. This 00280 case also applied to write_row(). 00281 00282 Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, 00283 sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. 00284 */ 00285 int ha_example::write_row(byte * buf) 00286 { 00287 DBUG_ENTER("ha_example::write_row"); 00288 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00289 } 00290 00291 00292 /* 00293 Yes, update_row() does what you expect, it updates a row. old_data will have 00294 the previous row record in it, while new_data will have the newest data in 00295 it. 00296 Keep in mind that the server can do updates based on ordering if an ORDER BY 00297 clause was used. Consecutive ordering is not guarenteed. 00298 Currently new_data will not have an updated auto_increament record, or 00299 and updated timestamp field. You can do these for example by doing these: 00300 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) 00301 table->timestamp_field->set_time(); 00302 if (table->next_number_field && record == table->record[0]) 00303 update_auto_increment(); 00304 00305 Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc. 00306 */ 00307 int ha_example::update_row(const byte * old_data, byte * new_data) 00308 { 00309 00310 DBUG_ENTER("ha_example::update_row"); 00311 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00312 } 00313 00314 00315 /* 00316 This will delete a row. buf will contain a copy of the row to be deleted. 00317 The server will call this right after the current row has been called (from 00318 either a previous rnd_nexT() or index call). 00319 If you keep a pointer to the last row or can access a primary key it will 00320 make doing the deletion quite a bit easier. 00321 Keep in mind that the server does no guarentee consecutive deletions. ORDER BY 00322 clauses can be used. 00323 00324 Called in sql_acl.cc and sql_udf.cc to manage internal table information. 00325 Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select it is 00326 used for removing duplicates while in insert it is used for REPLACE calls. 00327 */ 00328 int ha_example::delete_row(const byte * buf) 00329 { 00330 DBUG_ENTER("ha_example::delete_row"); 00331 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00332 } 00333 00334 00335 /* 00336 Positions an index cursor to the index specified in the handle. Fetches the 00337 row if available. If the key value is null, begin at the first key of the 00338 index. 00339 */ 00340 int ha_example::index_read(byte * buf, const byte * key, 00341 uint key_len __attribute__((unused)), 00342 enum ha_rkey_function find_flag 00343 __attribute__((unused))) 00344 { 00345 DBUG_ENTER("ha_example::index_read"); 00346 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00347 } 00348 00349 00350 /* 00351 Positions an index cursor to the index specified in key. Fetches the 00352 row if any. This is only used to read whole keys. 00353 */ 00354 int ha_example::index_read_idx(byte * buf, uint index, const byte * key, 00355 uint key_len __attribute__((unused)), 00356 enum ha_rkey_function find_flag 00357 __attribute__((unused))) 00358 { 00359 DBUG_ENTER("ha_example::index_read_idx"); 00360 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00361 } 00362 00363 00364 /* 00365 Used to read forward through the index. 00366 */ 00367 int ha_example::index_next(byte * buf) 00368 { 00369 DBUG_ENTER("ha_example::index_next"); 00370 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00371 } 00372 00373 00374 /* 00375 Used to read backwards through the index. 00376 */ 00377 int ha_example::index_prev(byte * buf) 00378 { 00379 DBUG_ENTER("ha_example::index_prev"); 00380 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00381 } 00382 00383 00384 /* 00385 index_first() asks for the first key in the index. 00386 00387 Called from opt_range.cc, opt_sum.cc, sql_handler.cc, 00388 and sql_select.cc. 00389 */ 00390 int ha_example::index_first(byte * buf) 00391 { 00392 DBUG_ENTER("ha_example::index_first"); 00393 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00394 } 00395 00396 00397 /* 00398 index_last() asks for the last key in the index. 00399 00400 Called from opt_range.cc, opt_sum.cc, sql_handler.cc, 00401 and sql_select.cc. 00402 */ 00403 int ha_example::index_last(byte * buf) 00404 { 00405 DBUG_ENTER("ha_example::index_last"); 00406 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00407 } 00408 00409 00410 /* 00411 rnd_init() is called when the system wants the storage engine to do a table 00412 scan. 00413 See the example in the introduction at the top of this file to see when 00414 rnd_init() is called. 00415 00416 Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc, 00417 and sql_update.cc. 00418 */ 00419 int ha_example::rnd_init(bool scan) 00420 { 00421 DBUG_ENTER("ha_example::rnd_init"); 00422 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00423 } 00424 00425 int ha_example::rnd_end() 00426 { 00427 DBUG_ENTER("ha_example::rnd_end"); 00428 DBUG_RETURN(0); 00429 } 00430 00431 /* 00432 This is called for each row of the table scan. When you run out of records 00433 you should return HA_ERR_END_OF_FILE. Fill buff up with the row information. 00434 The Field structure for the table is the key to getting data into buf 00435 in a manner that will allow the server to understand it. 00436 00437 Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc, 00438 and sql_update.cc. 00439 */ 00440 int ha_example::rnd_next(byte *buf) 00441 { 00442 DBUG_ENTER("ha_example::rnd_next"); 00443 DBUG_RETURN(HA_ERR_END_OF_FILE); 00444 } 00445 00446 00447 /* 00448 position() is called after each call to rnd_next() if the data needs 00449 to be ordered. You can do something like the following to store 00450 the position: 00451 my_store_ptr(ref, ref_length, current_position); 00452 00453 The server uses ref to store data. ref_length in the above case is 00454 the size needed to store current_position. ref is just a byte array 00455 that the server will maintain. If you are using offsets to mark rows, then 00456 current_position should be the offset. If it is a primary key like in 00457 BDB, then it needs to be a primary key. 00458 00459 Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. 00460 */ 00461 void ha_example::position(const byte *record) 00462 { 00463 DBUG_ENTER("ha_example::position"); 00464 DBUG_VOID_RETURN; 00465 } 00466 00467 00468 /* 00469 This is like rnd_next, but you are given a position to use 00470 to determine the row. The position will be of the type that you stored in 00471 ref. You can use ha_get_ptr(pos,ref_length) to retrieve whatever key 00472 or position you saved when position() was called. 00473 Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc. 00474 */ 00475 int ha_example::rnd_pos(byte * buf, byte *pos) 00476 { 00477 DBUG_ENTER("ha_example::rnd_pos"); 00478 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00479 } 00480 00481 00482 /* 00483 ::info() is used to return information to the optimizer. 00484 see my_base.h for the complete description 00485 00486 Currently this table handler doesn't implement most of the fields 00487 really needed. SHOW also makes use of this data 00488 Another note, you will probably want to have the following in your 00489 code: 00490 if (records < 2) 00491 records = 2; 00492 The reason is that the server will optimize for cases of only a single 00493 record. If in a table scan you don't know the number of records 00494 it will probably be better to set records to two so you can return 00495 as many records as you need. 00496 Along with records a few more variables you may wish to set are: 00497 records 00498 deleted 00499 data_file_length 00500 index_file_length 00501 delete_length 00502 check_time 00503 Take a look at the public variables in handler.h for more information. 00504 00505 Called in: 00506 filesort.cc 00507 ha_heap.cc 00508 item_sum.cc 00509 opt_sum.cc 00510 sql_delete.cc 00511 sql_delete.cc 00512 sql_derived.cc 00513 sql_select.cc 00514 sql_select.cc 00515 sql_select.cc 00516 sql_select.cc 00517 sql_select.cc 00518 sql_show.cc 00519 sql_show.cc 00520 sql_show.cc 00521 sql_show.cc 00522 sql_table.cc 00523 sql_union.cc 00524 sql_update.cc 00525 00526 */ 00527 void ha_example::info(uint flag) 00528 { 00529 DBUG_ENTER("ha_example::info"); 00530 DBUG_VOID_RETURN; 00531 } 00532 00533 00534 /* 00535 extra() is called whenever the server wishes to send a hint to 00536 the storage engine. The myisam engine implements the most hints. 00537 ha_innodb.cc has the most exhaustive list of these hints. 00538 */ 00539 int ha_example::extra(enum ha_extra_function operation) 00540 { 00541 DBUG_ENTER("ha_example::extra"); 00542 DBUG_RETURN(0); 00543 } 00544 00545 00546 /* 00547 Deprecated and likely to be removed in the future. Storage engines normally 00548 just make a call like: 00549 ha_example::extra(HA_EXTRA_RESET); 00550 to handle it. 00551 */ 00552 int ha_example::reset(void) 00553 { 00554 DBUG_ENTER("ha_example::reset"); 00555 DBUG_RETURN(0); 00556 } 00557 00558 00559 /* 00560 Used to delete all rows in a table. Both for cases of truncate and 00561 for cases where the optimizer realizes that all rows will be 00562 removed as a result of a SQL statement. 00563 00564 Called from item_sum.cc by Item_func_group_concat::clear(), 00565 Item_sum_count_distinct::clear(), and Item_func_group_concat::clear(). 00566 Called from sql_delete.cc by mysql_delete(). 00567 Called from sql_select.cc by JOIN::reinit(). 00568 Called from sql_union.cc by st_select_lex_unit::exec(). 00569 */ 00570 int ha_example::delete_all_rows() 00571 { 00572 DBUG_ENTER("ha_example::delete_all_rows"); 00573 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00574 } 00575 00576 00577 /* 00578 First you should go read the section "locking functions for mysql" in 00579 lock.cc to understand this. 00580 This create a lock on the table. If you are implementing a storage engine 00581 that can handle transacations look at ha_berkely.cc to see how you will 00582 want to goo about doing this. Otherwise you should consider calling flock() 00583 here. 00584 00585 Called from lock.cc by lock_external() and unlock_external(). Also called 00586 from sql_table.cc by copy_data_between_tables(). 00587 */ 00588 int ha_example::external_lock(THD *thd, int lock_type) 00589 { 00590 DBUG_ENTER("ha_example::external_lock"); 00591 DBUG_RETURN(0); 00592 } 00593 00594 00595 /* 00596 The idea with handler::store_lock() is the following: 00597 00598 The statement decided which locks we should need for the table 00599 for updates/deletes/inserts we get WRITE locks, for SELECT... we get 00600 read locks. 00601 00602 Before adding the lock into the table lock handler (see thr_lock.c) 00603 mysqld calls store lock with the requested locks. Store lock can now 00604 modify a write lock to a read lock (or some other lock), ignore the 00605 lock (if we don't want to use MySQL table locks at all) or add locks 00606 for many tables (like we do when we are using a MERGE handler). 00607 00608 Berkeley DB for example changes all WRITE locks to TL_WRITE_ALLOW_WRITE 00609 (which signals that we are doing WRITES, but we are still allowing other 00610 reader's and writer's. 00611 00612 When releasing locks, store_lock() are also called. In this case one 00613 usually doesn't have to do anything. 00614 00615 In some exceptional cases MySQL may send a request for a TL_IGNORE; 00616 This means that we are requesting the same lock as last time and this 00617 should also be ignored. (This may happen when someone does a flush 00618 table when we have opened a part of the tables, in which case mysqld 00619 closes and reopens the tables and tries to get the same locks at last 00620 time). In the future we will probably try to remove this. 00621 00622 Called from lock.cc by get_lock_data(). 00623 */ 00624 THR_LOCK_DATA **ha_example::store_lock(THD *thd, 00625 THR_LOCK_DATA **to, 00626 enum thr_lock_type lock_type) 00627 { 00628 if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) 00629 lock.type=lock_type; 00630 *to++= &lock; 00631 return to; 00632 } 00633 00634 /* 00635 Used to delete a table. By the time delete_table() has been called all 00636 opened references to this table will have been closed (and your globally 00637 shared references released. The variable name will just be the name of 00638 the table. You will need to remove any files you have created at this point. 00639 00640 If you do not implement this, the default delete_table() is called from 00641 handler.cc and it will delete all files with the file extentions returned 00642 by bas_ext(). 00643 00644 Called from handler.cc by delete_table and ha_create_table(). Only used 00645 during create if the table_flag HA_DROP_BEFORE_CREATE was specified for 00646 the storage engine. 00647 */ 00648 int ha_example::delete_table(const char *name) 00649 { 00650 DBUG_ENTER("ha_example::delete_table"); 00651 /* This is not implemented but we want someone to be able that it works. */ 00652 DBUG_RETURN(0); 00653 } 00654 00655 /* 00656 Renames a table from one name to another from alter table call. 00657 00658 If you do not implement this, the default rename_table() is called from 00659 handler.cc and it will delete all files with the file extentions returned 00660 by bas_ext(). 00661 00662 Called from sql_table.cc by mysql_rename_table(). 00663 */ 00664 int ha_example::rename_table(const char * from, const char * to) 00665 { 00666 DBUG_ENTER("ha_example::rename_table "); 00667 DBUG_RETURN(HA_ERR_WRONG_COMMAND); 00668 } 00669 00670 /* 00671 Given a starting key, and an ending key estimate the number of rows that 00672 will exist between the two. end_key may be empty which in case determine 00673 if start_key matches any rows. 00674 00675 Called from opt_range.cc by check_quick_keys(). 00676 */ 00677 ha_rows ha_example::records_in_range(uint inx, key_range *min_key, 00678 key_range *max_key) 00679 { 00680 DBUG_ENTER("ha_example::records_in_range"); 00681 DBUG_RETURN(10); // low number to force index usage 00682 } 00683 00684 00685 /* 00686 create() is called to create a database. The variable name will have the name 00687 of the table. When create() is called you do not need to worry about opening 00688 the table. Also, the FRM file will have already been created so adjusting 00689 create_info will not do you any good. You can overwrite the frm file at this 00690 point if you wish to change the table definition, but there are no methods 00691 currently provided for doing that. 00692 00693 Called from handle.cc by ha_create_table(). 00694 */ 00695 int ha_example::create(const char *name, TABLE *table_arg, 00696 HA_CREATE_INFO *create_info) 00697 { 00698 DBUG_ENTER("ha_example::create"); 00699 /* This is not implemented but we want someone to be able to see that it works. */ 00700 DBUG_RETURN(0); 00701 } 00702 00703 struct st_mysql_storage_engine example_storage_engine= 00704 { MYSQL_HANDLERTON_INTERFACE_VERSION, &example_hton }; 00705 00706 00707 mysql_declare_plugin(example) 00708 { 00709 MYSQL_STORAGE_ENGINE_PLUGIN, 00710 &example_storage_engine, 00711 "EXAMPLE", 00712 "Brian Aker, MySQL AB", 00713 "Example storage engine", 00714 example_init_func, /* Plugin Init */ 00715 example_done_func, /* Plugin Deinit */ 00716 0x0001 /* 0.1 */, 00717 0 00718 } 00719 mysql_declare_plugin_end; 00720
1.4.7

