ha_example.cc 25.5 KB
Newer Older
1 2 3 4
/* 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
5
  the Free Software Foundation; version 2 of the License.
6 7 8 9 10 11 12 13 14 15

  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 */

16 17
/**
  @file ha_example.cc
18

19
  @brief
20 21 22 23 24
  The ha_example engine is a stubbed storage engine for example purposes only;
  it does nothing at this point. Its purpose is to provide a source
  code illustration of how to begin writing new storage engines; see also
  /storage/example/ha_example.h.

25 26 27 28 29 30 31 32
  @details
  ha_example will let you create/open/delete tables, but
  nothing further (for example, indexes are not supported nor can data
  be stored in the table). Use this example as a template for
  implementing the same functionality in your own storage engine. You
  can enable the example storage engine in your build by doing the
  following during your build process:<br> ./configure
  --with-example-storage-engine
33

34 35
  Once this is done, MySQL will let you create tables with:<br>
  CREATE TABLE <table name> (...) ENGINE=EXAMPLE;
36

37 38 39 40 41
  The example storage engine is set up 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 when it is using that
  table.
42

43
  Please read the object definition in ha_example.h before reading the rest
44 45
  of this file.

46 47 48 49 50 51 52 53
  @note
  When you create an EXAMPLE table, the MySQL Server creates a table .frm
  (format) file in the database directory, using the table name as the file
  name as is customary with MySQL. No other files are created. To get an idea
  of what occurs, here is an example select that would do a scan of an entire
  table:

  @code
54 55 56 57 58
  ha_example::store_lock
  ha_example::external_lock
  ha_example::info
  ha_example::rnd_init
  ha_example::extra
59
  ENUM HA_EXTRA_CACHE        Cache record in HA_rrnd()
60 61 62 63 64 65 66 67 68 69
  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
70
  ENUM HA_EXTRA_NO_CACHE     End caching of records (def)
71
  ha_example::external_lock
72
  ha_example::extra
73
  ENUM HA_EXTRA_RESET        Reset database to after open
74
  @endcode
75

76 77 78 79 80
  Here you see that the example storage engine has 9 rows called before
  rnd_next signals that it has reached the end of its data. Also note that
  the table in question was already opened; had it not been open, a call to
  ha_example::open() would also have been necessary. Calls to
  ha_example::extra() are hints as to what will be occuring to the request.
81

82 83 84 85
  A Longer Example can be found called the "Skeleton Engine" which can be 
  found on TangentOrg. It has both an engine and a full build environment
  for building a pluggable storage engine.

86
  Happy coding!<br>
87 88 89
    -Brian
*/

kent@mysql.com's avatar
kent@mysql.com committed
90
#ifdef USE_PRAGMA_IMPLEMENTATION
91 92 93
#pragma implementation        // gcc: Class implementation
#endif

94
#define MYSQL_SERVER 1
acurtis@xiphis.org's avatar
acurtis@xiphis.org committed
95
#include "mysql_priv.h"
96
#include "ha_example.h"
97
#include <mysql/plugin.h>
acurtis@xiphis.org's avatar
acurtis@xiphis.org committed
98

99 100 101
static handler *example_create_handler(handlerton *hton,
                                       TABLE_SHARE *table, 
                                       MEM_ROOT *mem_root);
102

103
handlerton *example_hton;
104

105
/* Variables for example share methods */
106

107 108 109 110 111 112 113 114 115 116 117
/* 
   Hash used to track the number of open tables; variable for example share
   methods
*/
static HASH example_open_tables;

/* The mutex used to init the hash; variable for example share methods */
pthread_mutex_t example_mutex;

/**
  @brief
118 119
  Function we use in the creation of our hash to get key.
*/
120

121
static uchar* example_get_key(EXAMPLE_SHARE *share, size_t *length,
122 123 124
                             my_bool not_used __attribute__((unused)))
{
  *length=share->table_name_length;
125
  return (uchar*) share->table_name;
126 127
}

