~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/ha_heap.cc

  • Committer: Stewart Smith
  • Date: 2010-02-15 01:56:32 UTC
  • mto: (1273.13.96 build)
  • mto: This revision was merged to the branch mainline in revision 1308.
  • Revision ID: stewart@flamingspork.com-20100215015632-pm7lnxfq5j5uh8kj
move DATABASE() to function plugin. modify parser so that it looks for a function named 'database' when DATABASE() is called. Special case still needed in parser due to hilarity of not-really-reserved words.

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
16
#include "heap_priv.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"
34
32
 
35
33
static const string engine_name("MEMORY");
36
34
 
37
 
boost::mutex THR_LOCK_heap;
 
35
pthread_mutex_t THR_LOCK_heap= PTHREAD_MUTEX_INITIALIZER;
38
36
 
39
37
static const char *ha_heap_exts[] = {
40
38
  NULL
43
41
class HeapEngine : public plugin::StorageEngine
44
42
{
45
43
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);
 
44
  HeapEngine(string name_arg)
 
45
   : plugin::StorageEngine(name_arg,
 
46
                                     HTON_STATS_RECORDS_IS_EXACT |
 
47
                                     HTON_NULL_IN_KEY |
 
48
                                     HTON_FAST_KEY_READ |
 
49
                                     HTON_NO_BLOBS |
 
50
                                     HTON_HAS_RECORDS |
 
51
                                     HTON_SKIP_STORE_LOCK |
 
52
                                     HTON_TEMPORARY_ONLY)
 
53
  { }
 
54
 
 
55
  virtual Cursor *create(TableShare &table,
 
56
                          memory::Root *mem_root)
 
57
  {
 
58
    return new (mem_root) ha_heap(*this, table);
66
59
  }
67
60
 
68
61
  const char **bas_ext() const {
69
62
    return ha_heap_exts;
70
63
  }
71
64
 
72
 
  int doCreateTable(Session &session,
73
 
                    Table &table_arg,
74
 
                    const TableIdentifier &identifier,
 
65
  int doCreateTable(Session *session,
 
66
                    const char *table_name,
 
67
                    Table& table_arg,
75
68
                    message::Table &create_proto);
76
69
 
77
70
  /* For whatever reason, internal tables can be created by Cursor::open()
85
78
                        message::Table &create_proto,
86
79
                        HP_SHARE **internal_share);
87
80
 
88
 
  int doRenameTable(Session&, const TableIdentifier &from, const TableIdentifier &to);
 
81
  int doRenameTable(Session*, const char * from, const char * to);
89
82
 
90
 
  int doDropTable(Session&, const TableIdentifier &identifier);
 
83
  int doDropTable(Session&, const string table_path);
91
84
 
92
85
  int doGetTableDefinition(Session& session,
93
 
                           const TableIdentifier &identifier,
94
 
                           message::Table &table_message);
 
86
                           const char* path,
 
87
                           const char *db,
 
88
                           const char *table_name,
 
89
                           const bool is_tmp,
 
90
                           message::Table *table_proto);
 
91
 
 
92
  /* Temp only engine, so do not return values. */
 
93
  void doGetTableNames(CachedDirectory &, string& , set<string>&) { };
95
94
 
96
95
  uint32_t max_supported_keys()          const { return MAX_KEY; }
97
96
  uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
98
97
 
99
 
  uint32_t index_flags(enum  ha_key_alg ) const
 
98
  uint32_t index_flags(enum  ha_key_alg algorithm) const
100
99
  {
101
 
    return ( HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
 
100
    return ((algorithm == HA_KEY_ALG_BTREE) ?
 
101
            HA_READ_NEXT |
 
102
            HA_READ_PREV |
 
103
            HA_READ_ORDER |
 
104
            HA_READ_RANGE :
 
105
            HA_ONLY_WHOLE_INDEX |
 
106
            HA_KEY_SCAN_NOT_ROR);
102
107
  }
103
108
 
104
 
  bool doDoesTableExist(Session& session, const TableIdentifier &identifier);
105
 
  void doGetTableIdentifiers(CachedDirectory &directory,
106
 
                             const SchemaIdentifier &schema_identifier,
107
 
                             TableIdentifier::vector &set_of_identifiers);
108
109
};
109
110
 
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;
 
111
int HeapEngine::doGetTableDefinition(Session&,
 
112
                                     const char* path,
 
113
                                     const char *,
 
114
                                     const char *,
 
115
                                     const bool,
 
116
                                     message::Table *table_proto)
 
117
{
 
118
  int error= ENOENT;
 
119
  ProtoCache::iterator iter;
 
120
 
 
121
  pthread_mutex_lock(&proto_cache_mutex);
 
122
  iter= proto_cache.find(path);
 
123
 
 
124
  if (iter!= proto_cache.end())
 
125
  {
 
126
    if (table_proto)
 
127
      table_proto->CopyFrom(((*iter).second));
 
128
    error= EEXIST;
 
129
  }
 
130
  pthread_mutex_unlock(&proto_cache_mutex);
 
131
 
 
132
  return error;
129
133
}
130
134
/*
131
135
  We have to ignore ENOENT entries as the MEMORY table is created on open and
132
136
  not when doing a CREATE on the table.
133
137
*/
134
 
int HeapEngine::doDropTable(Session &session, const TableIdentifier &identifier)
 
138
int HeapEngine::doDropTable(Session&, const string table_path)
135
139
{
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;
 
140
  ProtoCache::iterator iter;
 
141
 
 
142
  pthread_mutex_lock(&proto_cache_mutex);
 
143
  iter= proto_cache.find(table_path.c_str());
 
144
 
 
145
  if (iter!= proto_cache.end())
 
146
    proto_cache.erase(iter);
 
147
  pthread_mutex_unlock(&proto_cache_mutex);
 
148
 
 
149
  return heap_delete_table(table_path.c_str());
144
150
}
145
151
 
146
152
static HeapEngine *heap_storage_engine= NULL;
147
153
 
148
 
static int heap_init(module::Context &context)
 
154
static int heap_init(plugin::Registry &registry)
149
155
{
150
156
  heap_storage_engine= new HeapEngine(engine_name);
151
 
  context.add(heap_storage_engine);
 
157
  registry.add(heap_storage_engine);
 
158
  pthread_mutex_init(&THR_LOCK_heap, MY_MUTEX_INIT_FAST);
152
159
  return 0;
153
160
}
154
161
 
 
162
static int heap_deinit(plugin::Registry &registry)
 
163
{
 
164
  registry.remove(heap_storage_engine);
 
165
  delete heap_storage_engine;
 
166
 
 
167
  int ret= hp_panic(HA_PANIC_CLOSE);
 
168
 
 
169
  pthread_mutex_destroy(&THR_LOCK_heap);
 
170
 
 
171
  return ret;
 
172
}
 
173
 
 
174
 
155
175
 
156
176
/*****************************************************************************
157
177
** MEMORY tables
158
178
*****************************************************************************/
159
179
 
160
180
ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
161
 
                 Table &table_arg)
 
181
                 TableShare &table_arg)
