~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/csv/ha_tina.cc

  • Committer: Brian Aker
  • Date: 2009-05-15 17:06:35 UTC
  • mto: This revision was merged to the branch mainline in revision 1023.
  • Revision ID: brian@gaz-20090515170635-croy1u63a3gqdn9n
Dead convert functions for character sets.

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
60
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
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
91
99
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
92
100
}
93
101
 
94
 
static unsigned char* 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
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;
 
108
class Tina : public StorageEngine
 
109
{
 
110
public:
 
111
  Tina(const string& name_arg)
 
112
   : StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
 
113
                             HTON_NO_PARTITION) {}
 
114
  virtual handler *create(TableShare *table,
 
115
                          MEM_ROOT *mem_root)
 
116
  {
 
117
    return new (mem_root) ha_tina(this, table);
 
118
  }
 
119
};
 
120
 
 
121
static Tina *tina_engine= NULL;
 
122
 
 
123
static int tina_init_func(PluginRegistry &registry)
 
124
{
 
125
 
 
126
  tina_engine= new Tina(engine_name);
 
127
  registry.add(tina_engine);
 
128
 
106
129
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
130
  (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
131
                   (hash_get_key) tina_get_key,0,0);
109
 
  tina_hton->state= SHOW_OPTION_YES;
110
 
  tina_hton->create= tina_create_handler;
111
 
  tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | 
112
 
                     HTON_NO_PARTITION);
113
132
  return 0;
114
133
}
115
134
 
116
 
static int tina_done_func(void *p __attribute__((unused)))
 
135
static int tina_done_func(PluginRegistry &registry)
117
136
{
 
137
  registry.remove(tina_engine);
 
138
  delete tina_engine;
 
139
 
118
140
  hash_free(&tina_open_tables);
119
141
  pthread_mutex_destroy(&tina_mutex);
120
142
 
125
147
/*
126
148
  Simple lock controls.
127
149
*/
128
 
static TINA_SHARE *get_share(const char *table_name,
129
 
                             Table *table __attribute__((unused)))
 
150
static TINA_SHARE *get_share(const char *table_name, Table *)
130
151
{
131
152
  TINA_SHARE *share;
132
153
  char meta_file_name[FN_REFLEN];
162
183
    share->update_file_opened= false;
163
184
    share->tina_write_opened= false;
164
185
    share->data_file_version= 0;
165
 
    my_stpcpy(share->table_name, table_name);
 
186
    strcpy(share->table_name, table_name);
166
187
    fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
188
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
189
    fn_format(meta_file_name, table_name, "", CSM_EXT,
231
252
  unsigned char meta_buffer[META_BUFFER_SIZE];
232
253
  unsigned char *ptr= meta_buffer;
233
254
 
234
 
  my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
 
255
  lseek(meta_file, 0, SEEK_SET);
235
256
  if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
236
257
      != META_BUFFER_SIZE)
237
258
    return(HA_ERR_CRASHED_ON_USAGE);
298
319
  ptr+= 3*sizeof(uint64_t);
299
320
  *ptr= (unsigned char)dirty;
300
321
 
301
 
  my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
 
322
  lseek(meta_file, 0, SEEK_SET);
302
323
  if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
303
324
      != META_BUFFER_SIZE)
304
325
    return(-1);
308
329
  return(0);
309
330
}
310
331
 
311
 
bool ha_tina::check_and_repair(THD *thd)
 
332
bool ha_tina::check_and_repair(Session *session)
312
333
{
313
334
  HA_CHECK_OPT check_opt;
314
335
 
315
336
  check_opt.init();
316
337
 
317
 
  return(repair(thd, &check_opt));
 
338
  return(repair(session, &check_opt));
318
339
}
319
340
 
320
341
 
413
434
}
414
435
 
415
436
 
416
 
static handler *tina_create_handler(handlerton *hton,
417
 
                                    TABLE_SHARE *table, 
418
 
                                    MEM_ROOT *mem_root)
419
 