128

129
static int example_init_func(void *p)
130
{
131
  DBUG_ENTER("example_init_func");
132 133 134 135 136 137 138 139 140 141

  example_hton= (handlerton *)p;
  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);

  example_hton->state=   SHOW_OPTION_YES;
  example_hton->create=  example_create_handler;
  example_hton->flags=   HTON_CAN_RECREATE;

142
  DBUG_RETURN(0);
143 144
}

145

146
static int example_done_func(void *p)
147
{
148 149 150
  int error= 0;
  DBUG_ENTER("example_done_func");

151 152 153 154 155
  if (example_open_tables.records)
    error= 1;
  hash_free(&example_open_tables);
  pthread_mutex_destroy(&example_mutex);

156 157 158
  DBUG_RETURN(0);
}

159 160 161 162 163 164 165

/**
  @brief
  Example of simple lock controls. The "share" it creates is a
  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.
166
*/
167

168
static EXAMPLE_SHARE *get_share(const char *table_name, TABLE *table)
169
{
170
  EXAMPLE_SHARE *share;
171 172 173 174 175 176
  uint length;
  char *tmp_name;

  pthread_mutex_lock(&example_mutex);
  length=(uint) strlen(table_name);

177
  if (!(share=(EXAMPLE_SHARE*) hash_search(&example_open_tables,
178
                                           (uchar*) table_name,
179 180
                                           length)))
  {
181
    if (!(share=(EXAMPLE_SHARE *)
182 183 184
          my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
                          &share, sizeof(*share),
                          &tmp_name, length+1,
185
                          NullS)))
186 187 188 189 190 191 192 193 194
    {
      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);
195
    if (my_hash_insert(&example_open_tables, (uchar*) share))
196 197 198 199 200 201 202 203 204 205
      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:
206
  pthread_mutex_destroy(&share->mutex);
207
  my_free(share, MYF(0));
208 209 210 211

  return NULL;
}

212 213 214

/**
  @brief
215
  Free lock controls. We call this whenever we close a table. If the table had
216
  the last reference to the share, then we free memory associated with it.
217
*/
218

219
static int free_share(EXAMPLE_SHARE *share)
220 221
{
  pthread_mutex_lock(&example_mutex);
222 223
  if (!--share->use_count)
  {
224
    hash_delete(&example_open_tables, (uchar*) share);
225 226
    thr_lock_delete(&share->lock);
    pthread_mutex_destroy(&share->mutex);
227
    my_free(share, MYF(0));
228 229 230 231 232 233
  }
  pthread_mutex_unlock(&example_mutex);

  return 0;
}

234 235 236
static handler* example_create_handler(handlerton *hton,
                                       TABLE_SHARE *table, 
                                       MEM_ROOT *mem_root)
237
{
238
  return new (mem_root) ha_example(hton, table);
239 240
}

241 242
ha_example::ha_example(handlerton *hton, TABLE_SHARE *table_arg)
  :handler(hton, table_arg)
243 244
{}

245

246 247 248 249 250 251 252
/**
  @brief
  If frm_error() is called then we will use this to determine
  the file extensions that exist for the storage engine. This is also
  used by the default rename_table and delete_table method in
  handler.cc.

253 254 255 256 257
  For engines that have two file name extentions (separate meta/index file
  and data file), the order of elements is relevant. First element of engine
  file name extentions array should be meta/index file extention. Second
  element - data file extention. This order is assumed by
  prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued.
258

259
  @see
260 261
  rename_table method in handler.cc and
  delete_table method in handler.cc
262
*/
263

264 265 266 267
static const char *ha_example_exts[] = {
  NullS
};

268
const char **ha_example::bas_ext() const
269 270 271
{
  return ha_example_exts;
}
272

273 274 275