162
182
  :Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
163
183
  internal_table(0)
164
184
{}
176
196
*/
177
197
#define MEMORY_STATS_UPDATE_THRESHOLD 10
178
198
 
179
 
int ha_heap::doOpen(const drizzled::TableIdentifier &identifier, int mode, uint32_t test_if_locked)
 
199
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
180
200
{
181
 
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(identifier.getPath().c_str(), mode)) && errno == ENOENT))
 
201
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && errno == ENOENT))
182
202
  {
 
203
    HA_CREATE_INFO create_info;
183
204
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
 
205
    memset(&create_info, 0, sizeof(create_info));
184
206
    file= 0;
185
207
    HP_SHARE *internal_share= NULL;
186
208
    message::Table create_proto;
187
209
 
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))
 
210
    if (!heap_storage_engine->heap_create_table(ha_session(), name, table,
 
211
                                                internal_table,
 
212
                                                create_proto,
 
213
                                                &internal_share))
194
214
    {
195
215
        file= internal_table ?
196
216
          heap_open_from_share(internal_share, mode) :
198
218
      if (!file)
199
219
      {
200
220
         /* Couldn't open table; Remove the newly created table */
201
 
        THR_LOCK_heap.lock();
 
221
        pthread_mutex_lock(&THR_LOCK_heap);
202
222
        hp_free(internal_share);
203
 
        THR_LOCK_heap.unlock();
 
223
        pthread_mutex_unlock(&THR_LOCK_heap);
204
224
      }
 
225
      implicit_emptied= 1;
205
226
    }
