~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/csv/ha_tina.cc

  • Committer: Brian Aker
  • Date: 2009-07-11 19:23:04 UTC
  • mfrom: (1089.1.14 merge)
  • Revision ID: brian@gaz-20090711192304-ootijyl5yf9jq9kd
Merge Brian

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
 
41
41
 -Brian
42
42
*/
43
 
#include <drizzled/common_includes.h>
 
43
#include <drizzled/server_includes.h>
 
44
#include <drizzled/field.h>
 
45
#include <drizzled/field/blob.h>
 
46
#include <drizzled/field/timestamp.h>
 
47
#include <drizzled/error.h>
 
48
#include <drizzled/table.h>
 
49
#include <drizzled/session.h>
 
50
 
44
51
#include "ha_tina.h"
45
52
 
 
53
#include <string>
 
54
 
 
55
using namespace std;
 
56
 
 
57
static const string engine_name("CSV");
46
58
 
47
59
/*
48
 
  uchar + uchar + uint64_t + uint64_t + uint64_t + uint64_t + uchar
 
60
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
49
61
*/
50
 
#define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(uint64_t) \
51
 
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uchar)
 
62
#define META_BUFFER_SIZE sizeof(unsigned char) + sizeof(unsigned char) + sizeof(uint64_t) \
 
63
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(unsigned char)
52
64
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
53
65
#define BLOB_MEMROOT_ALLOC_SIZE 8192
54
66
 
58
70
#define CSM_EXT ".CSM"               // Meta file
59
71
 
60
72
 
61
 
static TINA_SHARE *get_share(const char *table_name, TABLE *table);
 
73
static TINA_SHARE *get_share(const char *table_name, Table *table);
62
74
static int free_share(TINA_SHARE *share);
63
75
static int read_meta_file(File meta_file, ha_rows *rows);
64
76
static int write_meta_file(File meta_file, ha_rows rows, bool dirty);
70
82
/* Stuff for shares */
71
83
pthread_mutex_t tina_mutex;
72
84
static HASH tina_open_tables;
73
 
static handler *tina_create_handler(handlerton *hton,
74
 
                                    TABLE_SHARE *table, 
75
 
                                    MEM_ROOT *mem_root);
76
 
 
77
85
 
78
86
/*****************************************************************************
79
87
 ** TINA tables
82
90
/*
83
91
  Used for sorting chains with qsort().
84
92
*/
85
 
int sort_set (tina_set *a, tina_set *b)
 
93
static int sort_set (tina_set *a, tina_set *b)
86
94
{
87
95
  /*
88
96
    We assume that intervals do not intersect. So, it is enought to compare
91
99
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
92
100
}
93
101
 
94
 
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
95
 
                          bool not_used __attribute__((unused)))
 
102
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length, bool)
96
103
{
97
104
  *length=share->table_name_length;
98
 
  return (uchar*) share->table_name;
 
105
  return (unsigned char*) share->table_name;
99
106
}
100
107
 
101
 
static int tina_init_func(void *p)
102
 
{
103
 
  handlerton *tina_hton;
104
 
 
105
 
  tina_hton= (handlerton *)p;
106
 
  VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
 
108
 
 
109
/*
 
110
  If frm_error() is called in table.cc this is called to find out what file
 
111
  extensions exist for this handler.
 
112
*/
 
113
static const char *ha_tina_exts[] = {
 
114
  CSV_EXT,
 
115
  CSM_EXT,
 
116
  NULL
 
117
};
 
118
 
 
119
class Tina : public StorageEngine
 
120
{
 
121
public:
 
122
  Tina(const string& name_arg)
 
123
   : StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_TEMPORARY_ONLY) {}
 
124
  virtual handler *create(TableShare *table,
 
125
                          MEM_ROOT *mem_root)
 
126
  {
 
127
    return new (mem_root) ha_tina(this, table);
 
128
  }
 
129
 
 
130
  const char **bas_ext() const {
 
131
    return ha_tina_exts;
 
132
  }
 
133
 
 
134
  int createTableImpl(Session *, const char *table_name, Table *table_arg,
 
135
                      HA_CREATE_INFO *);
 
136
 
 
137
};
 