/**
  @brief
276
  Used for opening tables. The name will be the name of the file.
277

278
  @details
279 280 281
  A table is opened when it needs to be opened; e.g. when a request comes in
  for a SELECT on the table (tables are not open and closed for each request,
  they are cached).
282 283 284

  Called from handler.cc by handler::ha_open(). The server opens all tables by
  calling ha_open() which then calls the handler specific open().
285

286
  @see
287
  handler::ha_open() in handler.cc
288
*/
289

290 291 292 293 294 295 296 297 298 299 300
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);
}

301 302 303

/**
  @brief
304
  Closes a table. We call the free_share() function to free any resources
305 306
  that we have allocated in the "shared" structure.

307
  @details
308
  Called from sql_base.cc, sql_select.cc, and table.cc. In sql_select.cc it is
309 310
  only used to close up temporary tables or during the process where a
  temporary table is converted over to being a myisam table.
311

312
  For sql_base.cc look at close_data_tables().
313

314
  @see
315
  sql_base.cc, sql_select.cc and table.cc
316
*/
317

318 319 320 321 322 323
int ha_example::close(void)
{
  DBUG_ENTER("ha_example::close");
  DBUG_RETURN(free_share(share));
}

324 325 326

/**
  @brief
327
  write_row() inserts a row. No extra() hint is given currently if a bulk load
328
  is happening. buf() is a byte array of data. You can use the field
329
  information to extract the data from the native byte array type.
330 331

    @details
332
  Example of this would be:
333
    @code
334 335 336 337
  for (Field **field=table->field ; *field ; field++)
  {
    ...
  }
338
    @endcode
339

340
  See ha_tina.cc for an example of extracting all of the data as strings.
341 342 343 344
  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
345
  case also applies to write_row().
346

347
  Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
348
  sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
349 350 351 352

    @see
  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
353
*/
354

355
int ha_example::write_row(uchar *buf)
356 357
{
  DBUG_ENTER("ha_example::write_row");
358
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
359 360
}

361 362 363

/**
  @brief
364
  Yes, update_row() does what you expect, it updates a row. old_data will have
365
  the previous row record in it, while new_data will have the newest data in it.
366
  Keep in mind that the server can do updates based on ordering if an ORDER BY
367 368 369
  clause was used. Consecutive ordering is not guaranteed.

    @details
370
  Currently new_data will not have an updated auto_increament record, or
371 372
  and updated timestamp field. You can do these for example by doing:
    @code
373 374
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
    table->timestamp_field->set_time();
375 376
  if (table->next_number_field && record == table->record[0])
    update_auto_increment();
377
    @endcode
378 379

  Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
380 381 382

    @see
  sql_select.cc, sql_acl.cc, sql_update.cc and sql_insert.cc
383
*/
384
int ha_example::update_row(const uchar *old_data, uchar *new_data)
385 386 387
{

  DBUG_ENTER("ha_example::update_row");
388
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
389 390
}

391 392 393

/**
  @brief
394 395 396
  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).
397

398
  @details
399
  If you keep a pointer to the last row or can access a primary key it will
400 401
  make doing the deletion quite a bit easier. Keep in mind that the server does
  not guarantee consecutive deletions. ORDER BY clauses can be used.
402

403 404 405 406
  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.
407

408
  @see
409
  sql_acl.cc, sql_udf.cc, sql_delete.cc, sql_insert.cc and sql_select.cc
410
*/
411

412
int ha_example::delete_row(const uchar *buf)
413 414
{
  DBUG_ENTER("ha_example::delete_row");
415
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
416 417
}

418 419 420

/**
  @brief
421 422 423 424
  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.
*/
425

426 427 428 429
int ha_example::index_read_map(uchar *buf, const uchar *key,
                               key_part_map keypart_map __attribute__((unused)),
                               enum ha_rkey_function find_flag
                               __attribute__((unused)))
430 431
{
  DBUG_ENTER("ha_example::index_read");
432
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
433 434
}

435 436 437

/**
  @brief
438 439
  Used to read forward through the index.
*/
440

441
int ha_example::index_next(uchar *buf)
442 443
{
  DBUG_ENTER("ha_example::index_next");
444
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
445 446
}