206
227
  }
207
228
  ref_length= sizeof(HEAP_PTR);
217
238
      ha_heap::info(), which is always called before key statistics are
218
239
      used.
219
240
    */
220
 
    key_stat_version= file->getShare()->key_stat_version - 1;
 
241
    key_stat_version= file->s->key_stat_version-1;
221
242
  }
222
243
  return (file ? 0 : 1);
223
244
}
233
254
 
234
255
  DESCRIPTION
235
256
    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
 
257
    table->s->path. This is needed by Windows where the clone() call sees
 
258
    '/'-delimited path in table->s->path, while ha_peap::open() was called
238
259
    with '\'-delimited path.
239
260
*/
240
261
 
241
 
Cursor *ha_heap::clone(memory::Root *)
 
262
Cursor *ha_heap::clone(memory::Root *mem_root)
242
263
{
243
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
244
 
  TableIdentifier identifier(getTable()->getShare()->getSchemaName(),
245
 
                             getTable()->getShare()->getTableName(),
246
 
                             getTable()->getShare()->getPath());
 
264
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
247
265
 
248
 
  if (new_handler && !new_handler->ha_open(identifier, getTable()->db_stat,
 
266
  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
249
267
                                           HA_OPEN_IGNORE_IF_LOCKED))
250
268
    return new_handler;
251
269
  return NULL;
252
270
}
253
271
 
254
272
 
255
 
const char *ha_heap::index_type(uint32_t )
 
273
const char *ha_heap::index_type(uint32_t inx)
256
274
{
257
 
  return ("HASH");
 
275
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
 
276
          "BTREE" : "HASH");
258
277
}
259
278
 
260
279
 
276
295
 
277
296
void ha_heap::set_keys_for_scanning(void)
278
297
{
 
298
  btree_keys.reset();
 
299
  for (uint32_t i= 0 ; i < table->s->keys ; i++)
 
300
  {
 
301
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
 
302
      btree_keys.set(i);
 
303
  }
279
304
}
280
305
 
281
306
 
282
307
void ha_heap::update_key_stats()
283
308
{
284
 
  for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
 
309
  for (uint32_t i= 0; i < table->s->keys; i++)
285
310
  {
286
 
    KeyInfo *key= &getTable()->key_info[i];
287
 
 
 
311
    KEY *key=table->key_info+i;
288
312
    if (!key->rec_per_key)
289
313
      continue;
290
 
 
 
314
    if (key->algorithm != HA_KEY_ALG_BTREE)
291
315
    {
292
316
      if (key->flags & HA_NOSAME)
293
317
        key->rec_per_key[key->key_parts-1]= 1;
294
318
      else
295
319
      {
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;
 
320
        ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
 
321
        uint32_t no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
298
322
        if (no_records < 2)
299
323
          no_records= 2;
300
324
        key->rec_per_key[key->key_parts-1]= no_records;
303
327
  }
304
328
  records_changed= 0;
305
329
  /* At the end of update_key_stats() we can proudly claim they are OK. */
306
 
  key_stat_version= file->getShare()->key_stat_version;
 
330
  key_stat_version= file->s->key_stat_version;
307
331
}
308
332
 
309
333
 
310
 
int ha_heap::doInsertRecord(unsigned char * buf)
 
334
int ha_heap::write_row(unsigned char * buf)
311
335
{
312
336
  int res;
313
 
  if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
 
337
  ha_statistic_increment(&SSV::ha_write_count);
 
338
  if (table->next_number_field && buf == table->record[0])
314
339
  {
315
340
    if ((res= update_auto_increment()))
316
341
      return res;
317
342
  }
318
343
  res= heap_write(file,buf);
319
344
  if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
320
 
               file->getShare()->records))
 
345
               file->s->records))
321
346
  {
322
347
    /*
323
348
       We can perform this safely since only one writer at the time is
324
349
       allowed on the table.
325
350
    */
326
 
    file->getShare()->key_stat_version++;
 
351
    file->s->key_stat_version++;
327
352
  }
328
353
  return res;
329
354
}
330
355
 
331
 
int ha_heap::doUpdateRecord(const unsigned char * old_data, unsigned char * new_data)
 