{
420
 
  return new (mem_root) ha_tina(hton, table);
421
 
}
422
 
 
423
 
 
424
 
ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
425
 
  :handler(hton, table_arg),
 
437
 
 
438
ha_tina::ha_tina(StorageEngine *engine_arg, TableShare *table_arg)
 
439
  :handler(engine_arg, table_arg),
426
440
  /*
427
441
    These definitions are found in handler.h
428
442
    They are not probably completely right.
442
456
  Encode a buffer into the quoted format.
443
457
*/
444
458
 
445
 
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
 
459
int ha_tina::encode_quote(unsigned char *)
446
460
{
447
461
  char attribute_buffer[1024];
448
462
  String attribute(attribute_buffer, sizeof(attribute_buffer),
455
469
    const char *ptr;
456
470
    const char *end_ptr;
457
471
    const bool was_null= (*field)->is_null();
458
 
    
 
472
 
459
473
    /*
460
474
      assistance for backwards compatibility in production builds.
461
475
      note: this will not work for ENUM columns.
467
481
    }
468
482
 
469
483
    (*field)->val_str(&attribute,&attribute);
470
 
    
 
484
 
471
485
    if (was_null)
472
486
      (*field)->set_null();
473
487
 
478
492
 
479
493
      buffer.append('"');
480
494
 
481
 
      while (ptr < end_ptr) 
 
495
      while (ptr < end_ptr)
482
496
      {
483
497
        if (*ptr == '"')
484
498
        {
543
557
      chain_size += DEFAULT_CHAIN_LENGTH;
544
558
      if (chain_alloced)
545
559
      {
546
 
        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
547
 
        if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
548
 
                                            chain_size, MYF(MY_WME))) == NULL)
 
560
        if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
549
561
          return -1;
550
562
      }
551
563
      else
552
564
      {
553
 
        tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
554
 
                                              MYF(MY_WME));
 
565
        tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
 
566
        if (ptr == NULL)
 
567
          return -1;
555
568
        memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
556
569
        chain= ptr;
557
570
        chain_alloced++;
575
588
  off_t end_offset, curr_offset= current_position;
576
589
  int eoln_len;
577
590
  int error;
578
 
  bool read_all;
 
591
  bool read_all= false;
579
592
 
580
593
  free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
581
594
 
588
601
                       local_saved_data_file_length, &eoln_len)) == 0)
589
602
    return(HA_ERR_END_OF_FILE);
590
603
 
591
 
  /* We must read all columns in case a table is opened for update */
592
 
  read_all= !bitmap_is_clear_all(table->write_set);
593
604
  error= HA_ERR_CRASHED_ON_USAGE;
594
605
 
595
606
  memset(buf, 0, table->s->null_bytes);
596
607
 
 
608
  /* We need to first check to see if this is a write (rewrite this to something sane that knows if we are doing an update) */
 
609
  for (Field **field=table->field ; *field ; field++)
 
610
  {
 
611
    if ((*field)->isWriteSet())
 
612
    {
 
613
      read_all= true;
 
614
      break;
 
615
    }
 
616
  }
 
617
 
597
618
  for (Field **field=table->field ; *field ; field++)
598
619
  {
599
620
    char curr_char;
600
 
    
 
621
 
601
622
    buffer.length(0);
602
623
    if (curr_offset >= end_offset)
603
624
      goto err;
645
666
        }
646
667
      }
647
668
    }
648
 
    else 
 
669
    else
649
670
    {
650
671
      for(; curr_offset < end_offset; curr_offset++)
651
672
      {
659
680
      }
660
681
    }
661
682
 
662
 
    if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
 
683
    if (read_all || (*field)->isReadSet())
663
684
    {
664
685
      if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
665
686
                          CHECK_FIELD_WARN))
669
690
        Field_blob *blob= *(Field_blob**) field;
670
691
        unsigned char *src, *tgt;
671
692
        uint32_t length, packlength;
672
 
        
 
693
 
673
694
        packlength= blob->pack_length_no_ptr();
674
695
        length= blob->get_length(blob->ptr);
675
696
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
676
697
        if (src)
