~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/ha_heap.cc

Re-org'd the replication stuff into slots.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "heap_priv.h"
 
16
#include <drizzled/server_includes.h>
17
17
#include <drizzled/error.h>
18
18
#include <drizzled/table.h>
19
19
#include <drizzled/session.h>
 
20
#include <drizzled/current_session.h>
20
21
#include <drizzled/field/timestamp.h>
21
22
#include <drizzled/field/varstring.h>
22
 
#include "drizzled/plugin/daemon.h"
23
 
 
24
 
#include <boost/thread/mutex.hpp>
25
23
 
26
24
#include "heap.h"
27
25
#include "ha_heap.h"
 
26
#include "heapdef.h"
28
27
 
29
28
#include <string>
30
29
 
31
 
 
32
 
using namespace drizzled;
33
30
using namespace std;
34
31
 
35
32
static const string engine_name("MEMORY");
36
33
 
37
 
boost::mutex THR_LOCK_heap;
 
34
pthread_mutex_t THR_LOCK_heap= PTHREAD_MUTEX_INITIALIZER;
38
35
 
39
36
static const char *ha_heap_exts[] = {
40
37
  NULL
41
38
};
42
39
 
43
 
class HeapEngine : public plugin::StorageEngine
 
40
class HeapEngine : public StorageEngine
44
41
{
45
42
public:
46
 
  explicit HeapEngine(string name_arg) :
47
 
    plugin::StorageEngine(name_arg,
48
 
                          HTON_STATS_RECORDS_IS_EXACT |
49
 
                          HTON_NULL_IN_KEY |
50
 
                          HTON_FAST_KEY_READ |
51
 
                          HTON_NO_BLOBS |
52
 
                          HTON_HAS_RECORDS |
53
 
                          HTON_SKIP_STORE_LOCK |
54
 
                          HTON_TEMPORARY_ONLY)
55
 
  {
56
 
  }
57
 
 
58
 
  virtual ~HeapEngine()
59
 
  {
60
 
    hp_panic(HA_PANIC_CLOSE);
61
 
  }
62
 
 
63
 
  virtual Cursor *create(Table &table)
64
 
  {
65
 
    return new ha_heap(*this, table);
 
43
  HeapEngine(string name_arg) : StorageEngine(name_arg, HTON_CAN_RECREATE|HTON_TEMPORARY_ONLY)
 
44
  {
 
45
    addAlias("HEAP");
 
46
  }
 
47
 
 
48
  virtual handler *create(TableShare *table,
 
49
                          MEM_ROOT *mem_root)
 
50
  {
 
51
    return new (mem_root) ha_heap(this, table);
66
52
  }
67
53
 
68
54
  const char **bas_ext() const {
69
55
    return ha_heap_exts;
70
56
  }
71
57
 
72
 
  int doCreateTable(Session &session,
73
 
                    Table &table_arg,
74
 
                    const TableIdentifier &identifier,
75
 
                    message::Table &create_proto);
 
58
  int createTableImplementation(Session *session, const char *table_name,
 
59
                                Table *table_arg, HA_CREATE_INFO *create_info,
 
60
                                drizzled::message::Table*);
76
61
 
77
 
  /* For whatever reason, internal tables can be created by Cursor::open()
78
 
     for MEMORY.
 
62
  /* For whatever reason, internal tables can be created by handler::open()
 
63
     for HEAP.
79
64
     Instead of diving down a rat hole, let's just cry ourselves to sleep
80
65
     at night with this odd hackish workaround.
81
66
   */
82
67
  int heap_create_table(Session *session, const char *table_name,
83
 
                        Table *table_arg,
 
68
                        Table *table_arg, HA_CREATE_INFO *create_info,
84
69
                        bool internal_table,
85
 
                        message::Table &create_proto,
86
70
                        HP_SHARE **internal_share);
87
71
 
88
 
  int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
89
 
 
90
 
  int doDropTable(Session&, const TableIdentifier &identifier);
91
 
 
92
 
  int doGetTableDefinition(Session& session,
93
 
                           const TableIdentifier &identifier,
94
 
                           message::Table &table_message);
95
 
 
96
 
  uint32_t max_supported_keys()          const { return MAX_KEY; }
97
 
  uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
98
 
 
99
 
  uint32_t index_flags(enum  ha_key_alg ) const
100
 
  {
101
 
    return ( HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
102
 
  }
103
 
 
104
 
  bool doDoesTableExist(Session& session, const TableIdentifier &identifier);
105
 
  void doGetTableIdentifiers(CachedDirectory &directory,
106
 
                             const SchemaIdentifier &schema_identifier,
107
 
                             TableIdentifier::vector &set_of_identifiers);
 
72
  int renameTableImplementation(Session*, const char * from, const char * to);
 
73
 
 
74
  int deleteTableImplementation(Session *, const string table_path);
108
75
};
109
76
 
110
 
void HeapEngine::doGetTableIdentifiers(CachedDirectory&,
111
 
                                       const SchemaIdentifier&,
112
 
                                       TableIdentifier::vector&)
113
 
{
114
 
}
115
 
 
116
 
bool HeapEngine::doDoesTableExist(Session& session, const TableIdentifier &identifier)
117
 
{
118
 
  return session.getMessageCache().doesTableMessageExist(identifier);
119
 
}
120
 
 
121
 
int HeapEngine::doGetTableDefinition(Session &session,
122
 
                                     const TableIdentifier &identifier,
123
 
                                     message::Table &table_proto)
124
 
{
125
 
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
126
 
    return EEXIST;
127
 
 
128
 
  return ENOENT;
129
 
}
130
77
/*
131
 
  We have to ignore ENOENT entries as the MEMORY table is created on open and
 
78
  We have to ignore ENOENT entries as the HEAP table is created on open and
132
79
  not when doing a CREATE on the table.
133
80
*/
134
 
int HeapEngine::doDropTable(Session &session, const TableIdentifier &identifier)
 
81
int HeapEngine::deleteTableImplementation(Session*, const string table_path)
135
82
{
136
 
  session.getMessageCache().removeTableMessage(identifier);
137
 
 
138
 
  int error= heap_delete_table(identifier.getPath().c_str());
139
 
 
140
 
  if (error == ENOENT)
141
 
    error= 0;
142
 
 
143
 
  return error;
 
83
  return heap_delete_table(table_path.c_str());
144
84
}
145
85
 
146
86
static HeapEngine *heap_storage_engine= NULL;
147
87
 
148
 
static int heap_init(module::Context &context)
 
88
static int heap_init(drizzled::plugin::Registry &registry)
149
89
{
150
90
  heap_storage_engine= new HeapEngine(engine_name);
151
 
  context.add(heap_storage_engine);
 
91
  registry.add(heap_storage_engine);
 
92
  pthread_mutex_init(&THR_LOCK_heap, MY_MUTEX_INIT_FAST);
152
93
  return 0;
153
94
}
154
95
 
 
96
static int heap_deinit(drizzled::plugin::Registry &registry)
 
97
{
 
98
  registry.remove(heap_storage_engine);
 
99
  delete heap_storage_engine;
 
100
 
 
101
  int ret= hp_panic(HA_PANIC_CLOSE);
 
102
 
 
103
  pthread_mutex_destroy(&THR_LOCK_heap);
 
104
 
 
105
  return ret;
 
106
}
 
107
 
 
108
 
155
109
 
156
110
/*****************************************************************************
157
 
** MEMORY tables
 
111
** HEAP tables
158
112
*****************************************************************************/
159
113
 
160
 
ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
161
 
                 Table &table_arg)
162
 
  :Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
 
114
ha_heap::ha_heap(StorageEngine *engine_arg, TableShare *table_arg)
 
115
  :handler(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
163
116
  internal_table(0)
164
117
{}
165
118
 
166
119
/*
167
120
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
168
 
  rec_per_key) after 1/MEMORY_STATS_UPDATE_THRESHOLD fraction of table records
 
121
  rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records
169
122
  have been inserted/updated/deleted. delete_all_rows() and table flush cause
170
123
  immediate update.
171
124
 
174
127
   from 0 to non-zero value and vice versa. Otherwise records_in_range may
175
128
   erroneously return 0 and 'range' may miss records.
176
129
*/
177
 
#define MEMORY_STATS_UPDATE_THRESHOLD 10
 
130
#define HEAP_STATS_UPDATE_THRESHOLD 10
178
131
 
179
 
int ha_heap::doOpen(const drizzled::TableIdentifier &identifier, int mode, uint32_t test_if_locked)
 
132
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
180
133
{
181
 
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(identifier.getPath().c_str(), mode)) && errno == ENOENT))
 