356
int ha_heap::update_row(const unsigned char * old_data, unsigned char * new_data)
332
357
{
333
358
  int res;
334
 
 
 
359
  ha_statistic_increment(&SSV::ha_update_count);
 
360
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
361
    table->timestamp_field->set_time();
335
362
  res= heap_update(file,old_data,new_data);
336
363
  if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
337
 
              file->getShare()->records)
 
364
              file->s->records)
338
365
  {
339
366
    /*
340
367
       We can perform this safely since only one writer at the time is
341
368
       allowed on the table.
342
369
    */
343
 
    file->getShare()->key_stat_version++;
 
370
    file->s->key_stat_version++;
344
371
  }
345
372
  return res;
346
373
}
347
374
 
348
 
int ha_heap::doDeleteRecord(const unsigned char * buf)
 
375
int ha_heap::delete_row(const unsigned char * buf)
349
376
{
350
377
  int res;
351
 
 
 
378
  ha_statistic_increment(&SSV::ha_delete_count);
352
379
  res= heap_delete(file,buf);
353
 
  if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
354
 
      ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
 
380
  if (!res && table->s->tmp_table == NO_TMP_TABLE &&
 
381
      ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->s->records)
355
382
  {
356
383
    /*
357
384
       We can perform this safely since only one writer at the time is
358
385
       allowed on the table.
359
386
    */
360
 
    file->getShare()->key_stat_version++;
 
387
    file->s->key_stat_version++;
361
388
  }
362
389
  return res;
363
390
}
367
394
                            enum ha_rkey_function find_flag)
368
395
{
369
396
  assert(inited==INDEX);
370
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
397
  ha_statistic_increment(&SSV::ha_read_key_count);
371
398
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
372
 
  getTable()->status = error ? STATUS_NOT_FOUND : 0;
 
399
  table->status = error ? STATUS_NOT_FOUND : 0;
373
400
  return error;
374
401
}
375
402
 
377
404
                                 key_part_map keypart_map)
378
405
{
379
406
  assert(inited==INDEX);
380
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
407
  ha_statistic_increment(&SSV::ha_read_key_count);
381
408
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
382
409
                       HA_READ_PREFIX_LAST);
383
 
  getTable()->status= error ? STATUS_NOT_FOUND : 0;
 
410
  table->status= error ? STATUS_NOT_FOUND : 0;
384
411
  return error;
385
412
}
386
413
 
388
415
                                key_part_map keypart_map,
389
416
                                enum ha_rkey_function find_flag)
390
417
{
391
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
418
  ha_statistic_increment(&SSV::ha_read_key_count);
392
419
  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
393
 
  getTable()->status = error ? STATUS_NOT_FOUND : 0;
 
420
  table->status = error ? STATUS_NOT_FOUND : 0;
394
421
  return error;
395
422
}
396
423
 
397
424
int ha_heap::index_next(unsigned char * buf)
398
425
{
399
426
  assert(inited==INDEX);
400
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
427
  ha_statistic_increment(&SSV::ha_read_next_count);
401
428
  int error=heap_rnext(file,buf);
402
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
429
  table->status=error ? STATUS_NOT_FOUND: 0;
403
430
  return error;
404
431
}
405
432
 
406
433
int ha_heap::index_prev(unsigned char * buf)
407
434
{
408
435
  assert(inited==INDEX);
409
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
436
  ha_statistic_increment(&SSV::ha_read_prev_count);
410
437
  int error=heap_rprev(file,buf);
411
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
438
  table->status=error ? STATUS_NOT_FOUND: 0;
412
439
  return error;
413
440
}
414
441
 
415
442
int ha_heap::index_first(unsigned char * buf)
416
443
{
417
444
  assert(inited==INDEX);
418
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
445
  ha_statistic_increment(&SSV::ha_read_first_count);
419
446
  int error=heap_rfirst(file, buf, active_index);
420
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
447
  table->status=error ? STATUS_NOT_FOUND: 0;
421
448
  return error;
422
449
}
423
450
 
424
451
int ha_heap::index_last(unsigned char * buf)
425
452
{
426
453
  assert(inited==INDEX);
427
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
454
  ha_statistic_increment(&SSV::ha_read_last_count);
428
455
  int error=heap_rlast(file, buf, active_index);
429
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
456
  table->status=error ? STATUS_NOT_FOUND: 0;
430
457
  return error;
431
458
}
432
459
 