447 448 449

/**
  @brief
450 451
  Used to read backwards through the index.
*/
452

453
int ha_example::index_prev(uchar *buf)
454 455
{
  DBUG_ENTER("ha_example::index_prev");
456
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
457 458
}

459 460 461

/**
  @brief
462 463
  index_first() asks for the first key in the index.

464 465 466 467 468
    @details
  Called from opt_range.cc, opt_sum.cc, sql_handler.cc, and sql_select.cc.

    @see
  opt_range.cc, opt_sum.cc, sql_handler.cc and sql_select.cc
469
*/
470
int ha_example::index_first(uchar *buf)
471 472
{
  DBUG_ENTER("ha_example::index_first");
473
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
474 475
}

476 477 478

/**
  @brief
479 480
  index_last() asks for the last key in the index.

481 482 483 484 485
    @details
  Called from opt_range.cc, opt_sum.cc, sql_handler.cc, and sql_select.cc.

    @see
  opt_range.cc, opt_sum.cc, sql_handler.cc and sql_select.cc
486
*/
487
int ha_example::index_last(uchar *buf)
488 489
{
  DBUG_ENTER("ha_example::index_last");
490
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
491 492
}

493 494 495

/**
  @brief
496
  rnd_init() is called when the system wants the storage engine to do a table
497
  scan. See the example in the introduction at the top of this file to see when
498 499
  rnd_init() is called.

500
    @details
501 502
  Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
  and sql_update.cc.
503 504 505

    @see
  filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc and sql_update.cc
506
*/
507 508 509
int ha_example::rnd_init(bool scan)
{
  DBUG_ENTER("ha_example::rnd_init");
510
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
511 512
}

513 514 515 516 517
int ha_example::rnd_end()
{
  DBUG_ENTER("ha_example::rnd_end");
  DBUG_RETURN(0);
}
518

519 520 521

/**
  @brief
522 523 524 525 526
  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.

527
    @details
528 529
  Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc,
  and sql_update.cc.
530 531 532

    @see
  filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc and sql_update.cc
533
*/
534
int ha_example::rnd_next(uchar *buf)
535 536 537 538 539
{
  DBUG_ENTER("ha_example::rnd_next");
  DBUG_RETURN(HA_ERR_END_OF_FILE);
}

540 541 542

/**
  @brief
543 544 545
  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:
546
    @code
petr@mysql.com's avatar
petr@mysql.com committed
547
  my_store_ptr(ref, ref_length, current_position);
548
    @endcode
549

550
    @details
551 552 553 554
  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
555 556
  BDB, then it needs to be a primary key.

557 558 559 560
  Called from filesort.cc, sql_select.cc, sql_delete.cc, and sql_update.cc.

    @see
  filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc
561
*/
562
void ha_example::position(const uchar *record)
563 564 565 566 567
{
  DBUG_ENTER("ha_example::position");
  DBUG_VOID_RETURN;
}

568 569 570

/**
  @brief
571 572 573 574
  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.
575 576 577 578 579 580

    @details
  Called from filesort.cc, records.cc, sql_insert.cc, sql_select.cc, and sql_update.cc.

    @see
  filesort.cc, records.cc, sql_insert.cc, sql_select.cc and sql_update.cc
581
*/
582
int ha_example::rnd_pos(uchar *buf, uchar *pos)
583 584
{
  DBUG_ENTER("ha_example::rnd_pos");
585
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
586 587
}

588 589 590

/**
  @brief
591 592
  ::info() is used to return information to the optimizer. See my_base.h for
  the complete description.
593

594 595 596
    @details
  Currently this table handler doesn't implement most of the fields really needed.
  SHOW also makes use of this data.
597

598 599
  You will probably want to have the following in your code:
    @code
600 601
  if (records < 2)
    records = 2;
602
    @endcode
603
  The reason is that the server will optimize for cases of only a single
604 605 606 607
  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:
608 609 610 611 612 613 614 615
    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.

616 617 618 619
  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, and sql_update.cc.
620

621 622 623 624 625
    @see
  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 and sql_update.cc
626
*/
627
int ha_example::info(uint flag)
628 629
{
  DBUG_ENTER("ha_example::info");
630
  DBUG_RETURN(0);
631 632
}