134
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
182
135
  {
 
136
    HA_CREATE_INFO create_info;
183
137
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
 
138
    memset(&create_info, 0, sizeof(create_info));
184
139
    file= 0;
185
140
    HP_SHARE *internal_share= NULL;
186
 
    message::Table create_proto;
187
 
 
188
 
    if (not heap_storage_engine->heap_create_table(getTable()->in_use,
189
 
                                                   identifier.getPath().c_str(),
190
 
                                                   getTable(),
191
 
                                                   internal_table,
192
 
                                                   create_proto,
193
 
                                                   &internal_share))
 
141
    if (!heap_storage_engine->heap_create_table(ha_session(), name, table,
 
142
                                                &create_info,
 
143
                                                internal_table,&internal_share))
194
144
    {
195
145
        file= internal_table ?
196
146
          heap_open_from_share(internal_share, mode) :
198
148
      if (!file)
199
149
      {
200
150
         /* Couldn't open table; Remove the newly created table */
201
 
        THR_LOCK_heap.lock();
 
151
        pthread_mutex_lock(&THR_LOCK_heap);
202
152
        hp_free(internal_share);
203
 
        THR_LOCK_heap.unlock();
 
153
        pthread_mutex_unlock(&THR_LOCK_heap);
204
154
      }
 
155
      implicit_emptied= 1;
205
156
    }
206
157
  }