433
 
int ha_heap::doStartTableScan(bool scan)
 
460
int ha_heap::rnd_init(bool scan)
434
461
{
435
462
  return scan ? heap_scan_init(file) : 0;
436
463
}
437
464
 
438
465
int ha_heap::rnd_next(unsigned char *buf)
439
466
{
440
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
467
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
441
468
  int error=heap_scan(file, buf);
442
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
469
  table->status=error ? STATUS_NOT_FOUND: 0;
443
470
  return error;
444
471
}
445
472
 
447
474
{
448
475
  int error;
449
476
  HEAP_PTR heap_position;
450
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
 
477
  ha_statistic_increment(&SSV::ha_read_rnd_count);
451
478
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
452
479
  error=heap_rrnd(file, buf, heap_position);
453
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
480
  table->status=error ? STATUS_NOT_FOUND: 0;
454
481
  return error;
455
482
}
456
483
 
479
506
    have to update the key statistics. Hoping that a table lock is now
480
507
    in place.
481
508
  */
482
 
  if (key_stat_version != file->getShare()->key_stat_version)
 
509
  if (key_stat_version != file->s->key_stat_version)
483
510
    update_key_stats();
484
511
  return 0;
485
512
}
486
513
 
 
514
 
 
515
enum row_type ha_heap::get_row_type() const
 
516
{
 
517
  if (file->s->recordspace.is_variable_size)
 
518
    return ROW_TYPE_DYNAMIC;
 
519
 
 
520
  return ROW_TYPE_FIXED;
 
521
}
 
522
 
487
523
int ha_heap::extra(enum ha_extra_function operation)
488
524
{
489
525
  return heap_extra(file,operation);
499
535
int ha_heap::delete_all_rows()
500
536
{
501
537
  heap_clear(file);
502
 
  if (getTable()->getShare()->getType() == message::Table::STANDARD)
 
538
  if (table->s->tmp_table == NO_TMP_TABLE)
503
539
  {
504
540
    /*
505
541
       We can perform this safely since only one writer at the time is
506
542
       allowed on the table.
507
543
    */
508
 
    file->getShare()->key_stat_version++;
 
544
    file->s->key_stat_version++;
509
545
  }
510
546
  return 0;
511
547
}
619
655
 
620
656
void ha_heap::drop_table(const char *)
621
657
{
622
 
  file->getShare()->delete_on_close= 1;
 
658
  file->s->delete_on_close= 1;
623
659
  close();
624
660
}
625
661
 
626
662
 
627
 
int HeapEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
663
int HeapEngine::doRenameTable(Session*,
 
664
                              const char *from, const char *to)
628
665
{
629
 
  session.getMessageCache().renameTableMessage(from, to);
630
 
  return heap_rename(from.getPath().c_str(), to.getPath().c_str());
 
666
  return heap_rename(from,to);
631
667
}
632
668
 
633
669
 
634
670
ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
635
671
                                  key_range *max_key)