138
 
 
139
static Tina *tina_engine= NULL;
 
140
 
 
141
static int tina_init_func(PluginRegistry &registry)
 
142
{
 
143
 
 
144
  tina_engine= new Tina(engine_name);
 
145
  registry.add(tina_engine);
 
146
 
 
147
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
148
  (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
149
                   (hash_get_key) tina_get_key,0,0);
109
 
  tina_hton->state= SHOW_OPTION_YES;
110
 
  tina_hton->db_type= DB_TYPE_CSV_DB;
111
 
  tina_hton->create= tina_create_handler;
112
 
  tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | 
113
 
                     HTON_NO_PARTITION);
114
150
  return 0;
115
151
}
116
152
 
117
 
static int tina_done_func(void *p __attribute__((unused)))
 
153
static int tina_done_func(PluginRegistry &registry)
118
154
{
 
155
  registry.remove(tina_engine);
 
156
  delete tina_engine;
 
157
 
119
158
  hash_free(&tina_open_tables);
120
159
  pthread_mutex_destroy(&tina_mutex);
121
160
 
126
165
/*
127
166
  Simple lock controls.
128
167
*/
129
 
static TINA_SHARE *get_share(const char *table_name,
130
 
                             TABLE *table __attribute__((unused)))
 
168
static TINA_SHARE *get_share(const char *table_name, Table *)
131
169
{
132
170
  TINA_SHARE *share;
133
171
  char meta_file_name[FN_REFLEN];
134
172
  struct stat file_stat;
135
173
  char *tmp_name;
136
 
  uint length;
 
174
  uint32_t length;
137
175
 
138
176
  pthread_mutex_lock(&tina_mutex);
139
177
  length=(uint) strlen(table_name);
143
181
    initialize its members.
144
182
  */
145
183
  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
146
 
                                        (uchar*) table_name,
 
184
                                        (unsigned char*) table_name,
147
185
                                       length)))
148
186
  {
149
187
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
150
188
                         &share, sizeof(*share),
151
189
                         &tmp_name, length+1,
152
 
                         NullS))
 
190
                         NULL))
