Drizzled Public API Documentation

ha_heap.cc
1 /* Copyright (C) 2000-2006 MySQL AB
2 
3  This program is free software; you can redistribute it and/or modify
4  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  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "heap_priv.h"
17 #include <drizzled/error.h>
18 #include <drizzled/table.h>
19 #include <drizzled/session.h>
20 #include <drizzled/field/varstring.h>
21 #include <drizzled/plugin/daemon.h>
22 #include <drizzled/plugin/storage_engine.h>
23 #include <drizzled/util/test.h>
24 #include <drizzled/session/table_messages.h>
25 #include <drizzled/statistics_variables.h>
26 #include <drizzled/system_variables.h>
27 
28 #include <boost/thread/mutex.hpp>
29 
30 #include "heap.h"
31 #include "ha_heap.h"
32 
33 #include <string>
34 
35 using namespace drizzled;
36 using namespace std;
37 
38 static const string engine_name("MEMORY");
39 
40 boost::mutex THR_LOCK_heap;
41 
42 static const char *ha_heap_exts[] = {
43  NULL
44 };
45 
46 class HeapEngine : public plugin::StorageEngine
47 {
48 public:
49  explicit HeapEngine(string name_arg) :
50  plugin::StorageEngine(name_arg,
51  HTON_STATS_RECORDS_IS_EXACT |
52  HTON_NULL_IN_KEY |
53  HTON_FAST_KEY_READ |
54  HTON_NO_BLOBS |
55  HTON_HAS_RECORDS |
56  HTON_SKIP_STORE_LOCK |
57  HTON_TEMPORARY_ONLY)
58  {
59  }
60 
61  virtual ~HeapEngine()
62  {
63  hp_panic(HA_PANIC_CLOSE);
64  }
65 
66  virtual Cursor *create(Table &table)
67  {
68  return new ha_heap(*this, table);
69  }
70 
71  const char **bas_ext() const
72  {
73  return ha_heap_exts;
74  }
75 
76  drizzled::message::Table::Index::IndexType default_index_type() const
77  {
78  return drizzled::message::Table::Index::HASH;
79  }
80 
81  int doCreateTable(Session &session,
82  Table &table_arg,
83  const identifier::Table &identifier,
84  const message::Table &create_proto);
85 
86  /* For whatever reason, internal tables can be created by Cursor::open()
87  for MEMORY.
88  Instead of diving down a rat hole, let's just cry ourselves to sleep
89  at night with this odd hackish workaround.
90  */
91  int heap_create_table(Session *session, const char *table_name,
92  Table *table_arg,
93  bool internal_table,
94  const message::Table &create_proto,
95  HP_SHARE **internal_share);
96 
97  int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
98 
99  int doDropTable(Session&, const identifier::Table &identifier);
100 
101  int doGetTableDefinition(Session& session,
102  const identifier::Table &identifier,
103  message::Table &table_message);
104 
105  uint32_t max_supported_keys() const { return MAX_KEY; }
106  uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
107 
108  uint32_t index_flags(enum ha_key_alg ) const
109  {
110  return ( HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
111  }
112 
113  bool doDoesTableExist(Session& session, const identifier::Table &identifier);
114  void doGetTableIdentifiers(CachedDirectory &directory,
115  const identifier::Schema &schema_identifier,
116  identifier::table::vector &set_of_identifiers);
117 };
118 
119 void HeapEngine::doGetTableIdentifiers(CachedDirectory&,
120  const identifier::Schema&,
121  identifier::table::vector&)
122 {
123 }
124 
125 bool HeapEngine::doDoesTableExist(Session& session, const identifier::Table &identifier)
126 {
127  return session.getMessageCache().doesTableMessageExist(identifier);
128 }
129 
130 int HeapEngine::doGetTableDefinition(Session &session,
131  const identifier::Table &identifier,
132  message::Table &table_proto)
133 {
134  if (session.getMessageCache().getTableMessage(identifier, table_proto))
135  return EEXIST;
136 
137  return ENOENT;
138 }
139 /*
140  We have to ignore ENOENT entries as the MEMORY table is created on open and
141  not when doing a CREATE on the table.
142 */
143 int HeapEngine::doDropTable(Session &session, const identifier::Table &identifier)
144 {
145  session.getMessageCache().removeTableMessage(identifier);
146 
147  int error= heap_delete_table(identifier.getPath().c_str());
148 
149  if (error == ENOENT)
150  error= 0;
151 
152  return error;
153 }
154 
155 static HeapEngine *heap_storage_engine= NULL;
156 
157 static int heap_init(module::Context &context)
158 {
159  heap_storage_engine= new HeapEngine(engine_name);
160  context.add(heap_storage_engine);
161  return 0;
162 }
163 
164 
165 /*****************************************************************************
166 ** MEMORY tables
167 *****************************************************************************/
168 
169 ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
170  Table &table_arg)
171  :Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
172  internal_table(0)
173 {}
174 
175 /*
176  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
177  rec_per_key) after 1/MEMORY_STATS_UPDATE_THRESHOLD fraction of table records
178  have been inserted/updated/deleted. delete_all_rows() and table flush cause
179  immediate update.
180 
181  NOTE
182  hash index statistics must be updated when number of table records changes
183  from 0 to non-zero value and vice versa. Otherwise records_in_range may
184  erroneously return 0 and 'range' may miss records.
185 */
186 #define MEMORY_STATS_UPDATE_THRESHOLD 10
187 
188 int ha_heap::doOpen(const drizzled::identifier::Table &identifier, int mode, uint32_t test_if_locked)
189 {
190  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(identifier.getPath().c_str(), mode)) && errno == ENOENT))
191  {
192  internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
193  file= 0;
194  HP_SHARE *internal_share= NULL;
195  message::Table create_proto;
196 
197  if (not heap_storage_engine->heap_create_table(getTable()->in_use,
198  identifier.getPath().c_str(),
199  getTable(),
200  internal_table,
201  create_proto,
202  &internal_share))
203  {
204  file= internal_table ?
205  heap_open_from_share(internal_share, mode) :
206  heap_open_from_share_and_register(internal_share, mode);
207  if (!file)
208  {
209  /* Couldn't open table; Remove the newly created table */
210  THR_LOCK_heap.lock();
211  hp_free(internal_share);
212  THR_LOCK_heap.unlock();
213  }
214  }
215  }
216  ref_length= sizeof(HEAP_PTR);
217  if (file)
218  {
219  /* Initialize variables for the opened table */
220  set_keys_for_scanning();
221  /*
222  We cannot run update_key_stats() here because we do not have a
223  lock on the table. The 'records' count might just be changed
224  temporarily at this moment and we might get wrong statistics (Bug
225  #10178). Instead we request for update. This will be done in
226  ha_heap::info(), which is always called before key statistics are
227  used.
228  */
229  key_stat_version= file->getShare()->key_stat_version - 1;
230  }
231  return file ? 0 : 1;
232 }
233 
234 int ha_heap::close(void)
235 {
236  return internal_table ? hp_close(file) : heap_close(file);
237 }
238 
239 
240 /*
241  Create a copy of this table
242 
243  DESCRIPTION
244  Do same as default implementation but use file->s->name instead of
245  table->getShare()->path. This is needed by Windows where the clone() call sees
246  '/'-delimited path in table->getShare()->path, while ha_peap::open() was called
247  with '\'-delimited path.
248 */
249 
250 Cursor *ha_heap::clone(memory::Root *)
251 {
252  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
253  identifier::Table identifier(*getTable());
254 
255  if (new_handler && !new_handler->ha_open(identifier, getTable()->db_stat,
256  HA_OPEN_IGNORE_IF_LOCKED))
257  return new_handler;
258  return NULL;
259 }
260 
261 
262 const char *ha_heap::index_type(uint32_t )
263 {
264  return ("HASH");
265 }
266 
267 
268 /*
269  Compute which keys to use for scanning
270 
271  SYNOPSIS
272  set_keys_for_scanning()
273  no parameter
274 
275  DESCRIPTION
276  Set the bitmap btree_keys, which is used when the upper layers ask
277  which keys to use for scanning. For each btree index the
278  corresponding bit is set.
279 
280  RETURN
281  void
282 */
283 
284 void ha_heap::set_keys_for_scanning(void)
285 {
286 }
287 
288 
289 void ha_heap::update_key_stats()
290 {
291  for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
292  {
293  KeyInfo *key= &getTable()->key_info[i];
294 
295  if (!key->rec_per_key)
296  continue;
297 
298  {
299  if (key->flags & HA_NOSAME)
300  key->rec_per_key[key->key_parts-1]= 1;
301  else
302  {
303  ha_rows hash_buckets= file->getShare()->keydef[i].hash_buckets;
304  uint32_t no_records= hash_buckets ? (uint) (file->getShare()->records/hash_buckets) : 2;
305  if (no_records < 2)
306  no_records= 2;
307  key->rec_per_key[key->key_parts-1]= no_records;
308  }
309  }
310  }
311  records_changed= 0;
312  /* At the end of update_key_stats() we can proudly claim they are OK. */
313  key_stat_version= file->getShare()->key_stat_version;
314 }
315 
316 
317 int ha_heap::doInsertRecord(unsigned char * buf)
318 {
319  int res;
320  if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
321  {
322  if ((res= update_auto_increment()))
323  return res;
324  }
325  res= heap_write(file,buf);
326  if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
327  file->getShare()->records))
328  {
329  /*
330  We can perform this safely since only one writer at the time is
331  allowed on the table.
332  */
333  file->getShare()->key_stat_version++;
334  }
335  return res;
336 }
337 
338 int ha_heap::doUpdateRecord(const unsigned char * old_data, unsigned char * new_data)
339 {
340  int res;
341 
342  res= heap_update(file,old_data,new_data);
343  if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
344  file->getShare()->records)
345  {
346  /*
347  We can perform this safely since only one writer at the time is
348  allowed on the table.
349  */
350  file->getShare()->key_stat_version++;
351  }
352  return res;
353 }
354 
355 int ha_heap::doDeleteRecord(const unsigned char * buf)
356 {
357  int res;
358 
359  res= heap_delete(file,buf);
360  if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
361  ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
362  {
363  /*
364  We can perform this safely since only one writer at the time is
365  allowed on the table.
366  */
367  file->getShare()->key_stat_version++;
368  }
369  return res;
370 }
371 
372 int ha_heap::index_read_map(unsigned char *buf, const unsigned char *key,
373  key_part_map keypart_map,
374  enum ha_rkey_function find_flag)
375 {
376  assert(inited==INDEX);
377  ha_statistic_increment(&system_status_var::ha_read_key_count);
378  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
379  getTable()->status = error ? STATUS_NOT_FOUND : 0;
380  return error;
381 }
382 
383 int ha_heap::index_read_last_map(unsigned char *buf, const unsigned char *key,
384  key_part_map keypart_map)
385 {
386  assert(inited==INDEX);
387  ha_statistic_increment(&system_status_var::ha_read_key_count);
388  int error= heap_rkey(file, buf, active_index, key, keypart_map,
389  HA_READ_PREFIX_LAST);
390  getTable()->status= error ? STATUS_NOT_FOUND : 0;
391  return error;
392 }
393 
394 int ha_heap::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
395  key_part_map keypart_map,
396  enum ha_rkey_function find_flag)
397 {
398  ha_statistic_increment(&system_status_var::ha_read_key_count);
399  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
400  getTable()->status = error ? STATUS_NOT_FOUND : 0;
401  return error;
402 }
403 
404 int ha_heap::index_next(unsigned char * buf)
405 {
406  assert(inited==INDEX);
407  ha_statistic_increment(&system_status_var::ha_read_next_count);
408  int error=heap_rnext(file,buf);
409  getTable()->status=error ? STATUS_NOT_FOUND: 0;
410  return error;
411 }
412 
413 int ha_heap::index_prev(unsigned char * buf)
414 {
415  assert(inited==INDEX);
416  ha_statistic_increment(&system_status_var::ha_read_prev_count);
417  int error=heap_rprev(file,buf);
418  getTable()->status=error ? STATUS_NOT_FOUND: 0;
419  return error;
420 }
421 
422 int ha_heap::index_first(unsigned char * buf)
423 {
424  assert(inited==INDEX);
425  ha_statistic_increment(&system_status_var::ha_read_first_count);
426  int error=heap_rfirst(file, buf, active_index);
427  getTable()->status=error ? STATUS_NOT_FOUND: 0;
428  return error;
429 }
430 
431 int ha_heap::index_last(unsigned char * buf)
432 {
433  assert(inited==INDEX);
434  ha_statistic_increment(&system_status_var::ha_read_last_count);
435  int error=heap_rlast(file, buf, active_index);
436  getTable()->status=error ? STATUS_NOT_FOUND: 0;
437  return error;
438 }
439 
441 {
442  return scan ? heap_scan_init(file) : 0;
443 }
444 
445 int ha_heap::rnd_next(unsigned char *buf)
446 {
447  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
448  int error=heap_scan(file, buf);
449  getTable()->status=error ? STATUS_NOT_FOUND: 0;
450  return error;
451 }
452 
453 int ha_heap::rnd_pos(unsigned char * buf, unsigned char *pos)
454 {
455  int error;
456  HEAP_PTR heap_position;
457  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
458  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
459  error=heap_rrnd(file, buf, heap_position);
460  getTable()->status=error ? STATUS_NOT_FOUND: 0;
461  return error;
462 }
463 
464 void ha_heap::position(const unsigned char *)
465 {
466  *(HEAP_PTR*) ref= heap_position(file); // Ref is aligned
467 }
468 
469 int ha_heap::info(uint32_t flag)
470 {
471  HEAPINFO hp_info;
472  (void) heap_info(file,&hp_info,flag);
473 
474  errkey= hp_info.errkey;
475  stats.records= hp_info.records;
476  stats.deleted= hp_info.deleted;
477  stats.mean_rec_length= hp_info.reclength;
478  stats.data_file_length= hp_info.data_length;
479  stats.index_file_length= hp_info.index_length;
480  stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
481  stats.delete_length= hp_info.deleted * hp_info.reclength;
482  if (flag & HA_STATUS_AUTO)
483  stats.auto_increment_value= hp_info.auto_increment;
484  /*
485  If info() is called for the first time after open(), we will still
486  have to update the key statistics. Hoping that a table lock is now
487  in place.
488  */
489  if (key_stat_version != file->getShare()->key_stat_version)
490  update_key_stats();
491  return 0;
492 }
493 
494 int ha_heap::extra(enum ha_extra_function operation)
495 {
496  return heap_extra(file,operation);
497 }
498 
499 
501 {
502  return heap_reset(file);
503 }
504 
505 
507 {
508  heap_clear(file);
509  if (getTable()->getShare()->getType() == message::Table::STANDARD)
510  {
511  /*
512  We can perform this safely since only one writer at the time is
513  allowed on the table.
514  */
515  file->getShare()->key_stat_version++;
516  }
517  return 0;
518 }
519 
520 /*
521  Disable indexes.
522 
523  SYNOPSIS
524  disable_indexes()
525  mode mode of operation:
526  HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
527  HA_KEY_SWITCH_ALL disable all keys
528  HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
529  HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
530 
531  DESCRIPTION
532  Disable indexes and clear keys to use for scanning.
533 
534  IMPLEMENTATION
535  HA_KEY_SWITCH_NONUNIQ is not implemented.
536  HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
537  HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
538 
539  RETURN
540  0 ok
541  HA_ERR_WRONG_COMMAND mode not implemented.
542 */
543 
544 int ha_heap::disable_indexes(uint32_t mode)
545 {
546  int error;
547 
548  if (mode == HA_KEY_SWITCH_ALL)
549  {
550  if (!(error= heap_disable_indexes(file)))
551  set_keys_for_scanning();
552  }
553  else
554  {
555  /* mode not implemented */
556  error= HA_ERR_WRONG_COMMAND;
557  }
558  return error;
559 }
560 
561 
562 /*
563  Enable indexes.
564 
565  SYNOPSIS
566  enable_indexes()
567  mode mode of operation:
568  HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
569  HA_KEY_SWITCH_ALL enable all keys
570  HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
571  HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
572 
573  DESCRIPTION
574  Enable indexes and set keys to use for scanning.
575  The indexes might have been disabled by disable_index() before.
576  The function works only if both data and indexes are empty,
577  since the heap storage engine cannot repair the indexes.
578  To be sure, call Cursor::delete_all_rows() before.
579 
580  IMPLEMENTATION
581  HA_KEY_SWITCH_NONUNIQ is not implemented.
582  HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
583  HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
584 
585  RETURN
586  0 ok
587  HA_ERR_CRASHED data or index is non-empty. Delete all rows and retry.
588  HA_ERR_WRONG_COMMAND mode not implemented.
589 */
590 
591 int ha_heap::enable_indexes(uint32_t mode)
592 {
593  int error;
594 
595  if (mode == HA_KEY_SWITCH_ALL)
596  {
597  if (!(error= heap_enable_indexes(file)))
598  set_keys_for_scanning();
599  }
600  else
601  {
602  /* mode not implemented */
603  error= HA_ERR_WRONG_COMMAND;
604  }
605  return error;
606 }
607 
608 
609 /*
610  Test if indexes are disabled.
611 
612  SYNOPSIS
613  indexes_are_disabled()
614  no parameters
615 
616  RETURN
617  0 indexes are not disabled
618  1 all indexes are disabled
619  [2 non-unique indexes are disabled - NOT YET IMPLEMENTED]
620 */
621 
622 int ha_heap::indexes_are_disabled()
623 {
624  return heap_indexes_are_disabled(file);
625 }
626 
627 void ha_heap::drop_table()
628 {
629  file->getShare()->delete_on_close= 1;
630  close();
631 }
632 
633 
634 int HeapEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
635 {
636  session.getMessageCache().renameTableMessage(from, to);
637  return heap_rename(from.getPath().c_str(), to.getPath().c_str());
638 }
639 
640 
641 ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
642  key_range *max_key)
643 {
644  KeyInfo *key= &getTable()->key_info[inx];
645 
646  if (!min_key || !max_key ||
647  min_key->length != max_key->length ||
648  min_key->length != key->key_length ||
649  min_key->flag != HA_READ_KEY_EXACT ||
650  max_key->flag != HA_READ_AFTER_KEY)
651  return HA_POS_ERROR; // Can only use exact keys
652 
653  if (stats.records <= 1)
654  return stats.records;
655 
656  /* Assert that info() did run. We need current statistics here. */
657  assert(key_stat_version == file->getShare()->key_stat_version);
658  return key->rec_per_key[key->key_parts-1];
659 }
660 
661 int HeapEngine::doCreateTable(Session &session,
662  Table &table_arg,
663  const identifier::Table &identifier,
664  const message::Table& create_proto)
665 {
666  int error;
667  HP_SHARE *internal_share;
668  const char *table_name= identifier.getPath().c_str();
669 
670  error= heap_create_table(&session, table_name, &table_arg,
671  false,
672  create_proto,
673  &internal_share);
674 
675  if (error == 0)
676  {
677  session.getMessageCache().storeTableMessage(identifier, create_proto);
678  }
679 
680  return error;
681 }
682 
683 
684 int HeapEngine::heap_create_table(Session *session, const char *table_name,
685  Table *table_arg,
686  bool internal_table,
687  const message::Table &create_proto,
688  HP_SHARE **internal_share)
689 {
690  uint32_t key, parts, mem_per_row_keys= 0;
691  uint32_t keys= table_arg->getShare()->sizeKeys();
692  uint32_t auto_key= 0, auto_key_type= 0;
693  uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
694  uint32_t column_count= table_arg->getShare()->sizeFields();
695  std::vector<HP_KEYDEF> keydef;
696  int error;
697  bool found_real_auto_increment= 0;
698 
699  /*
700  * We cannot create tables with more rows than UINT32_MAX. This is a
701  * limitation of the HEAP engine. Here, since TableShare::getMaxRows()
702  * can return a number more than that, we trap it here instead of casting
703  * to a truncated integer.
704  */
705  uint64_t num_rows= table_arg->getShare()->getMaxRows();
706  if (num_rows > UINT32_MAX)
707  return -1;
708 
709  for (key= parts= 0; key < keys; key++)
710  parts+= table_arg->key_info[key].key_parts;
711 
712  keydef.resize(keys);
713  std::vector<HA_KEYSEG> seg_buffer;
714  seg_buffer.resize(parts);
715  HA_KEYSEG *seg= &seg_buffer[0];
716 
717  for (key= 0; key < keys; key++)
718  {
719  KeyInfo *pos= &table_arg->key_info[key];
720  KeyPartInfo *key_part= pos->key_part;
721  KeyPartInfo *key_part_end= key_part + pos->key_parts;
722 
723  keydef[key].keysegs= (uint) pos->key_parts;
724  keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
725  keydef[key].seg= seg;
726 
727  mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
728 
729  for (; key_part != key_part_end; key_part++, seg++)
730  {
731  Field *field= key_part->field;
732 
733  {
734  if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
735  seg->type != HA_KEYTYPE_VARTEXT1 &&
736  seg->type != HA_KEYTYPE_VARTEXT2 &&
737  seg->type != HA_KEYTYPE_VARBINARY1 &&
738  seg->type != HA_KEYTYPE_VARBINARY2)
739  seg->type= HA_KEYTYPE_BINARY;
740  }
741  seg->start= (uint) key_part->offset;
742  seg->length= (uint) key_part->length;
743  seg->flag= key_part->key_part_flag;
744 
745  next_field_pos= seg->start + seg->length;
746  if (field->type() == DRIZZLE_TYPE_VARCHAR)
747  {
748  next_field_pos+= (uint8_t)(((Field_varstring*)field)->pack_length_no_ptr());
749  }
750 
751  if (next_field_pos > key_part_size) {
752  key_part_size= next_field_pos;
753  }
754 
755  if (field->flags & ENUM_FLAG)
756  seg->charset= &my_charset_bin;
757  else
758  seg->charset= field->charset();
759  if (field->null_ptr)
760  {
761  seg->null_bit= field->null_bit;
762  seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->getInsertRecord());
763  }
764  else
765  {
766  seg->null_bit= 0;
767  seg->null_pos= 0;
768  }
769  if (field->flags & AUTO_INCREMENT_FLAG &&
770  table_arg->found_next_number_field &&
771  key == table_arg->getShare()->next_number_index)
772  {
773  /*
774  Store key number and type for found auto_increment key
775  We have to store type as seg->type can differ from it
776  */
777  auto_key= key+ 1;
778  auto_key_type= field->key_type();
779  }
780  if ((uint)field->position() + 1 > max_key_fieldnr)
781  {
782  /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
783  max_key_fieldnr= field->position() + 1;
784  }
785  }
786  }
787 
788  if (key_part_size < table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3))
789  {
790  /* Make sure to include null fields regardless of the presense of keys */
791  key_part_size = table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3);
792  }
793 
794 
795 
796  if (table_arg->found_next_number_field)
797  {
798  keydef[table_arg->getShare()->next_number_index].flag|= HA_AUTO_KEY;
799  found_real_auto_increment= table_arg->getShare()->next_number_key_offset == 0;
800  }
801  HP_CREATE_INFO hp_create_info;
802  hp_create_info.auto_key= auto_key;
803  hp_create_info.auto_key_type= auto_key_type;
804  hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
805  create_proto.options().auto_increment_value() - 1 : 0);
806  hp_create_info.max_table_size=session->variables.max_heap_table_size;
807  hp_create_info.with_auto_increment= found_real_auto_increment;
808  hp_create_info.internal_table= internal_table;
809  hp_create_info.max_chunk_size= table_arg->getShare()->block_size;
810 
811  error= heap_create(table_name,
812  keys, &keydef[0],
813  column_count,
814  key_part_size,
815  table_arg->getShare()->getRecordLength(), mem_per_row_keys,
816  static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
817  0, // Factor out MIN
818  &hp_create_info, internal_share);
819 
820  return (error);
821 }
822 
823 
824 void ha_heap::get_auto_increment(uint64_t, uint64_t, uint64_t,
825  uint64_t *first_value,
826  uint64_t *nb_reserved_values)
827 {
828  ha_heap::info(HA_STATUS_AUTO);
829  *first_value= stats.auto_increment_value;
830  /* such table has only table-level locking so reserves up to +inf */
831  *nb_reserved_values= UINT64_MAX;
832 }
833 
834 
835 int ha_heap::cmp_ref(const unsigned char *ref1, const unsigned char *ref2)
836 {
837  return memcmp(ref1, ref2, sizeof(HEAP_PTR));
838 }
839 
840 
841 DRIZZLE_DECLARE_PLUGIN
842 {
843  DRIZZLE_VERSION_ID,
844  "memory",
845  "1.0",
846  "MySQL AB",
847  N_("MEMORY storage engine"),
848  PLUGIN_LICENSE_GPL,
849  heap_init,
850  NULL,
851  NULL
852 }
853 DRIZZLE_DECLARE_PLUGIN_END;
int doStartTableScan(bool scan)
Definition: ha_heap.cc:440
int delete_all_rows(void)
Definition: ha_heap.cc:506
TODO: Rename this file - func.h is stupid.
int ha_open(const identifier::Table &identifier, int mode, int test_if_locked)
Definition: cursor.cc:216
int index_read_last_map(unsigned char *buf, const unsigned char *key, drizzled::key_part_map keypart_map)
The following functions works like index_read, but it find the last row with the current key value or...
Definition: ha_heap.cc:383
Field * found_next_number_field
Definition: table.h:143
int index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key, drizzled::key_part_map keypart_map, enum drizzled::ha_rkey_function find_flag)
Positions an index cursor to the index specified in the handle. Fetches the row if available...
Definition: ha_heap.cc:394
int index_read_map(unsigned char *buf, const unsigned char *key, drizzled::key_part_map keypart_map, enum drizzled::ha_rkey_function find_flag)
Positions an index cursor to the index specified in the handle. Fetches the row if available...
Definition: ha_heap.cc:372
KeyInfo * key_info
Definition: table.h:141
int reset()
Definition: ha_heap.cc:500
unsigned char null_bit
Definition: field.h:152
uint32_t ref_length
Definition: cursor.h:159
unsigned char * null_ptr
Definition: field.h:72
drizzle_system_variables & variables
Definition: session.h:199