636
672
{
637
 
  KeyInfo *key= &getTable()->key_info[inx];
 
673
  KEY *key=table->key_info+inx;
 
674
  if (key->algorithm == HA_KEY_ALG_BTREE)
 
675
    return hp_rb_records_in_range(file, inx, min_key, max_key);
638
676
 
639
677
  if (!min_key || !max_key ||
640
678
      min_key->length != max_key->length ||
647
685
    return stats.records;
648
686
 
649
687
  /* Assert that info() did run. We need current statistics here. */
650
 
  assert(key_stat_version == file->getShare()->key_stat_version);
 
688
  assert(key_stat_version == file->s->key_stat_version);
651
689
  return key->rec_per_key[key->key_parts-1];
652
690
}
653
691
 
654
 
int HeapEngine::doCreateTable(Session &session,
 
692
int HeapEngine::doCreateTable(Session *session,
 
693
                              const char *table_name,
655
694
                              Table &table_arg,
656
 
                              const TableIdentifier &identifier,
657
695
                              message::Table& create_proto)
658
696
{
659
697
  int error;
660
698
  HP_SHARE *internal_share;
661
 
  const char *table_name= identifier.getPath().c_str();
662
699
 
663
 
  error= heap_create_table(&session, table_name, &table_arg,
 
700
  error= heap_create_table(session, table_name, &table_arg,
664
701
                           false, 
665
702
                           create_proto,
666
703
                           &internal_share);
667
704
 
668
705
  if (error == 0)
669
706
  {
670
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
 
707
    pthread_mutex_lock(&proto_cache_mutex);
 
708
    proto_cache.insert(make_pair(table_name, create_proto));
 
709
    pthread_mutex_unlock(&proto_cache_mutex);
671
710
  }
672
711
 
673
712
  return error;
680
719
                                  message::Table &create_proto,
681
720
                                  HP_SHARE **internal_share)
682
721
{
683
 
  uint32_t key, parts, mem_per_row_keys= 0;
684
 
  uint32_t keys= table_arg->getShare()->sizeKeys();
 
722
  uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
685
723
  uint32_t auto_key= 0, auto_key_type= 0;
686
724
  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;
 
725
  uint32_t column_idx, column_count= table_arg->s->fields;
 
726
  HP_COLUMNDEF *columndef;
 
727
  HP_KEYDEF *keydef;
 
728
  HA_KEYSEG *seg;
 
729
  char buff[FN_REFLEN];
689
730
  int error;
 
731
  TableShare *share= table_arg->s;
690
732
  bool found_real_auto_increment= 0;
691
733
 
692
734
  /* 
695
737
   * can return a number more than that, we trap it here instead of casting
696
738
   * to a truncated integer.
697
739
   */
698
 
  uint64_t num_rows= table_arg->getShare()->getMaxRows();
 
740
  uint64_t num_rows= share->getMaxRows();
699
741
  if (num_rows > UINT32_MAX)
700
742
    return -1;
701
743
 
 
744
  if (!(columndef= (HP_COLUMNDEF*) malloc(column_count * sizeof(HP_COLUMNDEF))))
 
745
    return errno;
 
746
 
 
747
  for (column_idx= 0; column_idx < column_count; column_idx++)
 
748
  {
 
749
    Field* field= *(table_arg->field + column_idx);
 
750
    HP_COLUMNDEF* column= columndef + column_idx;
 
751
    column->type= (uint16_t)field->type();
 
752
    column->length= field->pack_length();
 
753
    column->offset= field->offset(field->table->record[0]);
 
754
 
 
755
    if (field->null_bit)
 
756
    {
 
757
      column->null_bit= field->null_bit;
 
758
      column->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
 
759
    }
 
760
    else
 
761
    {
 
762
      column->null_bit= 0;
 
763
      column->null_pos= 0;
 
764
    }
 
765
 
 
766
    if (field->type() == DRIZZLE_TYPE_VARCHAR)
 
767
    {
 
768
      column->length_bytes= (uint8_t)(((Field_varstring*)field)->length_bytes);
 
769
    }
 
770
    else
 
771
    {
 
772
      column->length_bytes= 0;
 
773
    }
 
774
  }
 
775
 
702
776
  for (key= parts= 0; key < keys; key++)
703
777
    parts+= table_arg->key_info[key].key_parts;
704
778
 
705
 
  keydef.resize(keys);
706
 
  std::vector<HA_KEYSEG> seg_buffer;
707
 
  seg_buffer.resize(parts);
708
 
  HA_KEYSEG *seg= &seg_buffer[0];
 
779
  if (!(keydef= (HP_KEYDEF*) malloc(keys * sizeof(HP_KEYDEF) +
 
780
                                    parts * sizeof(HA_KEYSEG))))
 
781
  {
 
782
    free((void *) columndef);
 
783
    return errno;
 
784
  }
709
785
 
 
786
  seg= reinterpret_cast<HA_KEYSEG*> (keydef + keys);
710
787
  for (key= 0; key < keys; key++)
711
788
  {
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;
 
789
    KEY *pos= table_arg->key_info+key;
 
790
    KEY_PART_INFO *key_part=     pos->key_part;
 
791
    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
715
792
 
716
793
    keydef[key].keysegs=   (uint) pos->key_parts;
717
794
    keydef[key].flag=      (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
718
795
    keydef[key].seg=       seg;
719
796
 
720
 
    mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
797
    switch (pos->algorithm) {
 
798
    case HA_KEY_ALG_UNDEF:
 
799
    case HA_KEY_ALG_HASH:
 
800
      keydef[key].algorithm= HA_KEY_ALG_HASH;
 
801
      mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
802
      break;
 
803
    case HA_KEY_ALG_BTREE:
 
804
      keydef[key].algorithm= HA_KEY_ALG_BTREE;
 
805
      mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
 
806
      break;
 
807
    default:
 
808
      assert(0); // cannot happen
 
809
    }
721
810
 
722
811
    for (; key_part != key_part_end; key_part++, seg++)
723
812
    {
724
813
      Field *field= key_part->field;
725
814
 
 
815
      if (pos->algorithm == HA_KEY_ALG_BTREE)
 
816
        seg->type= field->key_type();
 
817
      else
726
818
      {
727
819
        if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
728
820
            seg->type != HA_KEYTYPE_VARTEXT1 &&
738
830
      next_field_pos= seg->start + seg->length;
739
831
      if (field->type() == DRIZZLE_TYPE_VARCHAR)
740
832
      {
741
 
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->pack_length_no_ptr());
 
833
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
742
834
      }
743
835
 
744
836
      if (next_field_pos > key_part_size) {
745
837
        key_part_size= next_field_pos;
746
838
      }
747
839
 
748
 
      if (field->flags & ENUM_FLAG)
 
840
      if (field->flags & (ENUM_FLAG | SET_FLAG))
749
841
        seg->charset= &my_charset_bin;
750
842
      else
751
843
        seg->charset= field->charset();
752
844
      if (field->null_ptr)
753
845
      {
754
846
        seg->null_bit= field->null_bit;
755
 
        seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->getInsertRecord());
 
847
        seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
756
848
      }
757
849
      else
758
850
      {
761
853
      }
762
854
      if (field->flags & AUTO_INCREMENT_FLAG &&
763
855
          table_arg->found_next_number_field &&
764
 
          key == table_arg->getShare()->next_number_index)
 
856
          key == share->next_number_index)
765
857
      {
766
858
        /*
767
859
          Store key number and type for found auto_increment key
770
862
        auto_key= key+ 1;
771
863
        auto_key_type= field->key_type();
772
864
      }
773
 
      if ((uint)field->position() + 1 > max_key_fieldnr)
 
865
      if ((uint)field->field_index + 1 > max_key_fieldnr)
774
866
      {
775
867
        /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
776
 
        max_key_fieldnr= field->position() + 1;
 
868
        max_key_fieldnr= field->field_index + 1;
777
869
      }
778
870
    }
779
871
  }
780
872
 
781
 
  if (key_part_size < table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3))
 
873
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
782
874
  {
783
875
    /* 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);
 
876
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
785
877
  }
786
878
 
787
879
 
788
880
 
789
881
  if (table_arg->found_next_number_field)
790
882
  {
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;
 
883
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
 
884
    found_real_auto_increment= share->next_number_key_offset == 0;
793
885
  }
794
886
  HP_CREATE_INFO hp_create_info;
795
887
  hp_create_info.auto_key= auto_key;
799
891
  hp_create_info.max_table_size=session->variables.max_heap_table_size;
800
892
  hp_create_info.with_auto_increment= found_real_auto_increment;
801
893
  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);
 
894
  hp_create_info.max_chunk_size= share->block_size;
 
895
  hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
 
896
 
 
897
  error= heap_create(internal::fn_format(buff,table_name,"","",
 
898
                              MY_REPLACE_EXT|MY_UNPACK_FILENAME),
 
899
                    keys, keydef,
 
900
                    column_count, columndef,
 
901
                    max_key_fieldnr, key_part_size,
 
902
                    share->reclength, mem_per_row_keys,
 
903
                    static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
 
904
                    0, // Factor out MIN
 
905
                    &hp_create_info, internal_share);
 
906
 
 
907
  free((unsigned char*) keydef);
 
908
  free((void *) columndef);
812
909
 
813
910
  return (error);
814
911
}
840
937
  "Hash based, stored in memory, useful for temporary tables",
841
938
  PLUGIN_LICENSE_GPL,
842
939
  heap_init,
 
940
  heap_deinit,
 
941
  NULL,                       /* status variables                */
843
942
  NULL,                       /* system variables                */
844
943
  NULL                        /* config options                  */
845
944
}