153
191
    {
154
192
      pthread_mutex_unlock(&tina_mutex);
155
193
      return NULL;
163
201
    share->update_file_opened= false;
164
202
    share->tina_write_opened= false;
165
203
    share->data_file_version= 0;
166
 
    stpcpy(share->table_name, table_name);
 
204
    strcpy(share->table_name, table_name);
167
205
    fn_format(share->data_file_name, table_name, "", CSV_EXT,
168
206
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
169
207
    fn_format(meta_file_name, table_name, "", CSM_EXT,
173
211
      goto error;
174
212
    share->saved_data_file_length= file_stat.st_size;
175
213
 
176
 
    if (my_hash_insert(&tina_open_tables, (uchar*) share))
 
214
    if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
177
215
      goto error;
178
216
    thr_lock_init(&share->lock);
179
217
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
202
240
 
203
241
error:
204
242
  pthread_mutex_unlock(&tina_mutex);
205
 
  my_free((uchar*) share, MYF(0));
 
243
  free((unsigned char*) share);
206
244
 
207
245
  return NULL;
208
246
}
229
267
 
230
268
static int read_meta_file(File meta_file, ha_rows *rows)
231
269
{
232
 
  uchar meta_buffer[META_BUFFER_SIZE];
233
 
  uchar *ptr= meta_buffer;
 
270
  unsigned char meta_buffer[META_BUFFER_SIZE];
 
271
  unsigned char *ptr= meta_buffer;
234
272
 
235
 
  VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
236
 
  if (my_read(meta_file, (uchar*)meta_buffer, META_BUFFER_SIZE, 0)
 
273
  lseek(meta_file, 0, SEEK_SET);
 
274
  if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
237
275
      != META_BUFFER_SIZE)
238
276
    return(HA_ERR_CRASHED_ON_USAGE);
239
277
 
241
279
    Parse out the meta data, we ignore version at the moment
242
280
  */
243
281
 
244
 
  ptr+= sizeof(uchar)*2; // Move past header
 
282
  ptr+= sizeof(unsigned char)*2; // Move past header
245
283
  *rows= (ha_rows)uint8korr(ptr);
246
284
  ptr+= sizeof(uint64_t); // Move past rows
247
285
  /*
251
289
  ptr+= 3*sizeof(uint64_t);
252
290
 
253
291
  /* check crashed bit and magic number */
254
 
  if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
 
292
  if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
255
293
      ((bool)(*ptr)== true))
256
294
    return(HA_ERR_CRASHED_ON_USAGE);
257
295
 
282
320
 
283
321
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
284
322
{
285
 
  uchar meta_buffer[META_BUFFER_SIZE];
286
 
  uchar *ptr= meta_buffer;
 
323
  unsigned char meta_buffer[META_BUFFER_SIZE];
 
324
  unsigned char *ptr= meta_buffer;
287
325
 
288
 
  *ptr= (uchar)TINA_CHECK_HEADER;
289
 
  ptr+= sizeof(uchar);
290
 
  *ptr= (uchar)TINA_VERSION;
291
 
  ptr+= sizeof(uchar);
 
326
  *ptr= (unsigned char)TINA_CHECK_HEADER;
 
327
  ptr+= sizeof(unsigned char);
 
328
  *ptr= (unsigned char)TINA_VERSION;
 
329
  ptr+= sizeof(unsigned char);
292
330
  int8store(ptr, (uint64_t)rows);
293
331
  ptr+= sizeof(uint64_t);
294
332
  memset(ptr, 0, 3*sizeof(uint64_t));
297
335
     We'll need them later.
298
336
  */
299
337
  ptr+= 3*sizeof(uint64_t);
300
 
  *ptr= (uchar)dirty;
 
338
  *ptr= (unsigned char)dirty;
301
339
 
302
 
  VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
303
 
  if (my_write(meta_file, (uchar *)meta_buffer, META_BUFFER_SIZE, 0)
 
340
  lseek(meta_file, 0, SEEK_SET);
 
341
  if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
304
342
      != META_BUFFER_SIZE)
305
343
    return(-1);
306
344
 
309
347
  return(0);
310
348
}
311
349
 
312
 
bool ha_tina::check_and_repair(THD *thd)
 
350
bool ha_tina::check_and_repair(Session *session)
313
351
{
314
352
  HA_CHECK_OPT check_opt;
315
353
 
316
354
  check_opt.init();
317
355
 
318
 
  return(repair(thd, &check_opt));
 
356
  return(repair(session, &check_opt));
319
357
}
320
358
 
321
359
 
365
403
      share->tina_write_opened= false;
366
404
    }
367
405
 
368
 
    hash_delete(&tina_open_tables, (uchar*) share);
 
406
    hash_delete(&tina_open_tables, (unsigned char*) share);
369
407
    thr_lock_delete(&share->lock);
370
408
    pthread_mutex_destroy(&share->mutex);
371
 
    my_free((uchar*) share, MYF(0));
 
409
    free((unsigned char*) share);
372
410
  }
373
411
  pthread_mutex_unlock(&tina_mutex);
374
412
 
386
424
  '\r''\n' --  DOS\Windows line ending
387
425
*/
388
426
 
389
 
off_t find_eoln_buff(Transparent_file *data_buff, off_t begin,
390
 
                     off_t end, int *eoln_len)
 
427
static off_t find_eoln_buff(Transparent_file *data_buff, off_t begin,
 
428
                            off_t end, int *eoln_len)
391
429
{
392
430
  *eoln_len= 0;
393
431
 
414
452
}
415
453
 
416
454
 
417
 
static handler *tina_create_handler(handlerton *hton,
418
 
                                    TABLE_SHARE *table, 
419
 
                                    MEM_ROOT *mem_root)
420
 
{
421
 
  return new (mem_root) ha_tina(hton, table);
422
 
}
423
 
 
424
 
 
425
 
ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
426
 
  :handler(hton, table_arg),
 
455
 
 
456
ha_tina::ha_tina(StorageEngine *engine_arg, TableShare *table_arg)
 
457
  :handler(engine_arg, table_arg),
427
458
  /*
428
459
    These definitions are found in handler.h
429
460
    They are not probably completely right.
443
474
  Encode a buffer into the quoted format.
444
475
*/
445
476
 
446
 