633 634 635

/**
  @brief
636 637 638
  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.
639 640 641

    @see
  ha_innodb.cc
642
*/
643 644 645 646 647 648
int ha_example::extra(enum ha_extra_function operation)
{
  DBUG_ENTER("ha_example::extra");
  DBUG_RETURN(0);
}

649 650 651

/**
  @brief
652 653
  Used to delete all rows in a table, including cases of truncate and cases where
  the optimizer realizes that all rows will be removed as a result of an SQL statement.
654

655
    @details
656
  Called from item_sum.cc by Item_func_group_concat::clear(),
657 658 659 660
  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().
661 662 663 664 665 666 667

    @see
  Item_func_group_concat::clear(), Item_sum_count_distinct::clear() and
  Item_func_group_concat::clear() in item_sum.cc;
  mysql_delete() in sql_delete.cc;
  JOIN::reinit() in sql_select.cc and
  st_select_lex_unit::exec() in sql_union.cc.
668
*/
669 670 671
int ha_example::delete_all_rows()
{
  DBUG_ENTER("ha_example::delete_all_rows");
672
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
673 674
}

675 676 677

/**
  @brief
678 679
  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
680 681 682
  want to go about doing this. Otherwise you should consider calling flock()
  here. Hint: Read the section "locking functions for mysql" in lock.cc to understand
  this.
683

684
    @details
685 686
  Called from lock.cc by lock_external() and unlock_external(). Also called
  from sql_table.cc by copy_data_between_tables().
687 688 689 690 691

    @see
  lock.cc by lock_external() and unlock_external() in lock.cc;
  the section "locking functions for mysql" in lock.cc;
  copy_data_between_tables() in sql_table.cc.
692
*/
693 694 695 696 697 698
int ha_example::external_lock(THD *thd, int lock_type)
{
  DBUG_ENTER("ha_example::external_lock");
  DBUG_RETURN(0);
}

699 700 701

/**
  @brief
702 703 704
  The idea with handler::store_lock() is: The statement decides which locks
  should be needed for the table. For updates/deletes/inserts we get WRITE
  locks, for SELECT... we get read locks.
705

706 707 708
    @details
  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
709
  modify a write lock to a read lock (or some other lock), ignore the
710
  lock (if we don't want to use MySQL table locks at all), or add locks
711 712
  for many tables (like we do when we are using a MERGE handler).

713 714 715
  Berkeley DB, for example, changes all WRITE locks to TL_WRITE_ALLOW_WRITE
  (which signals that we are doing WRITES, but are still allowing other
  readers and writers).
716

717
  When releasing locks, store_lock() is also called. In this case one
718 719 720 721 722 723 724
  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
725
  time). In the future we will probably try to remove this.
726 727

  Called from lock.cc by get_lock_data().
728

serg@janus.mylan's avatar
serg@janus.mylan committed
729 730 731 732 733
    @note
  In this method one should NEVER rely on table->in_use, it may, in fact,
  refer to a different thread! (this happens if get_lock_data() is called
  from mysql_lock_abort_for_thread() function)

734 735
    @see
  get_lock_data() in lock.cc
736
*/
737 738 739 740 741 742 743 744 745 746
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;
}

747 748 749