207
158
  ref_length= sizeof(HEAP_PTR);
217
168
      ha_heap::info(), which is always called before key statistics are
218
169
      used.
219
170
    */
220
 
    key_stat_version= file->getShare()->key_stat_version - 1;
 
171
    key_stat_version= file->s->key_stat_version-1;
221
172
  }
222
173
  return (file ? 0 : 1);
223
174
}
233
184
 
234
185
  DESCRIPTION
235
186
    Do same as default implementation but use file->s->name instead of
236
 
    table->getShare()->path. This is needed by Windows where the clone() call sees
237
 
    '/'-delimited path in table->getShare()->path, while ha_peap::open() was called
 
187
    table->s->path. This is needed by Windows where the clone() call sees
 
188
    '/'-delimited path in table->s->path, while ha_peap::open() was called
238
189
    with '\'-delimited path.
239
190
*/
240
191
 
241
 
Cursor *ha_heap::clone(memory::Root *)
 
192
handler *ha_heap::clone(MEM_ROOT *mem_root)
242
193
{
243
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
244
 
  TableIdentifier identifier(getTable()->getShare()->getSchemaName(),
245
 
                             getTable()->getShare()->getTableName(),
246
 
                             getTable()->getShare()->getPath());
247
 
 
248
 
  if (new_handler && !new_handler->ha_open(identifier, getTable()->db_stat,
 
194
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
 
195
  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
249
196
                                           HA_OPEN_IGNORE_IF_LOCKED))
250
197
    return new_handler;
251
 
  return NULL;
252
 
}
253
 
 
254
 
 
255
 
const char *ha_heap::index_type(uint32_t )
256
 
{
257
 
  return ("HASH");
 
198
  return NULL;  /* purecov: inspected */
 
199
}
 
200
 
 
201
 
 
202
const char *ha_heap::index_type(uint32_t inx)
 
203
{
 
204
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
 
205
          "BTREE" : "HASH");
 
206
}
 
207
 
 
208
 
 
209
uint32_t ha_heap::index_flags(uint32_t inx, uint32_t, bool) const
 
210
{
 
211
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
 
212
          HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE :
 
213
          HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
258
214
}
259
215
 
260
216
 
276
232
 
277
233
void ha_heap::set_keys_for_scanning(void)
278
234
{
 
235
  btree_keys.reset();
 
236
  for (uint32_t i= 0 ; i < table->s->keys ; i++)
 
237
  {
 
238
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
 
239
      btree_keys.set(i);
 
240
  }
279
241
}
280
242
 
281
243
 