int ha_tina::encode_quote(uchar *buf __attribute__((unused)))
 
477
int ha_tina::encode_quote(unsigned char *)
447
478
{
448
479
  char attribute_buffer[1024];
449
480
  String attribute(attribute_buffer, sizeof(attribute_buffer),
450
481
                   &my_charset_bin);
451
482
 
452
 
  my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
453
483
  buffer.length(0);
454
484
 
455
485
  for (Field **field=table->field ; *field ; field++)
457
487
    const char *ptr;
458
488
    const char *end_ptr;
459
489
    const bool was_null= (*field)->is_null();
460
 
    
 
490
 
461
491
    /*
462
492
      assistance for backwards compatibility in production builds.
463
493
      note: this will not work for ENUM columns.
468
498
      (*field)->set_notnull();
469
499
    }
470
500
 
 
501
    /* 
 
502
      Since we are needing to "translate" the type into a string we 
 
503
      will need to do a val_str(). This would cause an assert() to
 
504
      normally occur since we are onlying "writing" values.
 
505
    */
 
506
    (*field)->setReadSet();
471
507
    (*field)->val_str(&attribute,&attribute);
472
 
    
 
508
 
473
509
    if (was_null)
474
510
      (*field)->set_null();
475
511
 
480
516
 
481
517
      buffer.append('"');
482
518
 
483
 
      while (ptr < end_ptr) 
 
519
      while (ptr < end_ptr)
484
520
      {
485
521
        if (*ptr == '"')
486
522
        {
524
560
 
525
561
  //buffer.replace(buffer.length(), 0, "\n", 1);
526
562
 
527
 
  dbug_tmp_restore_column_map(table->read_set, org_bitmap);
528
563
  return (buffer.length());
529
564
}
530
565
 
546
581
      chain_size += DEFAULT_CHAIN_LENGTH;
547
582
      if (chain_alloced)
548
583
      {
549
 
        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
550
 
        if ((chain= (tina_set *) my_realloc((uchar*)chain,
551
 
                                            chain_size, MYF(MY_WME))) == NULL)
 
584
        if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
552
585
          return -1;
553
586
      }
554
587
      else
555
588
      {
556
 
        tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
557
 
                                              MYF(MY_WME));
 
589
        tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
 
590
        if (ptr == NULL)
 
591
          return -1;
558
592
        memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
559
593
        chain= ptr;
560
594
        chain_alloced++;
573
607
/*
574
608
  Scans for a row.
575
609
*/
576
 
int ha_tina::find_current_row(uchar *buf)
 
610
int ha_tina::find_current_row(unsigned char *buf)
577
611
{
578
612
  off_t end_offset, curr_offset= current_position;
579
613
  int eoln_len;
580
 
  my_bitmap_map *org_bitmap;
581
614
  int error;
582
 
  bool read_all;
583
615
 
584
616
  free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
585
617
 
592
624
                       local_saved_data_file_length, &eoln_len)) == 0)
593
625
    return(HA_ERR_END_OF_FILE);
594
626
 
595
 
  /* We must read all columns in case a table is opened for update */
596
 
  read_all= !bitmap_is_clear_all(table->write_set);
597
 
  /* Avoid asserts in ::store() for columns that are not going to be updated */
598
 
  org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
599
627
  error= HA_ERR_CRASHED_ON_USAGE;
600
628
 
601
629
  memset(buf, 0, table->s->null_bytes);
603
631
  for (Field **field=table->field ; *field ; field++)
604
632
  {
605
633
    char curr_char;
606
 
    
 
634
 
607
635
    buffer.length(0);
608
636
    if (curr_offset >= end_offset)
609
637
      goto err;
651
679
        }
652
680
      }
653
681
    }
654
 
    else 
 
682
    else
655
683
    {
656
684
      for(; curr_offset < end_offset; curr_offset++)
657
685
      {
665
693
      }
666
694
    }
667
695
 
668
 
    if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
 
696
    if ((*field)->isReadSet() || (*field)->isWriteSet())
669
697
    {
 
698
      /* This masks a bug in the logic for a SELECT * */
 
699
      (*field)->setWriteSet();
670
700
      if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
671
701
                          CHECK_FIELD_WARN))