/**
  @brief
750
  Used to delete a table. By the time delete_table() has been called all
751
  opened references to this table will have been closed (and your globally
752
  shared references released). The variable name will just be the name of
753 754
  the table. You will need to remove any files you have created at this point.

755
    @details
756
  If you do not implement this, the default delete_table() is called from
757
  handler.cc and it will delete all files with the file extensions returned
758 759
  by bas_ext().

760
  Called from handler.cc by delete_table and ha_create_table(). Only used
761 762
  during create if the table_flag HA_DROP_BEFORE_CREATE was specified for
  the storage engine.
763 764 765

    @see
  delete_table and ha_create_table() in handler.cc
766
*/
767 768 769
int ha_example::delete_table(const char *name)
{
  DBUG_ENTER("ha_example::delete_table");
770 771
  /* This is not implemented but we want someone to be able that it works. */
  DBUG_RETURN(0);
772 773
}

774 775 776

/**
  @brief
777
  Renames a table from one name to another via an alter table call.
778

779
  @details
780
  If you do not implement this, the default rename_table() is called from
781
  handler.cc and it will delete all files with the file extensions returned
782 783
  by bas_ext().

784
  Called from sql_table.cc by mysql_rename_table().
785

786
  @see
787
  mysql_rename_table() in sql_table.cc
788
*/
789 790 791
int ha_example::rename_table(const char * from, const char * to)
{
  DBUG_ENTER("ha_example::rename_table ");
792
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
793 794
}

795 796 797

/**
  @brief
798 799 800
  Given a starting key and an ending key, estimate the number of rows that
  will exist between the two keys.

801
  @details
802
  end_key may be empty, in which case determine if start_key matches any rows.
803 804

  Called from opt_range.cc by check_quick_keys().
805

806
  @see
807
  check_quick_keys() in opt_range.cc
808
*/
809 810
ha_rows ha_example::records_in_range(uint inx, key_range *min_key,
                                     key_range *max_key)
811
{
812 813
  DBUG_ENTER("ha_example::records_in_range");
  DBUG_RETURN(10);                         // low number to force index usage
814 815
}

816 817 818

/**
  @brief
819
  create() is called to create a database. The variable name will have the name
820 821
  of the table.

822 823 824 825 826 827 828
  @details
  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 is not necessary. 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
  so.
829 830

  Called from handle.cc by ha_create_table().
831

832
  @see
833
  ha_create_table() in handle.cc
834
*/
835

836
int ha_example::create(const char *name, TABLE *table_arg,
837
                       HA_CREATE_INFO *create_info)
838 839
{
  DBUG_ENTER("ha_example::create");
840 841 842 843
  /*
    This is not implemented but we want someone to be able to see that it
    works.
  */
844
  DBUG_RETURN(0);
845
}
846

847

848
struct st_mysql_storage_engine example_storage_engine=
849
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
850

851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
static ulong srv_enum_var= 0;

const char *enum_var_names[]=
{
  "e1", "e2", NullS
};

TYPELIB enum_var_typelib=
{
  array_elements(enum_var_names) - 1, "enum_var_typelib",
  enum_var_names, NULL
};

static MYSQL_SYSVAR_ENUM(
  enum_var,                       // name
  srv_enum_var,                   // varname
  PLUGIN_VAR_RQCMDARG,            // opt
  "Sample ENUM system variable.", // comment
  NULL,                           // check
  NULL,                           // update
  0,                              // def
  &enum_var_typelib);             // typelib

static struct st_mysql_sys_var* example_system_variables[]= {
  MYSQL_SYSVAR(enum_var),
  NULL
};

acurtis@xiphis.org's avatar
acurtis@xiphis.org committed
879
mysql_declare_plugin(example)
880 881
{
  MYSQL_STORAGE_ENGINE_PLUGIN,
882 883
  &example_storage_engine,
  "EXAMPLE",
884
  "Brian Aker, MySQL AB",
885
  "Example storage engine",
886
  PLUGIN_LICENSE_GPL,
887 888
  example_init_func,                            /* Plugin Init */
  example_done_func,                            /* Plugin Deinit */
acurtis@xiphis.org's avatar
acurtis@xiphis.org committed
889
  0x0001 /* 0.1 */,
890
  NULL,                                         /* status variables */
891
  example_system_variables,                     /* system variables */
892
  NULL                                          /* config options */
893 894
}
mysql_declare_plugin_end;