282
244
void ha_heap::update_key_stats()
283
245
{
284
 
  for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
 
246
  for (uint32_t i= 0; i < table->s->keys; i++)
285
247
  {
286
 
    KeyInfo *key= &getTable()->key_info[i];
287
 
 
 
248
    KEY *key=table->key_info+i;
288
249
    if (!key->rec_per_key)
289
250
      continue;
290
 
 
 
251
    if (key->algorithm != HA_KEY_ALG_BTREE)
291
252
    {
292
253
      if (key->flags & HA_NOSAME)
293
254
        key->rec_per_key[key->key_parts-1]= 1;
294
255
      else
295
256
      {
296
 
        ha_rows hash_buckets= file->getShare()->keydef[i].hash_buckets;
297
 
        uint32_t no_records= hash_buckets ? (uint) (file->getShare()->records/hash_buckets) : 2;
 
257
        ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
 
258
        uint32_t no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
298
259
        if (no_records < 2)
299
260
          no_records= 2;
300
261
        key->rec_per_key[key->key_parts-1]= no_records;
303
264
  }
304
265
  records_changed= 0;
305
266
  /* At the end of update_key_stats() we can proudly claim they are OK. */
306
 
  key_stat_version= file->getShare()->key_stat_version;
 
267
  key_stat_version= file->s->key_stat_version;
307
268
}
308
269
 
309
270
 
310
 
int ha_heap::doInsertRecord(unsigned char * buf)
 
271
int ha_heap::write_row(unsigned char * buf)
311
272
{
312
273
  int res;
313
 
  if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
 
274
  ha_statistic_increment(&SSV::ha_write_count);
 
275
  if (table->next_number_field && buf == table->record[0])
314
276
  {
315
277
    if ((res= update_auto_increment()))
316
278
      return res;
317
279
  }
318
280
  res= heap_write(file,buf);
319
 
  if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
320
 
               file->getShare()->records))
 
281
  if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
 
282
               file->s->records))
321
283
  {
322
284
    /*
323
285
       We can perform this safely since only one writer at the time is
324
286
       allowed on the table.
325
287
    */
326
 
    file->getShare()->key_stat_version++;
 
288
    file->s->key_stat_version++;
327
289
  }
328
290
  return res;
329
291
}
330
292
 
331
 
int ha_heap::doUpdateRecord(const unsigned char * old_data, unsigned char * new_data)
 
293
int ha_heap::update_row(const unsigned char * old_data, unsigned char * new_data)
332
294
{
333
295
  int res;
334
 
 
 
296
  ha_statistic_increment(&SSV::ha_update_count);
 
297
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
298
    table->timestamp_field->set_time();
335
299
  res= heap_update(file,old_data,new_data);
336
 
  if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
337
 
              file->getShare()->records)
 
300
  if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
 
301
              file->s->records)
338
302
  {
339
303
    /*
340
304
       We can perform this safely since only one writer at the time is
341
305
       allowed on the table.
342
306
    */
343
 
    file->getShare()->key_stat_version++;
 
307
    file->s->key_stat_version++;
344
308
  }
345
309
  return res;
346
310
}
347
311
 
348
 
int ha_heap::doDeleteRecord(const unsigned char * buf)
 
312
int ha_heap::delete_row(const unsigned char * buf)
349
313
{
350
314
  int res;
351
 
 
 
315
  ha_statistic_increment(&SSV::ha_delete_count);
352
316
  res= heap_delete(file,buf);
353
 
  if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
354
 
      ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
 
317
  if (!res && table->s->tmp_table == NO_TMP_TABLE &&
 
318
      ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
355
319
  {
356
320
    /*
357
321
       We can perform this safely since only one writer at the time is
358
322
       allowed on the table.
359
323
    */
360
 
    file->getShare()->key_stat_version++;
 
324
    file->s->key_stat_version++;
361
325
  }
362
326
  return res;
363
327
}
367
331
                            enum ha_rkey_function find_flag)
368
332
{
369
333
  assert(inited==INDEX);
370
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
334
  ha_statistic_increment(&SSV::ha_read_key_count);
371
335
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
372
 
  getTable()->status = error ? STATUS_NOT_FOUND : 0;
 
336
  table->status = error ? STATUS_NOT_FOUND : 0;
373
337
  return error;
374
338
}
375
339
 
377
341
                                 key_part_map keypart_map)
378
342
{
379
343
  assert(inited==INDEX);
380
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
344
  ha_statistic_increment(&SSV::ha_read_key_count);
381
345
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
382
346
                       HA_READ_PREFIX_LAST);
383
 
  getTable()->status= error ? STATUS_NOT_FOUND : 0;
 
347
  table->status= error ? STATUS_NOT_FOUND : 0;
384
348
  return error;
385
349
}
386
350
 
388
352
                                key_part_map keypart_map,
389
353
                                enum ha_rkey_function find_flag)
390
354
{
391
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
355
  ha_statistic_increment(&SSV::ha_read_key_count);
392
356
  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
393
 
  getTable()->status = error ? STATUS_NOT_FOUND : 0;
 
357
  table->status = error ? STATUS_NOT_FOUND : 0;
394
358
  return error;
395
359
}
396
360
 
