MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ha_heap.cc
1 /*
2  Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16 
17 
18 #define MYSQL_SERVER 1
19 #include "sql_priv.h"
20 #include "probes_mysql.h"
21 #include "sql_plugin.h"
22 #include "ha_heap.h"
23 #include "heapdef.h"
24 #include "sql_base.h" // enum_tdc_remove_table_type
25 
26 static handler *heap_create_handler(handlerton *hton,
28  MEM_ROOT *mem_root);
29 static int
30 heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
31  HP_CREATE_INFO *hp_create_info);
32 
33 
34 int heap_panic(handlerton *hton, ha_panic_function flag)
35 {
36  return hp_panic(flag);
37 }
38 
39 
40 int heap_init(void *p)
41 {
42  handlerton *heap_hton;
43 
44 #ifdef HAVE_PSI_INTERFACE
45  init_heap_psi_keys();
46 #endif
47 
48  heap_hton= (handlerton *)p;
49  heap_hton->state= SHOW_OPTION_YES;
50  heap_hton->db_type= DB_TYPE_HEAP;
51  heap_hton->create= heap_create_handler;
52  heap_hton->panic= heap_panic;
53  heap_hton->flags= HTON_CAN_RECREATE;
54 
55  return 0;
56 }
57 
58 static handler *heap_create_handler(handlerton *hton,
60  MEM_ROOT *mem_root)
61 {
62  return new (mem_root) ha_heap(hton, table);
63 }
64 
65 
66 /*****************************************************************************
67 ** HEAP tables
68 *****************************************************************************/
69 
70 ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg)
71  :handler(hton, table_arg), file(0), records_changed(0), key_stat_version(0),
72  internal_table(0)
73 {}
74 
75 
76 static const char *ha_heap_exts[] = {
77  NullS
78 };
79 
80 const char **ha_heap::bas_ext() const
81 {
82  return ha_heap_exts;
83 }
84 
85 /*
86  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
87  rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records
88  have been inserted/updated/deleted. delete_all_rows() and table flush cause
89  immediate update.
90 
91  NOTE
92  hash index statistics must be updated when number of table records changes
93  from 0 to non-zero value and vice versa. Otherwise records_in_range may
94  erroneously return 0 and 'range' may miss records.
95 */
96 #define HEAP_STATS_UPDATE_THRESHOLD 10
97 
98 int ha_heap::open(const char *name, int mode, uint test_if_locked)
99 {
100  internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
101  if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
102  {
103  HP_CREATE_INFO create_info;
104  my_bool created_new_share;
105  int rc;
106  file= 0;
107  if (heap_prepare_hp_create_info(table, internal_table, &create_info))
108  goto end;
109  create_info.pin_share= TRUE;
110 
111  rc= heap_create(name, &create_info, &internal_share, &created_new_share);
112  my_free(create_info.keydef);
113  if (rc)
114  goto end;
115 
116  implicit_emptied= test(created_new_share);
117  if (internal_table)
118  file= heap_open_from_share(internal_share, mode);
119  else
120  file= heap_open_from_share_and_register(internal_share, mode);
121 
122  if (!file)
123  {
124  heap_release_share(internal_share, internal_table);
125  goto end;
126  }
127  }
128 
129  ref_length= sizeof(HEAP_PTR);
130  /* Initialize variables for the opened table */
131  set_keys_for_scanning();
132  /*
133  We cannot run update_key_stats() here because we do not have a
134  lock on the table. The 'records' count might just be changed
135  temporarily at this moment and we might get wrong statistics (Bug
136  #10178). Instead we request for update. This will be done in
137  ha_heap::info(), which is always called before key statistics are
138  used.
139  */
140  key_stat_version= file->s->key_stat_version-1;
141 end:
142  return (file ? 0 : 1);
143 }
144 
145 int ha_heap::close(void)
146 {
147  return internal_table ? hp_close(file) : heap_close(file);
148 }
149 
150 
151 /*
152  Create a copy of this table
153 
154  DESCRIPTION
155  Do same as default implementation but use file->s->name instead of
156  table->s->path. This is needed by Windows where the clone() call sees
157  '/'-delimited path in table->s->path, while ha_heap::open() was called
158  with '\'-delimited path.
159 */
160 
161 handler *ha_heap::clone(const char *name, MEM_ROOT *mem_root)
162 {
163  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
164  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
165  HA_OPEN_IGNORE_IF_LOCKED))
166  return new_handler;
167  return NULL; /* purecov: inspected */
168 }
169 
170 
171 /*
172  Compute which keys to use for scanning
173 
174  SYNOPSIS
175  set_keys_for_scanning()
176  no parameter
177 
178  DESCRIPTION
179  Set the bitmap btree_keys, which is used when the upper layers ask
180  which keys to use for scanning. For each btree index the
181  corresponding bit is set.
182 
183  RETURN
184  void
185 */
186 
187 void ha_heap::set_keys_for_scanning(void)
188 {
189  btree_keys.clear_all();
190  for (uint i= 0 ; i < table->s->keys ; i++)
191  {
192  if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
193  btree_keys.set_bit(i);
194  }
195 }
196 
197 
198 void ha_heap::update_key_stats()
199 {
200  for (uint i= 0; i < table->s->keys; i++)
201  {
202  KEY *key=table->key_info+i;
203  if (!key->rec_per_key)
204  continue;
205  if (key->algorithm != HA_KEY_ALG_BTREE)
206  {
207  if (key->flags & HA_NOSAME)
208  key->rec_per_key[key->user_defined_key_parts - 1]= 1;
209  else
210  {
211  ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
212  uint no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
213  if (no_records < 2)
214  no_records= 2;
215  key->rec_per_key[key->user_defined_key_parts - 1]= no_records;
216  }
217  }
218  }
219  records_changed= 0;
220  /* At the end of update_key_stats() we can proudly claim they are OK. */
221  key_stat_version= file->s->key_stat_version;
222 }
223 
224 
225 int ha_heap::write_row(uchar * buf)
226 {
227  int res;
228  ha_statistic_increment(&SSV::ha_write_count);
229  if (table->next_number_field && buf == table->record[0])
230  {
231  if ((res= update_auto_increment()))
232  return res;
233  }
234  res= heap_write(file,buf);
235  if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
236  file->s->records))
237  {
238  /*
239  We can perform this safely since only one writer at the time is
240  allowed on the table.
241  */
242  file->s->key_stat_version++;
243  }
244  return res;
245 }
246 
247 int ha_heap::update_row(const uchar * old_data, uchar * new_data)
248 {
249  int res;
250  ha_statistic_increment(&SSV::ha_update_count);
251  res= heap_update(file,old_data,new_data);
252  if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
253  file->s->records)
254  {
255  /*
256  We can perform this safely since only one writer at the time is
257  allowed on the table.
258  */
259  file->s->key_stat_version++;
260  }
261  return res;
262 }
263 
264 int ha_heap::delete_row(const uchar * buf)
265 {
266  int res;
267  ha_statistic_increment(&SSV::ha_delete_count);
268  res= heap_delete(file,buf);
269  if (!res && table->s->tmp_table == NO_TMP_TABLE &&
270  ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
271  {
272  /*
273  We can perform this safely since only one writer at the time is
274  allowed on the table.
275  */
276  file->s->key_stat_version++;
277  }
278  return res;
279 }
280 
281 int ha_heap::index_read_map(uchar *buf, const uchar *key,
282  key_part_map keypart_map,
283  enum ha_rkey_function find_flag)
284 {
285  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
286  DBUG_ASSERT(inited==INDEX);
287  ha_statistic_increment(&SSV::ha_read_key_count);
288  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
289  table->status = error ? STATUS_NOT_FOUND : 0;
290  MYSQL_INDEX_READ_ROW_DONE(error);
291  return error;
292 }
293 
294 int ha_heap::index_read_last_map(uchar *buf, const uchar *key,
295  key_part_map keypart_map)
296 {
297  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
298  DBUG_ASSERT(inited==INDEX);
299  ha_statistic_increment(&SSV::ha_read_key_count);
300  int error= heap_rkey(file, buf, active_index, key, keypart_map,
301  HA_READ_PREFIX_LAST);
302  table->status= error ? STATUS_NOT_FOUND : 0;
303  MYSQL_INDEX_READ_ROW_DONE(error);
304  return error;
305 }
306 
307 int ha_heap::index_read_idx_map(uchar *buf, uint index, const uchar *key,
308  key_part_map keypart_map,
309  enum ha_rkey_function find_flag)
310 {
311  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
312  ha_statistic_increment(&SSV::ha_read_key_count);
313  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
314  table->status = error ? STATUS_NOT_FOUND : 0;
315  MYSQL_INDEX_READ_ROW_DONE(error);
316  return error;
317 }
318 
319 int ha_heap::index_next(uchar * buf)
320 {
321  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
322  DBUG_ASSERT(inited==INDEX);
323  ha_statistic_increment(&SSV::ha_read_next_count);
324  int error=heap_rnext(file,buf);
325  table->status=error ? STATUS_NOT_FOUND: 0;
326  MYSQL_INDEX_READ_ROW_DONE(error);
327  return error;
328 }
329 
330 int ha_heap::index_prev(uchar * buf)
331 {
332  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
333  DBUG_ASSERT(inited==INDEX);
334  ha_statistic_increment(&SSV::ha_read_prev_count);
335  int error=heap_rprev(file,buf);
336  table->status=error ? STATUS_NOT_FOUND: 0;
337  MYSQL_INDEX_READ_ROW_DONE(error);
338  return error;
339 }
340 
341 int ha_heap::index_first(uchar * buf)
342 {
343  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
344  DBUG_ASSERT(inited==INDEX);
345  ha_statistic_increment(&SSV::ha_read_first_count);
346  int error=heap_rfirst(file, buf, active_index);
347  table->status=error ? STATUS_NOT_FOUND: 0;
348  MYSQL_INDEX_READ_ROW_DONE(error);
349  return error;
350 }
351 
352 int ha_heap::index_last(uchar * buf)
353 {
354  MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
355  DBUG_ASSERT(inited==INDEX);
356  ha_statistic_increment(&SSV::ha_read_last_count);
357  int error=heap_rlast(file, buf, active_index);
358  table->status=error ? STATUS_NOT_FOUND: 0;
359  MYSQL_INDEX_READ_ROW_DONE(error);
360  return error;
361 }
362 
363 int ha_heap::rnd_init(bool scan)
364 {
365  return scan ? heap_scan_init(file) : 0;
366 }
367 
368 int ha_heap::rnd_next(uchar *buf)
369 {
370  MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
371  TRUE);
372  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
373  int error=heap_scan(file, buf);
374  table->status=error ? STATUS_NOT_FOUND: 0;
375  MYSQL_READ_ROW_DONE(error);
376  return error;
377 }
378 
379 int ha_heap::rnd_pos(uchar * buf, uchar *pos)
380 {
381  int error;
382  HEAP_PTR heap_position;
383  MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
384  FALSE);
385  ha_statistic_increment(&SSV::ha_read_rnd_count);
386  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
387  error=heap_rrnd(file, buf, heap_position);
388  table->status=error ? STATUS_NOT_FOUND: 0;
389  MYSQL_READ_ROW_DONE(error);
390  return error;
391 }
392 
393 void ha_heap::position(const uchar *record)
394 {
395  *(HEAP_PTR*) ref= heap_position(file); // Ref is aligned
396 }
397 
398 int ha_heap::info(uint flag)
399 {
400  HEAPINFO hp_info;
401  (void) heap_info(file,&hp_info,flag);
402 
403  errkey= hp_info.errkey;
404  stats.records= hp_info.records;
405  stats.deleted= hp_info.deleted;
406  stats.mean_rec_length= hp_info.reclength;
407  stats.data_file_length= hp_info.data_length;
408  stats.index_file_length= hp_info.index_length;
409  stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
410  stats.delete_length= hp_info.deleted * hp_info.reclength;
411  stats.create_time= (ulong) hp_info.create_time;
412  if (flag & HA_STATUS_AUTO)
413  stats.auto_increment_value= hp_info.auto_increment;
414  /*
415  If info() is called for the first time after open(), we will still
416  have to update the key statistics. Hoping that a table lock is now
417  in place.
418  */
419  if (key_stat_version != file->s->key_stat_version)
420  update_key_stats();
421  return 0;
422 }
423 
424 
425 int ha_heap::extra(enum ha_extra_function operation)
426 {
427  return heap_extra(file,operation);
428 }
429 
430 
432 {
433  return heap_reset(file);
434 }
435 
436 
438 {
439  heap_clear(file);
440  if (table->s->tmp_table == NO_TMP_TABLE)
441  {
442  /*
443  We can perform this safely since only one writer at the time is
444  allowed on the table.
445  */
446  file->s->key_stat_version++;
447  }
448  return 0;
449 }
450 
451 
453 {
454  int error= delete_all_rows();
455  return error ? error : reset_auto_increment(0);
456 }
457 
458 
459 int ha_heap::reset_auto_increment(ulonglong value)
460 {
461  file->s->auto_increment= value;
462  return 0;
463 }
464 
465 
466 int ha_heap::external_lock(THD *thd, int lock_type)
467 {
468  return 0; // No external locking
469 }
470 
471 
472 /*
473  Disable indexes.
474 
475  SYNOPSIS
476  disable_indexes()
477  mode mode of operation:
478  HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
479  HA_KEY_SWITCH_ALL disable all keys
480  HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
481  HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
482 
483  DESCRIPTION
484  Disable indexes and clear keys to use for scanning.
485 
486  IMPLEMENTATION
487  HA_KEY_SWITCH_NONUNIQ is not implemented.
488  HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
489  HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
490 
491  RETURN
492  0 ok
493  HA_ERR_WRONG_COMMAND mode not implemented.
494 */
495 
496 int ha_heap::disable_indexes(uint mode)
497 {
498  int error;
499 
500  if (mode == HA_KEY_SWITCH_ALL)
501  {
502  if (!(error= heap_disable_indexes(file)))
503  set_keys_for_scanning();
504  }
505  else
506  {
507  /* mode not implemented */
508  error= HA_ERR_WRONG_COMMAND;
509  }
510  return error;
511 }
512 
513 
514 /*
515  Enable indexes.
516 
517  SYNOPSIS
518  enable_indexes()
519  mode mode of operation:
520  HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
521  HA_KEY_SWITCH_ALL enable all keys
522  HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
523  HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
524 
525  DESCRIPTION
526  Enable indexes and set keys to use for scanning.
527  The indexes might have been disabled by disable_index() before.
528  The function works only if both data and indexes are empty,
529  since the heap storage engine cannot repair the indexes.
530  To be sure, call handler::delete_all_rows() before.
531 
532  IMPLEMENTATION
533  HA_KEY_SWITCH_NONUNIQ is not implemented.
534  HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
535  HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
536 
537  RETURN
538  0 ok
539  HA_ERR_CRASHED data or index is non-empty. Delete all rows and retry.
540  HA_ERR_WRONG_COMMAND mode not implemented.
541 */
542 
543 int ha_heap::enable_indexes(uint mode)
544 {
545  int error;
546 
547  if (mode == HA_KEY_SWITCH_ALL)
548  {
549  if (!(error= heap_enable_indexes(file)))
550  set_keys_for_scanning();
551  }
552  else
553  {
554  /* mode not implemented */
555  error= HA_ERR_WRONG_COMMAND;
556  }
557  return error;
558 }
559 
560 
561 /*
562  Test if indexes are disabled.
563 
564  SYNOPSIS
565  indexes_are_disabled()
566  no parameters
567 
568  RETURN
569  0 indexes are not disabled
570  1 all indexes are disabled
571  [2 non-unique indexes are disabled - NOT YET IMPLEMENTED]
572 */
573 
574 int ha_heap::indexes_are_disabled(void)
575 {
576  return heap_indexes_are_disabled(file);
577 }
578 
580  THR_LOCK_DATA **to,
581  enum thr_lock_type lock_type)
582 {
583  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
584  file->lock.type=lock_type;
585  *to++= &file->lock;
586  return to;
587 }
588 
589 /*
590  We have to ignore ENOENT entries as the HEAP table is created on open and
591  not when doing a CREATE on the table.
592 */
593 
594 int ha_heap::delete_table(const char *name)
595 {
596  int error= heap_delete_table(name);
597  return error == ENOENT ? 0 : error;
598 }
599 
600 
601 void ha_heap::drop_table(const char *name)
602 {
603  file->s->delete_on_close= 1;
604  close();
605 }
606 
607 
608 int ha_heap::rename_table(const char * from, const char * to)
609 {
610  return heap_rename(from,to);
611 }
612 
613 
614 ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
615  key_range *max_key)
616 {
617  KEY *key=table->key_info+inx;
618  if (key->algorithm == HA_KEY_ALG_BTREE)
619  return hp_rb_records_in_range(file, inx, min_key, max_key);
620 
621  if (!min_key || !max_key ||
622  min_key->length != max_key->length ||
623  min_key->length != key->key_length ||
624  min_key->flag != HA_READ_KEY_EXACT ||
625  max_key->flag != HA_READ_AFTER_KEY)
626  return HA_POS_ERROR; // Can only use exact keys
627 
628  if (stats.records <= 1)
629  return stats.records;
630 
631  /* Assert that info() did run. We need current statistics here. */
632  DBUG_ASSERT(key_stat_version == file->s->key_stat_version);
633  return key->rec_per_key[key->user_defined_key_parts - 1];
634 }
635 
636 
637 static int
638 heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
639  HP_CREATE_INFO *hp_create_info)
640 {
641  uint key, parts, mem_per_row= 0, keys= table_arg->s->keys;
642  uint auto_key= 0, auto_key_type= 0;
643  ha_rows max_rows;
644  HP_KEYDEF *keydef;
645  HA_KEYSEG *seg;
646  TABLE_SHARE *share= table_arg->s;
647  bool found_real_auto_increment= 0;
648 
649  memset(hp_create_info, 0, sizeof(*hp_create_info));
650 
651  for (key= parts= 0; key < keys; key++)
652  parts+= table_arg->key_info[key].user_defined_key_parts;
653 
654  if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
655  parts * sizeof(HA_KEYSEG),
656  MYF(MY_WME))))
657  return my_errno;
658  seg= reinterpret_cast<HA_KEYSEG*>(keydef + keys);
659  for (key= 0; key < keys; key++)
660  {
661  KEY *pos= table_arg->key_info+key;
662  KEY_PART_INFO *key_part= pos->key_part;
663  KEY_PART_INFO *key_part_end= key_part + pos->user_defined_key_parts;
664 
665  keydef[key].keysegs= (uint) pos->user_defined_key_parts;
666  keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
667  keydef[key].seg= seg;
668 
669  switch (pos->algorithm) {
670  case HA_KEY_ALG_UNDEF:
671  case HA_KEY_ALG_HASH:
672  keydef[key].algorithm= HA_KEY_ALG_HASH;
673  mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
674  break;
675  case HA_KEY_ALG_BTREE:
676  keydef[key].algorithm= HA_KEY_ALG_BTREE;
677  mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
678  break;
679  default:
680  DBUG_ASSERT(0); // cannot happen
681  }
682 
683  for (; key_part != key_part_end; key_part++, seg++)
684  {
685  Field *field= key_part->field;
686 
687  if (pos->algorithm == HA_KEY_ALG_BTREE)
688  seg->type= field->key_type();
689  else
690  {
691  if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
692  seg->type != HA_KEYTYPE_VARTEXT1 &&
693  seg->type != HA_KEYTYPE_VARTEXT2 &&
694  seg->type != HA_KEYTYPE_VARBINARY1 &&
695  seg->type != HA_KEYTYPE_VARBINARY2)
696  seg->type= HA_KEYTYPE_BINARY;
697  }
698  seg->start= (uint) key_part->offset;
699  seg->length= (uint) key_part->length;
700  seg->flag= key_part->key_part_flag;
701 
702  if (field->flags & (ENUM_FLAG | SET_FLAG))
703  seg->charset= &my_charset_bin;
704  else
705  seg->charset= field->charset_for_protocol();
706  if (field->real_maybe_null())
707  {
708  seg->null_bit= field->null_bit;
709  seg->null_pos= field->null_offset();
710  }
711  else
712  {
713  seg->null_bit= 0;
714  seg->null_pos= 0;
715  }
716  if (field->flags & AUTO_INCREMENT_FLAG &&
717  table_arg->found_next_number_field &&
718  key == share->next_number_index)
719  {
720  /*
721  Store key number and type for found auto_increment key
722  We have to store type as seg->type can differ from it
723  */
724  auto_key= key+ 1;
725  auto_key_type= field->key_type();
726  }
727  }
728  }
729  mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
730  if (table_arg->found_next_number_field)
731  {
732  keydef[share->next_number_index].flag|= HA_AUTO_KEY;
733  found_real_auto_increment= share->next_number_key_offset == 0;
734  }
735  hp_create_info->auto_key= auto_key;
736  hp_create_info->auto_key_type= auto_key_type;
737  hp_create_info->max_table_size=current_thd->variables.max_heap_table_size;
738  hp_create_info->with_auto_increment= found_real_auto_increment;
739  hp_create_info->internal_table= internal_table;
740 
741  max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row);
742  if (share->max_rows && share->max_rows < max_rows)
743  max_rows= share->max_rows;
744 
745  hp_create_info->max_records= (ulong) max_rows;
746  hp_create_info->min_records= (ulong) share->min_rows;
747  hp_create_info->keys= share->keys;
748  hp_create_info->reclength= share->reclength;
749  hp_create_info->keydef= keydef;
750  return 0;
751 }
752 
753 
754 int ha_heap::create(const char *name, TABLE *table_arg,
755  HA_CREATE_INFO *create_info)
756 {
757  int error;
758  my_bool created;
759  HP_CREATE_INFO hp_create_info;
760 
761  error= heap_prepare_hp_create_info(table_arg, internal_table,
762  &hp_create_info);
763  if (error)
764  return error;
765  hp_create_info.auto_increment= (create_info->auto_increment_value ?
766  create_info->auto_increment_value - 1 : 0);
767  error= heap_create(name, &hp_create_info, &internal_share, &created);
768  my_free(hp_create_info.keydef);
769  DBUG_ASSERT(file == 0);
770  return (error);
771 }
772 
773 
774 void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
775 {
776  table->file->info(HA_STATUS_AUTO);
777  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
778  create_info->auto_increment_value= stats.auto_increment_value;
779 }
780 
781 void ha_heap::get_auto_increment(ulonglong offset, ulonglong increment,
782  ulonglong nb_desired_values,
783  ulonglong *first_value,
784  ulonglong *nb_reserved_values)
785 {
786  ha_heap::info(HA_STATUS_AUTO);
787  *first_value= stats.auto_increment_value;
788  /* such table has only table-level locking so reserves up to +inf */
789  *nb_reserved_values= ULONGLONG_MAX;
790 }
791 
792 
794  uint table_changes)
795 {
796  /* Check that auto_increment value was not changed */
797  if ((info->used_fields & HA_CREATE_USED_AUTO &&
798  info->auto_increment_value != 0) ||
799  table_changes == IS_EQUAL_NO ||
800  table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
801  return COMPATIBLE_DATA_NO;
802  return COMPATIBLE_DATA_YES;
803 }
804 
805 struct st_mysql_storage_engine heap_storage_engine=
806 { MYSQL_HANDLERTON_INTERFACE_VERSION };
807 
808 mysql_declare_plugin(heap)
809 {
810  MYSQL_STORAGE_ENGINE_PLUGIN,
811  &heap_storage_engine,
812  "MEMORY",
813  "MySQL AB",
814  "Hash based, stored in memory, useful for temporary tables",
815  PLUGIN_LICENSE_GPL,
816  heap_init,
817  NULL,
818  0x0100, /* 1.0 */
819  NULL, /* status variables */
820  NULL, /* system variables */
821  NULL, /* config options */
822  0, /* flags */
823 }
824 mysql_declare_plugin_end;