677
698
        {
678
699
          tgt= (unsigned char*) alloc_root(&blobroot, length);
679
 
          memcpy(tgt, src, length);
 
700
          memmove(tgt, src, length);
680
701
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
681
702
        }
682
703
      }
710
731
  for CSV engine. For more details see mysys/thr_lock.c
711
732
*/
712
733
 
713
 
void tina_get_status(void* param,
714
 
                     int concurrent_insert __attribute__((unused)))
 
734
void tina_get_status(void* param, int)
715
735
{
716
736
  ha_tina *tina= (ha_tina*) param;
717
737
  tina->get_status();
724
744
}
725
745
 
726
746
/* this should exist and return 0 for concurrent insert to work */
727
 
bool tina_check_status(void* param __attribute__((unused)))
 
747
bool tina_check_status(void *)
728
748
{
729
749
  return 0;
730
750
}
764
784
    For log tables concurrent insert works different. The reason is that
765
785
    log tables are always opened and locked. And as they do not unlock
766
786
    tables, the file length after writes should be updated in a different
767
 
    way. 
 
787
    way.
768
788
*/
769
789
 
770
790
void ha_tina::update_status()
779
799
  this will not be called for every request. Any sort of positions
780
800
  that need to be reset should be kept in the ::extra() call.
781
801
*/
782
 
int ha_tina::open(const char *name, int mode __attribute__((unused)),
783
 
                  uint32_t open_options)
 