397
361
int ha_heap::index_next(unsigned char * buf)
398
362
{
399
363
  assert(inited==INDEX);
400
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
364
  ha_statistic_increment(&SSV::ha_read_next_count);
401
365
  int error=heap_rnext(file,buf);
402
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
366
  table->status=error ? STATUS_NOT_FOUND: 0;
403
367
  return error;
404
368
}
405
369
 
406
370
int ha_heap::index_prev(unsigned char * buf)
407
371
{
408
372
  assert(inited==INDEX);
409
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
373
  ha_statistic_increment(&SSV::ha_read_prev_count);
410
374
  int error=heap_rprev(file,buf);
411
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
375
  table->status=error ? STATUS_NOT_FOUND: 0;
412
376
  return error;
413
377
}
414
378
 
415
379
int ha_heap::index_first(unsigned char * buf)
416
380
{
417
381
  assert(inited==INDEX);
418
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
382
  ha_statistic_increment(&SSV::ha_read_first_count);
419
383
  int error=heap_rfirst(file, buf, active_index);
420
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
384
  table->status=error ? STATUS_NOT_FOUND: 0;
421
385
  return error;
422
386
}
423
387
 
424
388
int ha_heap::index_last(unsigned char * buf)
425
389
{
426
390
  assert(inited==INDEX);
427
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
391
  ha_statistic_increment(&SSV::ha_read_last_count);
428
392
  int error=heap_rlast(file, buf, active_index);
429
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
393
  table->status=error ? STATUS_NOT_FOUND: 0;
430
394
  return error;
431
395
}
432
396
 
433
 
int ha_heap::doStartTableScan(bool scan)
 
397
int ha_heap::rnd_init(bool scan)
434
398
{
435
399
  return scan ? heap_scan_init(file) : 0;
436
400
}
437
401
 
438
402
int ha_heap::rnd_next(unsigned char *buf)
439
403
{
440
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
404
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
441
405
  int error=heap_scan(file, buf);
442
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
406
  table->status=error ? STATUS_NOT_FOUND: 0;
443
407
  return error;
444
408
}
445
409
 
447
411
{
448
412
  int error;
449
413
  HEAP_PTR heap_position;
450
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
 
414
  ha_statistic_increment(&SSV::ha_read_rnd_count);
451
415
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
452
416
  error=heap_rrnd(file, buf, heap_position);
453
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
417
  table->status=error ? STATUS_NOT_FOUND: 0;
454
418
  return error;
455
419
}
456
420
 
479
443
    have to update the key statistics. Hoping that a table lock is now
480
444
    in place.
481
445
  */
482
 
  if (key_stat_version != file->getShare()->key_stat_version)
 
446
  if (key_stat_version != file->s->key_stat_version)
483
447
    update_key_stats();
484
448
  return 0;
485
449
}
486
450
 
 
451
 
 
452
enum row_type ha_heap::get_row_type() const
 
453
{
 
454
  if (file->s->recordspace.is_variable_size)
 
455
    return ROW_TYPE_DYNAMIC;
 
456
 
 
457
  return ROW_TYPE_FIXED;
 
458
}
 
459
 
