~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/memory/ha_heap.cc

  • Committer: Andrew Hutchings
  • Date: 2011-01-21 11:23:19 UTC
  • mto: (2100.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2101.
  • Revision ID: andrew@linuxjedi.co.uk-20110121112319-nj1cvg0yt3nnf2rr
Add errors page to drizzle client docs
Add link to specific error in migration docs
Minor changes to migration docs

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