802
int ha_tina::open(const char *name, int, uint32_t open_options)
784
803
{
785
804
  if (!(share= get_share(name, table)))
786
 
    return(HA_ERR_OUT_OF_MEM);
 
805
    return(ENOENT);
787
806
 
788
807
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
789
808
  {
836
855
 
837
856
  ha_statistic_increment(&SSV::ha_write_count);
838
857
 
839
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
840
 
    table->timestamp_field->set_time();
841
 
 
842
858
  size= encode_quote(buf);
843
859
 
844
860
  if (!share->tina_write_opened)
890
906
  This will be called in a table scan right before the previous ::rnd_next()
891
907
  call.
892
908
*/
893
 
int ha_tina::update_row(const unsigned char * old_data __attribute__((unused)),
894
 
                        unsigned char * new_data)
 
909
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
895
910
{
896
911
  int size;
897
912
  int rc= -1;
904
919
  size= encode_quote(new_data);
905
920
 
906
921
  /*
907
 
    During update we mark each updating record as deleted 
908
 
    (see the chain_append()) then write new one to the temporary data file. 
 
922
    During update we mark each updating record as deleted
 
923
    (see the chain_append()) then write new one to the temporary data file.
909
924
    At the end of the sequence in the rnd_end() we append all non-marked
910
925
    records from the data file to the temporary data file then rename it.
911
926
    The temp_file_length is used to calculate new data file length.
936
951
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
937
952
  DESC, ASC).
938
953
*/
939
 
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
 
954
int ha_tina::delete_row(const unsigned char *)
940
955
{
941
956
  ha_statistic_increment(&SSV::ha_delete_count);
942
957
 
956
971
 
957
972
/**
958
973
  @brief Initialize the data file.
959
 
  
 
974
 
960
975
  @details Compare the local version of the data file with the shared one.
961
976
  If they differ, there are some changes behind and we have to reopen
962
977
  the data file to make the changes visible.
963
 
  Call @c file_buff->init_buff() at the end to read the beginning of the 
 
978
  Call @c file_buff->init_buff() at the end to read the beginning of the
964
979
  data file into buffer.
965
 
  
 
980
 
966
981
  @retval  0  OK.
967
982
  @retval  1  There was an error.
968
983
*/
1012
1027
 
1013
1028
*/
1014
1029
 
1015
 
int ha_tina::rnd_init(bool scan __attribute__((unused)))
 
1030
int ha_tina::rnd_init(bool)
1016
1031
{
1017
1032
  /* set buffer to the beginning of the file */
1018
1033
  if (share->crashed || init_data_file())
1073
1088
  its just a position. Look at the bdb code if you want to see a case
1074
1089
  where something other then a number is stored.
1075
1090
*/
1076
 
void ha_tina::position(const unsigned char *record __attribute__((unused)))
 
1091
void ha_tina::position(const unsigned char *)
1077
1092
{
1078
1093
  my_store_ptr(ref, ref_length, current_position);
1079
1094
  return;
1097
1112
  Currently this table handler doesn't implement most of the fields
1098
1113
  really needed. SHOW also makes use of this data
1099
1114
*/
1100
 
int ha_tina::info(uint32_t flag __attribute__((unused)))
 
1115
int ha_tina::info(uint32_t)
1101
1116
{
1102
1117
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
 
  if (!records_is_known && stats.records < 2) 
 
1118
  if (!records_is_known && stats.records < 2)
1104
1119
    stats.records= 2;
1105
1120
  return(0);
1106
1121
}
1163
1178
    {
1164
1179
      bool in_hole= get_write_pos(&write_end, ptr);
1165
1180
      off_t write_length= write_end - write_begin;
 
1181
      if ((uint64_t)write_length > SIZE_MAX)
 
1182
      {
 
1183
        goto error;
 
1184
      }
1166
1185
 
1167
1186
      /* if there is something to write, write it */
1168
1187
      if (write_length)
1169
1188
      {
1170
 
        if (my_write(update_temp_file, 
 
1189
        if (my_write(update_temp_file,
1171
1190
                     (unsigned char*) (file_buff->ptr() +
1172
1191
                               (write_begin - file_buff->start())),
1173
 
                     write_length, MYF_RW))
 
1192
                     (size_t)write_length, MYF_RW))
1174
1193
          goto error;
1175
1194
        temp_file_length+= write_length;
1176
1195
      }
1221
1240
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1222
1241
      return(-1);
1223
1242
    /*
1224
 
      As we reopened the data file, increase share->data_file_version 
1225
 
      in order to force other threads waiting on a table lock and  
 
1243
      As we reopened the data file, increase share->data_file_version
 
1244
      in order to force other threads waiting on a table lock and
1226
1245
      have already opened the table to reopen the data file.
1227
1246
      That makes the latest changes become visible to them.
1228
 
      Update local_data_file_version as no need to reopen it in the 
 
1247
      Update local_data_file_version as no need to reopen it in the
1229
1248
      current thread.
1230
1249
    */
1231
1250
    share->data_file_version++;
1236
1255
      Here we record this fact to the meta-file.
1237
1256
    */
1238
1257
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
1239
 
    /* 
1240
 
      Update local_saved_data_file_length with the real length of the 
 
1258
    /*
 
1259
      Update local_saved_data_file_length with the real length of the
1241
1260
      data file.
1242
1261
    */
1243
1262
    local_saved_data_file_length= temp_file_length;
1256
1275
 
1257
1276
  SYNOPSIS
1258
1277
    repair()
1259
 
    thd         The thread, performing repair
 
1278
    session         The thread, performing repair
1260
1279
    check_opt   The options for repair. We do not use it currently.
1261
1280
 
1262
1281
  DESCRIPTION
1269
1288
         rows (after the first bad one) as well.
1270
1289
*/
1271
1290
 
1272
 
int ha_tina::repair(THD* thd,
1273
 
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1291
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1274
1292
{
1275
1293
  char repaired_fname[FN_REFLEN];
1276
1294
  unsigned char *buf;
1288
1306
 
1289
1307
  /* Don't assert in field::val() functions */
1290
1308
  table->use_all_columns();
1291
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1309
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1292
1310
    return(HA_ERR_OUT_OF_MEM);
1293
1311
 
1294
1312
  /* position buffer to the start of the file */
1309
1327
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1310
1328
  while (!(rc= find_current_row(buf)))
1311
1329
  {
1312
 
    thd_inc_row_count(thd);
 
1330
    session_inc_row_count(session);
1313
1331
    rows_repaired++;
1314
1332
    current_position= next_position;
1315
1333
  }
1349
1367
  while (1)
1350
1368
  {
1351
1369
    write_end= std::min(file_buff->end(), current_position);
1352
 
    if ((write_end - write_begin) &&
 
1370
 
 
1371
    off_t write_length= write_end - write_begin;
 
1372
    if ((uint64_t)write_length > SIZE_MAX)
 
1373
    {
 
1374
      return -1;
 
1375
    }
 
1376
    if ((write_length) &&
1353
1377
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
1354
 
                  write_end - write_begin, MYF_RW)))
 
1378
                  (size_t)write_length, MYF_RW)))
1355
1379
      return(-1);
1356
1380
 
1357
1381
    write_begin= write_end;
1415
1439
  Called by the database to lock the table. Keep in mind that this
1416
1440
  is an internal lock.
1417
1441
*/
1418
 
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
 
1442
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1419
1443
                                    THR_LOCK_DATA **to,
1420
1444
                                    enum thr_lock_type lock_type)
1421
1445
{
1425
1449
  return to;
1426
1450
}
1427
1451
 
1428
 
/* 
 
1452
/*
1429
1453
  Create a table. You do not want to leave the table open after a call to
1430
1454
  this (the database will call ::open() if it needs to).
1431
1455
*/
1432
1456
 
1433
 
int ha_tina::create(const char *name, Table *table_arg,
1434
 
                    HA_CREATE_INFO *create_info __attribute__((unused)))
 
1457
int ha_tina::create(const char *name, Table *table_arg, HA_CREATE_INFO *)
1435
1458
{
1436
1459
  char name_buff[FN_REFLEN];
1437
1460
  File create_file;
1447
1470
      return(HA_ERR_UNSUPPORTED);
1448
1471
    }
1449
1472
  }
1450
 
  
 
1473
 
1451
1474
 
1452
1475
  if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1476
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1467
1490
  return(0);
1468
1491
}
1469
1492
 
1470
 
int ha_tina::check(THD* thd,
1471
 
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1493
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1472
1494
{
1473
1495
  int rc= 0;
1474
1496
  unsigned char *buf;
1475
1497
  const char *old_proc_info;
1476
1498
  ha_rows count= share->rows_recorded;
1477
1499
 
1478
 
  old_proc_info= thd_proc_info(thd, "Checking table");
1479
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1500
  old_proc_info= get_session_proc_info(session);
 
1501
  set_session_proc_info(session, "Checking table");
 
1502
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1480
1503
    return(HA_ERR_OUT_OF_MEM);
1481
1504
 
1482
1505
  /* position buffer to the start of the file */
1497
1520
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1498
1521
  while (!(rc= find_current_row(buf)))
1499
1522
  {
1500
 
    thd_inc_row_count(thd);
 
1523
    session_inc_row_count(session);
1501
1524
    count--;
1502
1525
    current_position= next_position;
1503
1526
  }
1504
 
  
 
1527
 
1505
1528
  free_root(&blobroot, MYF(0));
1506
1529
 
1507
1530
  free((char*)buf);
1508
 
  thd_proc_info(thd, old_proc_info);
 
1531
  set_session_proc_info(session, old_proc_info);
1509
1532
 
1510
1533
  if ((rc != HA_ERR_END_OF_FILE) || count)
1511
1534
  {
1517
1540
}
1518
1541
 
1519
1542
 
1520
 
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1521
 
                                         uint32_t table_changes __attribute__((unused)))
1522
 
{
1523
 
  return COMPATIBLE_DATA_YES;
1524
 
}
1525
 
 
1526
 
mysql_declare_plugin(csv)
1527
 
{
1528
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1543
drizzle_declare_plugin(csv)
 
1544
{
1529
1545
  "CSV",
1530
1546
  "1.0",
1531
1547
  "Brian Aker, MySQL AB",
1537
1553
  NULL,                       /* system variables                */
1538
1554
  NULL                        /* config options                  */
1539
1555
}
1540
 
mysql_declare_plugin_end;
 
1556
drizzle_declare_plugin_end;
1541
1557