672
702
        goto err;
 
703
 
673
704
      if ((*field)->flags & BLOB_FLAG)
674
705
      {
675
706
        Field_blob *blob= *(Field_blob**) field;
676
 
        uchar *src, *tgt;
677
 
        uint length, packlength;
678
 
        
 
707
        unsigned char *src, *tgt;
 
708
        uint32_t length, packlength;
 
709
 
679
710
        packlength= blob->pack_length_no_ptr();
680
711
        length= blob->get_length(blob->ptr);
681
712
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
682
713
        if (src)
683
714
        {
684
 
          tgt= (uchar*) alloc_root(&blobroot, length);
685
 
          memcpy(tgt, src, length);
 
715
          tgt= (unsigned char*) alloc_root(&blobroot, length);
 
716
          memmove(tgt, src, length);
686
717
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
687
718
        }
688
719
      }
692
723
  error= 0;
693
724
 
694
725
err:
695
 
  dbug_tmp_restore_column_map(table->write_set, org_bitmap);
696
726
 
697
727
  return(error);
698
728
}
699
729
 
700
730
/*
701
 
  If frm_error() is called in table.cc this is called to find out what file
702
 
  extensions exist for this handler.
703
 
*/
704
 
static const char *ha_tina_exts[] = {
705
 
  CSV_EXT,
706
 
  CSM_EXT,
707
 
  NullS
708
 
};
709
 
 
710
 
const char **ha_tina::bas_ext() const
711
 
{
712
 
  return ha_tina_exts;
713
 
}
714
 
 
715
 
/*
716
731
  Three functions below are needed to enable concurrent insert functionality
717
732
  for CSV engine. For more details see mysys/thr_lock.c
718
733
*/
719
734
 
720
 
void tina_get_status(void* param,
721
 
                     int concurrent_insert __attribute__((unused)))
 
735
void tina_get_status(void* param, int)
722
736
{
723
737
  ha_tina *tina= (ha_tina*) param;
724
738
  tina->get_status();
731
745
}
732
746
 
733
747
/* this should exist and return 0 for concurrent insert to work */
734
 
bool tina_check_status(void* param __attribute__((unused)))
 
748
bool tina_check_status(void *)
735
749
{
736
750
  return 0;
737
751
}
771
785
    For log tables concurrent insert works different. The reason is that
772
786
    log tables are always opened and locked. And as they do not unlock
773
787
    tables, the file length after writes should be updated in a different
774
 
    way. 
 
788
    way.
775
789
*/
776
790
 
777
791
void ha_tina::update_status()
786
800
  this will not be called for every request. Any sort of positions
787
801
  that need to be reset should be kept in the ::extra() call.
788
802
*/
789
 
int ha_tina::open(const char *name, int mode __attribute__((unused)),
790
 
                  uint open_options)
 