487
460
int ha_heap::extra(enum ha_extra_function operation)
488
461
{
489
462
  return heap_extra(file,operation);
499
472
int ha_heap::delete_all_rows()
500
473
{
501
474
  heap_clear(file);
502
 
  if (getTable()->getShare()->getType() == message::Table::STANDARD)
 
475
  if (table->s->tmp_table == NO_TMP_TABLE)
503
476
  {
504
477
    /*
505
478
       We can perform this safely since only one writer at the time is
506
479
       allowed on the table.
507
480
    */
508
 
    file->getShare()->key_stat_version++;
 
481
    file->s->key_stat_version++;
509
482
  }
510
483
  return 0;
511
484
}
512
485
 
 
486
int ha_heap::external_lock(Session *, int)
 
487
{
 
488
  return 0;                                     // No external locking
 
489
}
 
490
 
 
491
 
513
492
/*
514
493
  Disable indexes.
515
494
 
568
547
    The indexes might have been disabled by disable_index() before.
569
548
    The function works only if both data and indexes are empty,
570
549
    since the heap storage engine cannot repair the indexes.
571
 
    To be sure, call Cursor::delete_all_rows() before.
 
550
    To be sure, call handler::delete_all_rows() before.
572
551
 
573
552
  IMPLEMENTATION
574
553
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
617
596
  return heap_indexes_are_disabled(file);
618
597
}
619
598
 
 
599
THR_LOCK_DATA **ha_heap::store_lock(Session *,
 
600
                                    THR_LOCK_DATA **to,
 
601
                                    enum thr_lock_type lock_type)
 
602
{
 
603
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
604
    file->lock.type=lock_type;
 
605
  *to++= &file->lock;
 
606
  return to;
 
607
}
 
608
 
620
609
void ha_heap::drop_table(const char *)
621
610
{
622
 
  file->getShare()->delete_on_close= 1;
 
611
  file->s->delete_on_close= 1;
623
612
  close();
624
613
}
625
614
 
626
615
 
627
 
int HeapEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
616
int HeapEngine::renameTableImplementation(Session*,
 
617
                                          const char *from, const char *to)
628
618
{
629
 
  session.getMessageCache().renameTableMessage(from, to);
630
 
  return heap_rename(from.getPath().c_str(), to.getPath().c_str());
 
619
  return heap_rename(from,to);
631
620
}
632
621
 
633
622
 
634
623
ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
635
624
                                  key_range *max_key)
636
625
{
637
 
  KeyInfo *key= &getTable()->key_info[inx];
 
626
  KEY *key=table->key_info+inx;
 
627
  if (key->algorithm == HA_KEY_ALG_BTREE)
 
628
    return hp_rb_records_in_range(file, inx, min_key, max_key);
638
629
 
639
630
  if (!min_key || !max_key ||
640
631
      min_key->length != max_key->length ||
647
638
    return stats.records;
648
639
 
649
640
  /* Assert that info() did run. We need current statistics here. */
650
 
  assert(key_stat_version == file->getShare()->key_stat_version);
 
641
  assert(key_stat_version == file->s->key_stat_version);
651
642
  return key->rec_per_key[key->key_parts-1];
652
643
}
653
644
 
654
 
int HeapEngine::doCreateTable(Session &session,
655
 
                              Table &table_arg,
656
 
                              const TableIdentifier &identifier,
657
 
                              message::Table& create_proto)
 
645
int HeapEngine::createTableImplementation(Session *session,
 
646
                                          const char *table_name,
 
647
                                          Table *table_arg,
 
648
                                          HA_CREATE_INFO *create_info,
 
649
                                          drizzled::message::Table*)
658
650
{
659
 
  int error;
660
651
  HP_SHARE *internal_share;
661
 
  const char *table_name= identifier.getPath().c_str();
662
 
 
663
 
  error= heap_create_table(&session, table_name, &table_arg,
664
 
                           false, 
665
 
                           create_proto,
666
 
                           &internal_share);
667
 
 
668
 
  if (error == 0)
669
 
  {
670
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
671
 
  }
672
 
 
673
 
  return error;
 
652
  return heap_create_table(session, table_name, table_arg, create_info,
 
653
                           false, &internal_share);
674
654
}
675
655
 
676
656
 
677
657
int HeapEngine::heap_create_table(Session *session, const char *table_name,
678
 
                                  Table *table_arg,
679
 
                                  bool internal_table, 
680
 
                                  message::Table &create_proto,
681
 
                                  HP_SHARE **internal_share)
 
658
                             Table *table_arg, HA_CREATE_INFO *create_info,
 
659
                             bool internal_table, HP_SHARE **internal_share)
682
660
{
683
 
  uint32_t key, parts, mem_per_row_keys= 0;
684
 
  uint32_t keys= table_arg->getShare()->sizeKeys();
 
661
  uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
685
662
  uint32_t auto_key= 0, auto_key_type= 0;
686
663
  uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
687
 
  uint32_t column_count= table_arg->getShare()->sizeFields();
688
 
  std::vector<HP_KEYDEF> keydef;
 
664
  uint32_t column_idx, column_count= table_arg->s->fields;
 
665
  HP_COLUMNDEF *columndef;
 
666
  HP_KEYDEF *keydef;
 
667
  HA_KEYSEG *seg;
 
668
  char buff[FN_REFLEN];
689
669
  int error;
 
670
  TableShare *share= table_arg->s;
690
671
  bool found_real_auto_increment= 0;
691
672
 
692
673
  /* 
695
676
   * can return a number more than that, we trap it here instead of casting
696
677
   * to a truncated integer.
697
678
   */
698
 
  uint64_t num_rows= table_arg->getShare()->getMaxRows();
 
679
  uint64_t num_rows= share->getMaxRows();
699
680
  if (num_rows > UINT32_MAX)
700
681
    return -1;
701
682
 
 
683
  if (!(columndef= (HP_COLUMNDEF*) malloc(column_count * sizeof(HP_COLUMNDEF))))
 
684
    return my_errno;
 
685
 
 
686
  for (column_idx= 0; column_idx < column_count; column_idx++)
 
687
  {
 
688
    Field* field= *(table_arg->field + column_idx);
 
689
    HP_COLUMNDEF* column= columndef + column_idx;
 
690
    column->type= (uint16_t)field->type();
 
691
    column->length= field->pack_length();
 
692
    column->offset= field->offset(field->table->record[0]);
 
693
 
 
694
    if (field->null_bit)
 
695
    {
 
696
      column->null_bit= field->null_bit;
 
697
      column->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
 
698
    }
 
699
    else
 
700
    {
 
701
      column->null_bit= 0;
 
702
      column->null_pos= 0;
 
703
    }
 
704
 
 
705
    if (field->type() == DRIZZLE_TYPE_VARCHAR)
 
706
    {
 
707
      column->length_bytes= (uint8_t)(((Field_varstring*)field)->length_bytes);
 
708
    }
 
709
    else
 
710
    {
 
711
      column->length_bytes= 0;
 
712
    }
 
713
  }
 
714
 
702
715
  for (key= parts= 0; key < keys; key++)
703
716
    parts+= table_arg->key_info[key].key_parts;
704
717
 
705
 
  keydef.resize(keys);
706
 
  std::vector<HA_KEYSEG> seg_buffer;
707
 
  seg_buffer.resize(parts);
708
 
  HA_KEYSEG *seg= &seg_buffer[0];
 
718
  if (!(keydef= (HP_KEYDEF*) malloc(keys * sizeof(HP_KEYDEF) +
 
719
                                    parts * sizeof(HA_KEYSEG))))
 
720
  {
 
721
    free((void *) columndef);
 
722
    return my_errno;
 
723
  }
709
724
 
 
725
  seg= reinterpret_cast<HA_KEYSEG*> (keydef + keys);
710
726
  for (key= 0; key < keys; key++)
711
727
  {
712
 
    KeyInfo *pos= &table_arg->key_info[key];
713
 
    KeyPartInfo *key_part=     pos->key_part;
714
 
    KeyPartInfo *key_part_end= key_part + pos->key_parts;
 
728
    KEY *pos= table_arg->key_info+key;
 
729
    KEY_PART_INFO *key_part=     pos->key_part;
 
730
    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
715
731
 
716
732
    keydef[key].keysegs=   (uint) pos->key_parts;
717
733
    keydef[key].flag=      (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
718
734
    keydef[key].seg=       seg;
719
735
 
720
 
    mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
736
    switch (pos->algorithm) {
 
737
    case HA_KEY_ALG_UNDEF:
 
738
    case HA_KEY_ALG_HASH:
 
739
      keydef[key].algorithm= HA_KEY_ALG_HASH;
 
740
      mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
741
      break;
 
742
    case HA_KEY_ALG_BTREE:
 
743
      keydef[key].algorithm= HA_KEY_ALG_BTREE;
 
744
      mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
 
745
      break;
 
746
    default:
 
747
      assert(0); // cannot happen
 
748
    }
721
749
 
722
750
    for (; key_part != key_part_end; key_part++, seg++)
723
751
    {
724
752
      Field *field= key_part->field;
725
753
 
 
754
      if (pos->algorithm == HA_KEY_ALG_BTREE)
 
755
        seg->type= field->key_type();
 
756
      else
726
757
      {
727
758
        if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
728
759
            seg->type != HA_KEYTYPE_VARTEXT1 &&
738
769
      next_field_pos= seg->start + seg->length;
739
770
      if (field->type() == DRIZZLE_TYPE_VARCHAR)
740
771
      {
741
 
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->pack_length_no_ptr());
 
772
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
742
773
      }
743
774
 
744
775
      if (next_field_pos > key_part_size) {
745
776
        key_part_size= next_field_pos;
746
777
      }
747
778
 
748
 
      if (field->flags & ENUM_FLAG)
 
779
      if (field->flags & (ENUM_FLAG | SET_FLAG))
749
780
        seg->charset= &my_charset_bin;
750
781
      else
751
782
        seg->charset= field->charset();
752
783
      if (field->null_ptr)
753
784
      {
754
785
        seg->null_bit= field->null_bit;
755
 
        seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->getInsertRecord());
 
786
        seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
756
787
      }
757
788
      else
758
789
      {
761
792
      }
762
793
      if (field->flags & AUTO_INCREMENT_FLAG &&
763
794
          table_arg->found_next_number_field &&
764
 
          key == table_arg->getShare()->next_number_index)
 
795
          key == share->next_number_index)
765
796
      {
766
797
        /*
767
798
          Store key number and type for found auto_increment key
770
801
        auto_key= key+ 1;
771
802
        auto_key_type= field->key_type();
772
803
      }
773
 
      if ((uint)field->position() + 1 > max_key_fieldnr)
 
804
      if ((uint)field->field_index + 1 > max_key_fieldnr)
774
805
      {
775
806
        /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
776
 
        max_key_fieldnr= field->position() + 1;
 
807
        max_key_fieldnr= field->field_index + 1;
777
808
      }
778
809
    }
779
810
  }
780
811
 
781
 
  if (key_part_size < table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3))
 
812
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
782
813
  {
783
814
    /* Make sure to include null fields regardless of the presense of keys */
784
 
    key_part_size = table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3);
 
815
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
785
816
  }
786
817
 
787
818
 
788
819
 
789
820
  if (table_arg->found_next_number_field)
790
821
  {
791
 
    keydef[table_arg->getShare()->next_number_index].flag|= HA_AUTO_KEY;
792
 
    found_real_auto_increment= table_arg->getShare()->next_number_key_offset == 0;
 
822
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
 
823
    found_real_auto_increment= share->next_number_key_offset == 0;
793
824
  }
794
825
  HP_CREATE_INFO hp_create_info;
795
826
  hp_create_info.auto_key= auto_key;
796
827
  hp_create_info.auto_key_type= auto_key_type;
797
 
  hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
798
 
                                  create_proto.options().auto_increment_value() - 1 : 0);
 