803
int ha_tina::open(const char *name, int, uint32_t open_options)
791
804
{
792
805
  if (!(share= get_share(name, table)))
793
 
    return(HA_ERR_OUT_OF_MEM);
 
806
    return(ENOENT);
794
807
 
795
808
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
796
809
  {
834
847
  of the file and appends the data. In an error case it really should
835
848
  just truncate to the original position (this is not done yet).
836
849
*/
837
 
int ha_tina::write_row(uchar * buf)
 
850
int ha_tina::write_row(unsigned char * buf)
838
851
{
839
852
  int size;
840
853
 
843
856
 
844
857
  ha_statistic_increment(&SSV::ha_write_count);
845
858
 
846
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
847
 
    table->timestamp_field->set_time();
848
 
 
849
859
  size= encode_quote(buf);
850
860
 
851
861
  if (!share->tina_write_opened)
853
863
      return(-1);
854
864
 
855
865
   /* use pwrite, as concurrent reader could have changed the position */
856
 
  if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
 
866
  if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
857
867
               MYF(MY_WME | MY_NABP)))
858
868
    return(-1);
859
869
 
897
907
  This will be called in a table scan right before the previous ::rnd_next()
898
908
  call.
899
909
*/
900
 
int ha_tina::update_row(const uchar * old_data __attribute__((unused)),
901
 
                        uchar * new_data)
 
910
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
902
911
{
903
912
  int size;
904
913
  int rc= -1;
911
920
  size= encode_quote(new_data);
912
921
 
913
922
  /*
914
 
    During update we mark each updating record as deleted 
915
 
    (see the chain_append()) then write new one to the temporary data file. 
 
923
    During update we mark each updating record as deleted
 
924
    (see the chain_append()) then write new one to the temporary data file.
916
925
    At the end of the sequence in the rnd_end() we append all non-marked
917
926
    records from the data file to the temporary data file then rename it.
918
927
    The temp_file_length is used to calculate new data file length.
923
932
  if (open_update_temp_file_if_needed())
924
933
    goto err;
925
934
 
926
 
  if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
 
935
  if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
927
936
               MYF(MY_WME | MY_NABP)))
928
937
    goto err;
929
938
  temp_file_length+= size;
943
952
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
944
953
  DESC, ASC).
945
954
*/
946
 
int ha_tina::delete_row(const uchar * buf __attribute__((unused)))
 
955
int ha_tina::delete_row(const unsigned char *)
947
956
{
948
957
  ha_statistic_increment(&SSV::ha_delete_count);
949
958
 
963
972
 
964
973
/**
965
974
  @brief Initialize the data file.
966
 
  
 
975
 
967
976
  @details Compare the local version of the data file with the shared one.
968
977
  If they differ, there are some changes behind and we have to reopen
969
978
  the data file to make the changes visible.
970
 
  Call @c file_buff->init_buff() at the end to read the beginning of the 
 
979
  Call @c file_buff->init_buff() at the end to read the beginning of the
971
980
  data file into buffer.
972
 
  
 
981
 
973
982
  @retval  0  OK.
974
983
  @retval  1  There was an error.
975
984
*/
1019
1028
 
1020
1029
*/
1021
1030
 
1022
 
int ha_tina::rnd_init(bool scan __attribute__((unused)))
 
1031
int ha_tina::rnd_init(bool)
1023
1032
{
1024
1033
  /* set buffer to the beginning of the file */
1025
1034
  if (share->crashed || init_data_file())
1049
1058
  NULL and "". This is ok since this table handler is for spreadsheets and
1050
1059
  they don't know about them either :)
1051
1060
*/
1052
 
int ha_tina::rnd_next(uchar *buf)
 
1061
int ha_tina::rnd_next(unsigned char *buf)
1053
1062
{
1054
1063
  int rc;
1055
1064
 
1080
1089
  its just a position. Look at the bdb code if you want to see a case
1081
1090
  where something other then a number is stored.
1082
1091
*/
1083
 
void ha_tina::position(const uchar *record __attribute__((unused)))
 
1092
void ha_tina::position(const unsigned char *)
1084
1093
{
1085
1094
  my_store_ptr(ref, ref_length, current_position);
1086
1095
  return;
1092
1101
  my_get_ptr() retrieves the data for you.
1093
1102
*/
1094
1103
 
1095
 
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
 
1104
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
1096
1105
{
1097
1106
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1098
1107
  current_position= (off_t)my_get_ptr(pos,ref_length);
1104
1113
  Currently this table handler doesn't implement most of the fields
1105
1114
  really needed. SHOW also makes use of this data
1106
1115
*/
1107
 
int ha_tina::info(uint flag __attribute__((unused)))
 
1116
int ha_tina::info(uint32_t)
1108
1117
{
1109
1118
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
1110
 
  if (!records_is_known && stats.records < 2) 
 
1119
  if (!records_is_known && stats.records < 2)
1111
1120
    stats.records= 2;
1112
1121
  return(0);
1113
1122
}
1122
1131
  if (closest_hole == chain_ptr) /* no more chains */
1123
1132
    *end_pos= file_buff->end();
1124
1133
  else
1125
 
    *end_pos= min(file_buff->end(),
1126
 
                  closest_hole->begin);
 
1134
    *end_pos= std::min(file_buff->end(),
 
1135
                       closest_hole->begin);
1127
1136
  return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1128
1137
}
1129
1138
 
1170
1179
    {
1171
1180
      bool in_hole= get_write_pos(&write_end, ptr);
1172
1181
      off_t write_length= write_end - write_begin;
 
1182
      if ((uint64_t)write_length > SIZE_MAX)
 
1183
      {
 
1184
        goto error;
 
1185
      }
1173
1186
 
1174
1187
      /* if there is something to write, write it */
1175
1188
      if (write_length)
1176
1189
      {
1177
 
        if (my_write(update_temp_file, 
1178
 
                     (uchar*) (file_buff->ptr() +
 
1190
        if (my_write(update_temp_file,
 
1191
                     (unsigned char*) (file_buff->ptr() +
1179
1192
                               (write_begin - file_buff->start())),
1180
 
                     write_length, MYF_RW))
 
1193
                     (size_t)write_length, MYF_RW))
1181
1194
          goto error;
1182
1195
        temp_file_length+= write_length;
1183
1196
      }
1228
1241
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1229
1242
      return(-1);
1230
1243
    /*
1231
 
      As we reopened the data file, increase share->data_file_version 
1232
 
      in order to force other threads waiting on a table lock and  
 
1244
      As we reopened the data file, increase share->data_file_version
 
1245
      in order to force other threads waiting on a table lock and
1233
1246
      have already opened the table to reopen the data file.
1234
1247
      That makes the latest changes become visible to them.
1235
 
      Update local_data_file_version as no need to reopen it in the 
 
1248
      Update local_data_file_version as no need to reopen it in the
1236
1249
      current thread.
1237
1250
    */
1238
1251
    share->data_file_version++;
1243
1256
      Here we record this fact to the meta-file.
1244
1257
    */
1245
1258
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
1246
 
    /* 
1247
 
      Update local_saved_data_file_length with the real length of the 
 
1259
    /*
 
1260
      Update local_saved_data_file_length with the real length of the
1248
1261
      data file.
1249
1262
    */
1250
1263
    local_saved_data_file_length= temp_file_length;
1263
1276
 
1264
1277
  SYNOPSIS
1265
1278
    repair()
1266
 
    thd         The thread, performing repair
 
1279
    session         The thread, performing repair
1267
1280
    check_opt   The options for repair. We do not use it currently.
1268
1281
 
1269
1282
  DESCRIPTION
1276
1289
         rows (after the first bad one) as well.
1277
1290
*/
1278
1291
 
1279
 
int ha_tina::repair(THD* thd,
1280
 
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1292
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1281
1293
{
1282
1294
  char repaired_fname[FN_REFLEN];
1283
 
  uchar *buf;
 
1295
  unsigned char *buf;
1284
1296
  File repair_file;
1285
1297
  int rc;
1286
1298
  ha_rows rows_repaired= 0;
1295
1307
 
1296
1308
  /* Don't assert in field::val() functions */
1297
1309
  table->use_all_columns();
1298
 
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1310
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1299
1311
    return(HA_ERR_OUT_OF_MEM);
1300
1312
 
1301
1313
  /* position buffer to the start of the file */
1316
1328
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1317
1329
  while (!(rc= find_current_row(buf)))
1318
1330
  {
1319
 
    thd_inc_row_count(thd);
 
1331
    session_inc_row_count(session);
1320
1332
    rows_repaired++;
1321
1333
    current_position= next_position;
1322
1334
  }
1323
1335
 
1324
1336
  free_root(&blobroot, MYF(0));
1325
1337
 
1326
 
  my_free((char*)buf, MYF(0));
 
1338
  free((char*)buf);
1327
1339
 
1328
1340
  if (rc == HA_ERR_END_OF_FILE)
1329
1341
  {
1355
1367
  /* write repaired file */
1356
1368
  while (1)
1357
1369
  {
1358
 
    write_end= min(file_buff->end(), current_position);
1359
 
    if ((write_end - write_begin) &&
1360
 
        (my_write(repair_file, (uchar*)file_buff->ptr(),
1361
 
                  write_end - write_begin, MYF_RW)))
 
1370
    write_end= std::min(file_buff->end(), current_position);
 
1371
 
 
1372
    off_t write_length= write_end - write_begin;
 
1373
    if ((uint64_t)write_length > SIZE_MAX)
 
1374
    {
 
1375
      return -1;
 
1376
    }
 
1377
    if ((write_length) &&
 
1378
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
 
1379
                  (size_t)write_length, MYF_RW)))
1362
1380
      return(-1);
1363
1381
 
1364
1382
    write_begin= write_end;
1422
1440
  Called by the database to lock the table. Keep in mind that this
1423
1441
  is an internal lock.
1424
1442
*/
1425
 
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
 
1443
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1426
1444
                                    THR_LOCK_DATA **to,
1427
1445
                                    enum thr_lock_type lock_type)
1428
1446
{
1432
1450
  return to;
1433
1451
}
1434
1452
 
1435
 
/* 
 
1453
/*
1436
1454
  Create a table. You do not want to leave the table open after a call to
1437
1455
  this (the database will call ::open() if it needs to).
1438
1456
*/
1439
1457
 
1440
 
int ha_tina::create(const char *name, TABLE *table_arg,
1441
 
                    HA_CREATE_INFO *create_info __attribute__((unused)))
 
1458
int Tina::createTableImpl(Session *, const char *table_name, Table *table_arg,
 
1459
                          HA_CREATE_INFO *)
1442
1460
{
1443
1461
  char name_buff[FN_REFLEN];
1444
1462
  File create_file;
1454
1472
      return(HA_ERR_UNSUPPORTED);
1455
1473
    }
1456
1474
  }
1457
 
  
1458
 
 
1459
 
  if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
 
1475
 
 
1476
 
 
1477
  if ((create_file= my_create(fn_format(name_buff, table_name, "", CSM_EXT,
1460
1478
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1461
1479
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1462
1480
    return(-1);
1464
1482
  write_meta_file(create_file, 0, false);
1465
1483
  my_close(create_file, MYF(0));
1466
1484
 
1467
 
  if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
 
1485
  if ((create_file= my_create(fn_format(name_buff, table_name, "", CSV_EXT,
1468
1486
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1469
1487
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1470
1488
    return(-1);
1474
1492
  return(0);
1475
1493
}
1476
1494
 
1477
 
int ha_tina::check(THD* thd,
1478
 
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1495
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1479
1496
{
1480
1497
  int rc= 0;
1481
 
  uchar *buf;
 
1498
  unsigned char *buf;
1482
1499
  const char *old_proc_info;
1483
1500
  ha_rows count= share->rows_recorded;
1484
1501
 
1485
 
  old_proc_info= thd_proc_info(thd, "Checking table");
1486
 
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1502
  old_proc_info= get_session_proc_info(session);
 
1503
  set_session_proc_info(session, "Checking table");
 
1504
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1487
1505
    return(HA_ERR_OUT_OF_MEM);
1488
1506
 
1489
1507
  /* position buffer to the start of the file */
1504
1522
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1505
1523
  while (!(rc= find_current_row(buf)))
1506
1524
  {
1507
 
    thd_inc_row_count(thd);
 
1525
    session_inc_row_count(session);
1508
1526
    count--;
1509
1527
    current_position= next_position;
1510
1528
  }
1511
 
  
 
1529
 
1512
1530
  free_root(&blobroot, MYF(0));
1513
1531
 
1514
 
  my_free((char*)buf, MYF(0));
1515
 
  thd_proc_info(thd, old_proc_info);
 
1532
  free((char*)buf);
 
1533
  set_session_proc_info(session, old_proc_info);
1516
1534
 
1517
1535
  if ((rc != HA_ERR_END_OF_FILE) || count)
1518
1536
  {
1524
1542
}
1525
1543
 
1526
1544
 
1527
 
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1528
 
                                         uint table_changes __attribute__((unused)))
1529
 
{
1530
 
  return COMPATIBLE_DATA_YES;
1531
 
}
1532
 
 
1533
 
mysql_declare_plugin(csv)
1534
 
{
1535
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1545
drizzle_declare_plugin(csv)
 
1546
{
1536
1547
  "CSV",
1537
1548
  "1.0",
1538
1549
  "Brian Aker, MySQL AB",
1544
1555
  NULL,                       /* system variables                */
1545
1556
  NULL                        /* config options                  */
1546
1557
}
1547
 
mysql_declare_plugin_end;
 
1558
drizzle_declare_plugin_end;
1548
1559