828
  hp_create_info.auto_increment= (create_info->auto_increment_value ?
 
829
                                  create_info->auto_increment_value - 1 : 0);
799
830
  hp_create_info.max_table_size=session->variables.max_heap_table_size;
800
831
  hp_create_info.with_auto_increment= found_real_auto_increment;
801
832
  hp_create_info.internal_table= internal_table;
802
 
  hp_create_info.max_chunk_size= table_arg->getShare()->block_size;
803
 
 
804
 
  error= heap_create(table_name,
805
 
                     keys, &keydef[0],
806
 
                     column_count,
807
 
                     key_part_size,
808
 
                     table_arg->getShare()->getRecordLength(), mem_per_row_keys,
809
 
                     static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
810
 
                     0, // Factor out MIN
811
 
                     &hp_create_info, internal_share);
 
833
  hp_create_info.max_chunk_size= share->block_size;
 
834
  hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
 
835
 
 
836
  error= heap_create(fn_format(buff,table_name,"","",
 
837
                              MY_REPLACE_EXT|MY_UNPACK_FILENAME),
 
838
                    keys, keydef,
 
839
                    column_count, columndef,
 
840
                    max_key_fieldnr, key_part_size,
 
841
                    share->reclength, mem_per_row_keys,
 
842
                    static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
 
843
                    0, // Factor out MIN
 
844
                    &hp_create_info, internal_share);
 
845
 
 
846
  free((unsigned char*) keydef);
 
847
  free((void *) columndef);
812
848
 
813
849
  return (error);
814
850
}
831
867
}
832
868
 
833
869
 
834
 
DRIZZLE_DECLARE_PLUGIN
 
870
drizzle_declare_plugin(heap)
835
871
{
836
 
  DRIZZLE_VERSION_ID,
837
872
  "MEMORY",
838
873
  "1.0",
839
874
  "MySQL AB",
840
875
  "Hash based, stored in memory, useful for temporary tables",
841
876
  PLUGIN_LICENSE_GPL,
842
877
  heap_init,
 
878
  heap_deinit,
 
879
  NULL,                       /* status variables                */
843
880
  NULL,                       /* system variables                */
844
881
  NULL                        /* config options                  */
845
882
}
846
 
DRIZZLE_DECLARE_PLUGIN_END;
 
883
drizzle_declare_plugin_end;