~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/ha_myisam.cc

  • Committer: Monty Taylor
  • Date: 2009-03-25 21:06:47 UTC
  • mto: This revision was merged to the branch mainline in revision 964.
  • Revision ID: mordred@inaugust.com-20090325210647-7j1tm98gvct3jxsu
Removed legacy_db_type.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
 
17
 
#ifdef USE_PRAGMA_IMPLEMENTATION
18
 
#pragma implementation                          // gcc: Class implementation
19
 
#endif
20
 
 
21
 
#define DRIZZLE_SERVER 1
22
17
 
23
18
#include <drizzled/server_includes.h>
24
19
#include <mysys/my_bit.h>
25
 
#include <myisampack.h>
 
20
#include "myisampack.h"
26
21
#include "ha_myisam.h"
27
22
#include "myisamdef.h"
28
 
#include <drizzled/drizzled_error_messages.h>
 
23
#include <drizzled/util/test.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/errmsg_print.h>
 
26
#include <drizzled/gettext.h>
 
27
#include <drizzled/session.h>
 
28
#include <drizzled/protocol.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/field/timestamp.h>
 
31
 
 
32
#include <string>
 
33
 
 
34
using namespace std;
 
35
 
 
36
static const string engine_name("MyISAM");
29
37
 
30
38
ulong myisam_recover_options= HA_RECOVER_NONE;
 
39
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
 
40
 
 
41
static uint32_t repair_threads;
 
42
static uint32_t block_size;
 
43
static uint64_t max_sort_file_size;
 
44
static uint64_t sort_buffer_size;
31
45
 
32
46
/* bits in myisam_recover_options */
33
47
const char *myisam_recover_names[] =
34
48
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", NULL};
35
49
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
36
 
                                 myisam_recover_names, NULL};
 
50
                                 myisam_recover_names, NULL};
37
51
 
38
52
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
39
53
                                           "nulls_ignored", NULL};
46
60
** MyISAM tables
47
61
*****************************************************************************/
48
62
 
49
 
static handler *myisam_create_handler(handlerton *hton,
50
 
                                      TABLE_SHARE *table, 
51
 
                                      MEM_ROOT *mem_root)
 
63
class MyisamEngine : public StorageEngine
52
64
{
53
 
  return new (mem_root) ha_myisam(hton, table);
54
 
}
 
65
public:
 
66
  MyisamEngine(string name_arg) : StorageEngine(name_arg) {}
 
67
 
 
68
  virtual handler *create(TABLE_SHARE *table,
 
69
                          MEM_ROOT *mem_root)
 
70
  {
 
71
    return new (mem_root) ha_myisam(this, table);
 
72
  }
 
73
};
55
74
 
56
75
// collect errors printed by mi_check routines
57
76
 
58
77
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
59
 
                               const char *fmt, va_list args)
 
78
                               const char *fmt, va_list args)
60
79
{
61
 
  THD* thd = (THD*)param->thd;
62
 
  Protocol *protocol= thd->protocol;
 
80
  Session* session = (Session*)param->session;
 
81
  Protocol *protocol= session->protocol;
63
82
  uint32_t length, msg_length;
64
83
  char msgbuf[MI_MAX_MSG_BUF];
65
84
  char name[NAME_LEN*2+2];
67
86
  msg_length= vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
68
87
  msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
69
88
 
70
 
  if (!thd->vio_ok())
 
89
  if (!session->drizzleclient_vio_ok())
71
90
  {
72
 
    sql_print_error(msgbuf);
 
91
    errmsg_printf(ERRMSG_LVL_ERROR, "%s",msgbuf);
73
92
    return;
74
93
  }
75
94
 
79
98
    my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
80
99
    return;
81
100
  }
82
 
  length=(uint) (strxmov(name, param->db_name,".",param->table_name,NULL) -
83
 
                 name);
 
101
  length= sprintf(name,"%s.%s",param->db_name,param->table_name);
 
102
 
84
103
  /*
85
104
    TODO: switch from protocol to push_warning here. The main reason we didn't
86
105
    it yet is parallel repair. Due to following trace:
95
114
  protocol->store(msg_type, system_charset_info);
96
115
  protocol->store(msgbuf, msg_length, system_charset_info);
97
116
  if (protocol->write())
98
 
    sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
 
117
    errmsg_printf(ERRMSG_LVL_ERROR, "Failed on drizzleclient_net_write, writing to stderr instead: %s\n",
99
118
                    msgbuf);
100
119
  return;
101
120
}
212
231
  record= table_arg->record[0];
213
232
  recpos= 0;
214
233
  recinfo_pos= recinfo;
215
 
  while (recpos < (uint) share->reclength)
 
234
  while (recpos < (uint) share->stored_rec_length)
216
235
  {
217
236
    Field **field, *found= 0;
218
237
    minpos= share->reclength;
393
412
volatile int *killed_ptr(MI_CHECK *param)
394
413
{
395
414
  /* In theory Unsafe conversion, but should be ok for now */
396
 
  return (int*) &(((THD *)(param->thd))->killed);
 
415
  return (int*) &(((Session *)(param->session))->killed);
397
416
}
398
417
 
399
418
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
442
461
void _mi_report_crashed(MI_INFO *file, const char *message,
443
462
                        const char *sfile, uint32_t sline)
444
463
{
445
 
  THD *cur_thd;
 
464
  Session *cur_session;
446
465
  LIST *element;
447
466
  pthread_mutex_lock(&file->s->intern_lock);
448
 
  if ((cur_thd= (THD*) file->in_use.data))
449
 
    sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id,
 
467
  if ((cur_session= (Session*) file->in_use.data))
 
468
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from thread_id=%"PRIu64", %s:%d"),
 
469
                    cur_session->thread_id,
450
470
                    sfile, sline);
451
471
  else
452
 
    sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline);
 
472
    errmsg_printf(ERRMSG_LVL_ERROR, _("Got an error from unknown thread, %s:%d"), sfile, sline);
453
473
  if (message)
454
 
    sql_print_error("%s", message);
 
474
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", message);
455
475
  for (element= file->s->in_use; element; element= list_rest(element))
456
476
  {
457
 
    sql_print_error("%s", "Unknown thread accessing table");
 
477
    errmsg_printf(ERRMSG_LVL_ERROR, "%s", _("Unknown thread accessing table"));
458
478
  }
459
479
  pthread_mutex_unlock(&file->s->intern_lock);
460
480
}
461
481
 
462
482
}
463
483
 
464
 
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
465
 
  :handler(hton, table_arg), file(0),
 
484
ha_myisam::ha_myisam(StorageEngine *engine_arg, TABLE_SHARE *table_arg)
 
485
  :handler(engine_arg, table_arg), file(0),
466
486
  int_table_flags(HA_NULL_IN_KEY |
467
487
                  HA_BINLOG_ROW_CAPABLE |
468
488
                  HA_BINLOG_STMT_CAPABLE |
499
519
}
500
520
 
501
521
 
502
 
const char *ha_myisam::index_type(uint32_t key_number __attribute__((unused)))
 
522
const char *ha_myisam::index_type(uint32_t )
503
523
{
504
524
  return "BTREE";
505
525
}
547
567
      /* purecov: end */
548
568
    }
549
569
  }
550
 
  
 
570
 
551
571
  if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
552
572
    mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0);
553
573
 
558
578
    int_table_flags|=HA_REC_NOT_IN_SEQ;
559
579
  if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
560
580
    int_table_flags|=HA_HAS_CHECKSUM;
561
 
  
 
581
 
562
582
  keys_with_parts.clear_all();
563
583
  for (i= 0; i < table->s->keys; i++)
564
584
  {
600
620
{
601
621
  ha_statistic_increment(&SSV::ha_write_count);
602
622
 
603
 
  /* If we have a timestamp column, update it to the current time */
604
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
605
 
    table->timestamp_field->set_time();
606
 
 
607
623
  /*
608
624
    If we have an auto_increment column and we are writing a changed row
609
625
    or a new row, then update the auto_increment value in the record.
617
633
  return mi_write(file,buf);
618
634
}
619
635
 
620
 
int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
 
636
int ha_myisam::check(Session* session, HA_CHECK_OPT* check_opt)
621
637
{
622
638
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
623
639
  int error;
624
640
  MI_CHECK param;
625
641
  MYISAM_SHARE* share = file->s;
626
 
  const char *old_proc_info= thd->get_proc_info();
 
642
  const char *old_proc_info= session->get_proc_info();
627
643
 
628
 
  thd_proc_info(thd, "Checking table");
 
644
  session->set_proc_info("Checking table");
629
645
  myisamchk_init(&param);
630
 
  param.thd = thd;
 
646
  param.session = session;
631
647
  param.op_name =   "check";
632
648
  param.db_name=    table->s->db.str;
633
649
  param.table_name= table->alias;
634
650
  param.testflag = check_opt->flags | T_CHECK | T_SILENT;
635
 
  param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
 
651
  param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
636
652
 
637
653
  if (!(table->db_stat & HA_READ_ONLY))
638
654
    param.testflag|= T_STATISTICS;
693
709
           HA_STATUS_CONST);
694
710
    }
695
711
  }
696
 
  else if (!mi_is_crashed(file) && !thd->killed)
 
712
  else if (!mi_is_crashed(file) && !session->killed)
697
713
  {
698
714
    mi_mark_crashed(file);
699
715
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
700
716
  }
701
717
 
702
 
  thd_proc_info(thd, old_proc_info);
 
718
  session->set_proc_info(old_proc_info);
703
719
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
704
720
}
705
721
 
710
726
  two threads may do an analyze at the same time!
711
727
*/
712
728
 
713
 
int ha_myisam::analyze(THD *thd,
714
 
                       HA_CHECK_OPT* check_opt __attribute__((unused)))
 
729
int ha_myisam::analyze(Session *session,
 
730
                       HA_CHECK_OPT* )
715
731
{
716
732
  int error=0;
717
733
  MI_CHECK param;
718
734
  MYISAM_SHARE* share = file->s;
719
735
 
720
736
  myisamchk_init(&param);
721
 
  param.thd = thd;
 
737
  param.session = session;
722
738
  param.op_name=    "analyze";
723
739
  param.db_name=    table->s->db.str;
724
740
  param.table_name= table->alias;
725
741
  param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
726
742
                   T_DONT_CHECK_CHECKSUM);
727
743
  param.using_global_keycache = 1;
728
 
  param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
 
744
  param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
729
745
 
730
746
  if (!(share->state.changed & STATE_NOT_ANALYZED))
731
747
    return HA_ADMIN_ALREADY_DONE;
737
753
    error=update_state_info(&param,file,UPDATE_STAT);
738
754
    pthread_mutex_unlock(&share->intern_lock);
739
755
  }
740
 
  else if (!mi_is_crashed(file) && !thd->killed)
 
756
  else if (!mi_is_crashed(file) && !session->killed)
741
757
    mi_mark_crashed(file);
742
758
  return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
743
759
}
744
760
 
745
761
 
746
 
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
 
762
int ha_myisam::repair(Session* session, HA_CHECK_OPT *check_opt)
747
763
{
748
764
  int error;
749
765
  MI_CHECK param;
752
768
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
753
769
 
754
770
  myisamchk_init(&param);
755
 
  param.thd = thd;
 
771
  param.session = session;
756
772
  param.op_name=  "repair";
757
773
  param.testflag= ((check_opt->flags & ~(T_EXTEND)) |
758
774
                   T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
759
775
                   (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
760
 
  param.sort_buffer_length=  check_opt->sort_buffer_size;
 
776
  param.sort_buffer_length=  (size_t)sort_buffer_size;
 
777
 
 
778
  // Release latches since this can take a long time
 
779
  ha_release_temporary_latches(session);
 
780
 
761
781
  start_records=file->state->records;
762
 
  while ((error=repair(thd,param,0)) && param.retry_repair)
 
782
  while ((error=repair(session,param,0)) && param.retry_repair)
763
783
  {
764
784
    param.retry_repair=0;
765
785
    if (test_all_bits(param.testflag,
766
786
                      (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
767
787
    {
768
788
      param.testflag&= ~T_RETRY_WITHOUT_QUICK;
769
 
      sql_print_information("Retrying repair of: '%s' without quick",
 
789
      errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' without quick",
770
790
                            table->s->path.str);
771
791
      continue;
772
792
    }
774
794
    if ((param.testflag & T_REP_BY_SORT))
775
795
    {
776
796
      param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
777
 
      sql_print_information("Retrying repair of: '%s' with keycache",
 
797
      errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' with keycache",
778
798
                            table->s->path.str);
779
799
      continue;
780
800
    }
784
804
      !(check_opt->flags & T_VERY_SILENT))
785
805
  {
786
806
    char llbuff[22],llbuff2[22];
787
 
    sql_print_information("Found %s of %s rows when repairing '%s'",
 
807
    errmsg_printf(ERRMSG_LVL_INFO, "Found %s of %s rows when repairing '%s'",
788
808
                          llstr(file->state->records, llbuff),
789
809
                          llstr(start_records, llbuff2),
790
810
                          table->s->path.str);
792
812
  return error;
793
813
}
794
814
 
795
 
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
 
815
int ha_myisam::optimize(Session* session, HA_CHECK_OPT *check_opt)
796
816
{
797
817
  int error;
798
818
  if (!file) return HA_ADMIN_INTERNAL_ERROR;
799
819
  MI_CHECK param;
800
820
 
801
821
  myisamchk_init(&param);
802
 
  param.thd = thd;
 
822
  param.session = session;
803
823
  param.op_name= "optimize";
804
824
  param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
805
825
                   T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
806
 
  param.sort_buffer_length=  check_opt->sort_buffer_size;
807
 
  if ((error= repair(thd,param,1)) && param.retry_repair)
 
826
  param.sort_buffer_length= (size_t)sort_buffer_size;
 
827
  if ((error= repair(session,param,1)) && param.retry_repair)
808
828
  {
809
 
    sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
 
829
    errmsg_printf(ERRMSG_LVL_WARN, "Warning: Optimize table got errno %d on %s.%s, retrying",
810
830
                      my_errno, param.db_name, param.table_name);
811
831
    param.testflag&= ~T_REP_BY_SORT;
812
 
    error= repair(thd,param,1);
 
832
    error= repair(session,param,1);
813
833
  }
814
834
  return error;
815
835
}
816
836
 
817
837
 
818
 
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool do_optimize)
 
838
int ha_myisam::repair(Session *session, MI_CHECK &param, bool do_optimize)
819
839
{
820
840
  int error=0;
821
 
  uint32_t local_testflag=param.testflag;
 
841
  uint32_t local_testflag= param.testflag;
822
842
  bool optimize_done= !do_optimize, statistics_done=0;
823
 
  const char *old_proc_info= thd->get_proc_info();
 
843
  const char *old_proc_info= session->get_proc_info();
824
844
  char fixed_name[FN_REFLEN];
825
845
  MYISAM_SHARE* share = file->s;
826
846
  ha_rows rows= file->state->records;
835
855
  */
836
856
  if (file->dfile == -1)
837
857
  {
838
 
    sql_print_information("Retrying repair of: '%s' failed. "
 
858
    errmsg_printf(ERRMSG_LVL_INFO, "Retrying repair of: '%s' failed. "
839
859
                          "Please try REPAIR EXTENDED or myisamchk",
840
860
                          table->s->path.str);
841
861
    return(HA_ADMIN_FAILED);
845
865
  param.table_name= table->alias;
846
866
  param.tmpfile_createflag = O_RDWR | O_TRUNC;
847
867
  param.using_global_keycache = 1;
848
 
  param.thd= thd;
849
 
  param.tmpdir= &mysql_tmpdir_list;
 
868
  param.session= session;
850
869
  param.out_flag= 0;
851
 
  my_stpcpy(fixed_name,file->filename);
 
870
  param.sort_buffer_length= (size_t)sort_buffer_size;
 
871
  strcpy(fixed_name,file->filename);
852
872
 
853
873
  // Don't lock tables if we have used LOCK Table
854
 
  if (!thd->locked_tables && 
 
874
  if (!session->locked_tables &&
855
875
      mi_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
856
876
  {
857
877
    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
873
893
      local_testflag|= T_STATISTICS;
874
894
      param.testflag|= T_STATISTICS;            // We get this for free
875
895
      statistics_done=1;
876
 
      if (thd->variables.myisam_repair_threads>1)
 
896
      if (repair_threads > 1)
877
897
      {
878
898
        char buf[40];
879
899
        /* TODO: respect myisam_repair_threads variable */
880
900
        snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
881
 
        thd_proc_info(thd, buf);
 
901
        session->set_proc_info(buf);
882
902
        error = mi_repair_parallel(&param, file, fixed_name,
883
903
            param.testflag & T_QUICK);
884
 
        thd_proc_info(thd, "Repair done"); // to reset proc_info, as
 
904
        session->set_proc_info("Repair done"); // to reset proc_info, as
885
905
                                      // it was pointing to local buffer
886
906
      }
887
907
      else
888
908
      {
889
 
        thd_proc_info(thd, "Repair by sorting");
 
909
        session->set_proc_info("Repair by sorting");
890
910
        error = mi_repair_by_sort(&param, file, fixed_name,
891
911
            param.testflag & T_QUICK);
892
912
      }
893
913
    }
894
914
    else
895
915
    {
896
 
      thd_proc_info(thd, "Repair with keycache");
 
916
      session->set_proc_info("Repair with keycache");
897
917
      param.testflag &= ~T_REP_BY_SORT;
898
918
      error=  mi_repair(&param, file, fixed_name,
899
919
                        param.testflag & T_QUICK);
907
927
        (share->state.changed & STATE_NOT_SORTED_PAGES))
908
928
    {
909
929
      optimize_done=1;
910
 
      thd_proc_info(thd, "Sorting index");
 
930
      session->set_proc_info("Sorting index");
911
931
      error=mi_sort_index(&param,file,fixed_name);
912
932
    }
913
933
    if (!statistics_done && (local_testflag & T_STATISTICS))
915
935
      if (share->state.changed & STATE_NOT_ANALYZED)
916
936
      {
917
937
        optimize_done=1;
918
 
        thd_proc_info(thd, "Analyzing");
 
938
        session->set_proc_info("Analyzing");
919
939
        error = chk_key(&param, file);
920
940
      }
921
941
      else
922
942
        local_testflag&= ~T_STATISTICS;         // Don't update statistics
923
943
    }
924
944
  }
925
 
  thd_proc_info(thd, "Saving state");
 
945
  session->set_proc_info("Saving state");
926
946
  if (!error)
927
947
  {
928
948
    if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
960
980
    file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
961
981
    update_state_info(&param, file, 0);
962
982
  }
963
 
  thd_proc_info(thd, old_proc_info);
964
 
  if (!thd->locked_tables)
 
983
  session->set_proc_info(old_proc_info);
 
984
  if (!session->locked_tables)
965
985
    mi_lock_database(file,F_UNLCK);
966
986
  return(error ? HA_ADMIN_FAILED :
967
987
              !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
972
992
  Assign table indexes to a specific key cache.
973
993
*/
974
994
 
975
 
int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt)
 
995
int ha_myisam::assign_to_keycache(Session* session, HA_CHECK_OPT *check_opt)
976
996
{
977
997
  KEY_CACHE *new_key_cache= check_opt->key_cache;
978
998
  const char *errmsg= 0;
990
1010
    map= table->keys_in_use_for_query.to_uint64_t();
991
1011
 
992
1012
  if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
993
 
  { 
 
1013
  {
994
1014
    char buf[STRING_BUFFER_USUAL_SIZE];
995
1015
    snprintf(buf, sizeof(buf),
996
1016
                "Failed to flush to index file (errno: %d)", error);
1003
1023
    /* Send error to user */
1004
1024
    MI_CHECK param;
1005
1025
    myisamchk_init(&param);
1006
 
    param.thd= thd;
 
1026
    param.session= session;
1007
1027
    param.op_name=    "assign_to_keycache";
1008
1028
    param.db_name=    table->s->db.str;
1009
1029
    param.table_name= table->s->table_name.str;
1107
1127
  }
1108
1128
  else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
1109
1129
  {
1110
 
    THD *thd=current_thd;
 
1130
    Session *session=current_session;
1111
1131
    MI_CHECK param;
1112
 
    const char *save_proc_info= thd->get_proc_info();
1113
 
    thd_proc_info(thd, "Creating index");
 
1132
    const char *save_proc_info= session->get_proc_info();
 
1133
    session->set_proc_info("Creating index");
1114
1134
    myisamchk_init(&param);
1115
1135
    param.op_name= "recreating_index";
1116
1136
    param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
1117
1137
                     T_CREATE_MISSING_KEYS);
1118
1138
    param.myf_rw&= ~MY_WAIT_IF_FULL;
1119
 
    param.sort_buffer_length=  thd->variables.myisam_sort_buff_size;
1120
 
    param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
1121
 
    param.tmpdir=&mysql_tmpdir_list;
1122
 
    if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
 
1139
    param.sort_buffer_length=  (size_t)sort_buffer_size;
 
1140
    param.stats_method= (enum_mi_stats_method)session->variables.myisam_stats_method;
 
1141
    if ((error= (repair(session,param,0) != HA_ADMIN_OK)) && param.retry_repair)
1123
1142
    {
1124
 
      sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
 
1143
      errmsg_printf(ERRMSG_LVL_WARN, "Warning: Enabling keys got errno %d on %s.%s, retrying",
1125
1144
                        my_errno, param.db_name, param.table_name);
1126
1145
      /* Repairing by sort failed. Now try standard repair method. */
1127
1146
      param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
1128
 
      error= (repair(thd,param,0) != HA_ADMIN_OK);
 
1147
      error= (repair(session,param,0) != HA_ADMIN_OK);
1129
1148
      /*
1130
1149
        If the standard repair succeeded, clear all error messages which
1131
1150
        might have been set by the first repair. They can still be seen
1132
1151
        with SHOW WARNINGS then.
1133
1152
      */
1134
1153
      if (! error)
1135
 
        thd->clear_error();
 
1154
        session->clear_error();
1136
1155
    }
1137
1156
    info(HA_STATUS_CONST);
1138
 
    thd_proc_info(thd, save_proc_info);
 
1157
    session->set_proc_info(save_proc_info);
1139
1158
  }
1140
1159
  else
1141
1160
  {
1163
1182
 
1164
1183
int ha_myisam::indexes_are_disabled(void)
1165
1184
{
1166
 
  
 
1185
 
1167
1186
  return mi_indexes_are_disabled(file);
1168
1187
}
1169
1188
 
1184
1203
 
1185
1204
void ha_myisam::start_bulk_insert(ha_rows rows)
1186
1205
{
1187
 
  THD *thd= current_thd;
1188
 
  ulong size= cmin(thd->variables.read_buff_size,
 
1206
  Session *session= current_session;
 
1207
  ulong size= cmin(session->variables.read_buff_size,
1189
1208
                  (ulong) (table->s->avg_row_length*rows));
1190
1209
 
1191
1210
  /* don't enable row cache if too few rows */
1208
1227
    if (!file->bulk_insert &&
1209
1228
        (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
1210
1229
    {
1211
 
      mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
 
1230
      mi_init_bulk_insert(file,
 
1231
                          (size_t)session->variables.bulk_insert_buff_size,
 
1232
                          rows);
1212
1233
    }
1213
1234
 
1214
1235
  return;
1236
1257
}
1237
1258
 
1238
1259
 
1239
 
bool ha_myisam::check_and_repair(THD *thd)
 
1260
bool ha_myisam::check_and_repair(Session *session)
1240
1261
{
1241
1262
  int error=0;
1242
1263
  int marked_crashed;
1249
1270
  // Don't use quick if deleted rows
1250
1271
  if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
1251
1272
    check_opt.flags|=T_QUICK;
1252
 
  sql_print_warning("Checking table:   '%s'",table->s->path.str);
 
1273
  errmsg_printf(ERRMSG_LVL_WARN, "Checking table:   '%s'",table->s->path.str);
1253
1274
 
1254
 
  old_query= thd->query;
1255
 
  old_query_length= thd->query_length;
 
1275
  old_query= session->query;
 
1276
  old_query_length= session->query_length;
1256
1277
  pthread_mutex_lock(&LOCK_thread_count);
1257
 
  thd->query=        table->s->table_name.str;
1258
 
  thd->query_length= table->s->table_name.length;
 
1278
  session->query=        table->s->table_name.str;
 
1279
  session->query_length= table->s->table_name.length;
1259
1280
  pthread_mutex_unlock(&LOCK_thread_count);
1260
1281
 
1261
 
  if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
 
1282
  if ((marked_crashed= mi_is_crashed(file)) || check(session, &check_opt))
1262
1283
  {
1263
 
    sql_print_warning("Recovering table: '%s'",table->s->path.str);
 
1284
    errmsg_printf(ERRMSG_LVL_WARN, "Recovering table: '%s'",table->s->path.str);
1264
1285
    check_opt.flags=
1265
1286
      ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
1266
1287
       (marked_crashed                             ? 0 : T_QUICK) |
1267
1288
       (myisam_recover_options & HA_RECOVER_FORCE  ? 0 : T_SAFE_REPAIR) |
1268
1289
       T_AUTO_REPAIR);
1269
 
    if (repair(thd, &check_opt))
 
1290
    if (repair(session, &check_opt))
1270
1291
      error=1;
1271
1292
  }
1272
1293
  pthread_mutex_lock(&LOCK_thread_count);
1273
 
  thd->query= old_query;
1274
 
  thd->query_length= old_query_length;
 
1294
  session->query= old_query;
 
1295
  session->query_length= old_query_length;
1275
1296
  pthread_mutex_unlock(&LOCK_thread_count);
1276
1297
  return(error);
1277
1298
}
1317
1338
#endif
1318
1339
 
1319
1340
 
1320
 
int ha_myisam::index_init(uint32_t idx, bool sorted __attribute__((unused)))
1321
 
 
1341
int ha_myisam::index_init(uint32_t idx, bool )
 
1342
{
1322
1343
  active_index=idx;
1323
1344
  //in_range_read= false;
1324
1345
  if (pushed_idx_cond_keyno == idx)
1325
1346
    mi_set_index_cond_func(file, index_cond_func_myisam, this);
1326
 
  return 0; 
 
1347
  return 0;
1327
1348
}
1328
1349
 
1329
1350
 
1334
1355
  mi_set_index_cond_func(file, NULL, 0);
1335
1356
  in_range_check_pushed_down= false;
1336
1357
  ds_mrr.dsmrr_close();
1337
 
  return 0; 
 
1358
  return 0;
 
1359
}
 
1360
 
 
1361
 
 
1362
uint32_t ha_myisam::index_flags(uint32_t inx, uint32_t, bool) const
 
1363
{
 
1364
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
 
1365
          0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
 
1366
          HA_READ_ORDER | HA_KEYREAD_ONLY |
 
1367
          (keys_with_parts.is_set(inx)?0:HA_DO_INDEX_COND_PUSHDOWN));
1338
1368
}
1339
1369
 
1340
1370
 
1407
1437
}
1408
1438
 
1409
1439
int ha_myisam::index_next_same(unsigned char *buf,
1410
 
                               const unsigned char *key __attribute__((unused)),
1411
 
                               uint32_t length __attribute__((unused)))
 
1440
                               const unsigned char *,
 
1441
                               uint32_t )
1412
1442
{
1413
1443
  int error;
1414
1444
  assert(inited==INDEX);
1476
1506
}
1477
1507
 
1478
1508
 
1479
 
void ha_myisam::position(const unsigned char *record __attribute__((unused)))
 
1509
void ha_myisam::position(const unsigned char *)
1480
1510
{
1481
1511
  my_off_t row_position= mi_position(file);
1482
1512
  my_store_ptr(ref, ref_length, row_position);
1506
1536
    stats.create_time= misam_info.create_time;
1507
1537
    ref_length= misam_info.reflength;
1508
1538
    share->db_options_in_use= misam_info.options;
1509
 
    stats.block_size= myisam_block_size;        /* record block size */
 
1539
    stats.block_size= block_size;        /* record block size */
1510
1540
 
1511
1541
    /* Update share */
1512
1542
    if (share->tmp_table == NO_TMP_TABLE)
1582
1612
}
1583
1613
 
1584
1614
 
1585
 
int ha_myisam::external_lock(THD *thd, int lock_type)
 
1615
int ha_myisam::external_lock(Session *session, int lock_type)
1586
1616
{
1587
 
  file->in_use.data= thd;
 
1617
  file->in_use.data= session;
1588
1618
  return mi_lock_database(file, !table->s->tmp_table ?
1589
1619
                          lock_type : ((lock_type == F_UNLCK) ?
1590
1620
                                       F_UNLCK : F_EXTRA_LCK));
1591
1621
}
1592
1622
 
1593
 
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd __attribute__((unused)),
 
1623
THR_LOCK_DATA **ha_myisam::store_lock(Session *,
1594
1624
                                      THR_LOCK_DATA **to,
1595
1625
                                      enum thr_lock_type lock_type)
1596
1626
{
1616
1646
                      HA_CREATE_INFO *ha_create_info)
1617
1647
{
1618
1648
  int error;
1619
 
  uint32_t create_flags= 0, records;
 
1649
  uint32_t create_flags= 0, create_records;
1620
1650
  char buff[FN_REFLEN];
1621
1651
  MI_KEYDEF *keydef;
1622
1652
  MI_COLUMNDEF *recinfo;
1623
1653
  MI_CREATE_INFO create_info;
1624
1654
  TABLE_SHARE *share= table_arg->s;
1625
1655
  uint32_t options= share->db_options_in_use;
1626
 
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
 
1656
  if ((error= table2myisam(table_arg, &keydef, &recinfo, &create_records)))
1627
1657
    return(error); /* purecov: inspected */
1628
1658
  memset(&create_info, 0, sizeof(create_info));
1629
1659
  create_info.max_rows= share->max_rows;
1653
1683
  error= mi_create(fn_format(buff, name, "", "",
1654
1684
                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
1655
1685
                   share->keys, keydef,
1656
 
                   records, recinfo,
 
1686
                   create_records, recinfo,
1657
1687
                   0, (MI_UNIQUEDEF*) 0,
1658
1688
                   &create_info, create_flags);
1659
1689
  free((unsigned char*) recinfo);
1667
1697
}
1668
1698
 
1669
1699
 
1670
 
void ha_myisam::get_auto_increment(uint64_t offset __attribute__((unused)),
1671
 
                                   uint64_t increment __attribute__((unused)),
1672
 
                                   uint64_t nb_desired_values __attribute__((unused)),
 
1700
void ha_myisam::get_auto_increment(uint64_t ,
 
1701
                                   uint64_t ,
 
1702
                                   uint64_t ,
1673
1703
                                   uint64_t *first_value,
1674
1704
                                   uint64_t *nb_reserved_values)
1675
1705
{
1730
1760
      HA_READ_KEY_EXACT         Include the key in the range
1731
1761
      HA_READ_AFTER_KEY         Don't include key in range
1732
1762
 
1733
 
    max_key.flag can have one of the following values:  
 
1763
    max_key.flag can have one of the following values:
1734
1764
      HA_READ_BEFORE_KEY        Don't include key in range
1735
1765
      HA_READ_AFTER_KEY         Include all 'end_key' values in the range
1736
1766
 
1754
1784
}
1755
1785
 
1756
1786
 
1757
 
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
 
1787
bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *create_info,
1758
1788
                                           uint32_t table_changes)
1759
1789
{
1760
1790
  uint32_t options= table->s->db_options_in_use;
1761
1791
 
1762
 
  if (info->auto_increment_value != stats.auto_increment_value ||
1763
 
      info->data_file_name != data_file_name ||
1764
 
      info->index_file_name != index_file_name ||
 
1792
  if (create_info->auto_increment_value != stats.auto_increment_value ||
 
1793
      create_info->data_file_name != data_file_name ||
 
1794
      create_info->index_file_name != index_file_name ||
1765
1795
      table_changes == IS_EQUAL_NO ||
1766
1796
      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
1767
1797
    return COMPATIBLE_DATA_NO;
1768
1798
 
1769
1799
  if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
1770
1800
                  HA_OPTION_DELAY_KEY_WRITE)) !=
1771
 
      (info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
 
1801
      (create_info->table_options & (HA_OPTION_PACK_RECORD |
 
1802
                                     HA_OPTION_CHECKSUM |
1772
1803
                              HA_OPTION_DELAY_KEY_WRITE)))
1773
1804
    return COMPATIBLE_DATA_NO;
1774
1805
  return COMPATIBLE_DATA_YES;
1775
1806
}
1776
1807
 
1777
 
int myisam_deinit(void *hton __attribute__((unused)))
 
1808
int myisam_deinit(void *p)
1778
1809
{
 
1810
 
 
1811
  MyisamEngine *engine= static_cast<MyisamEngine *>(p);
 
1812
  delete engine;
 
1813
 
 
1814
  pthread_mutex_destroy(&THR_LOCK_myisam);
 
1815
 
1779
1816
  return mi_panic(HA_PANIC_CLOSE);
1780
1817
}
1781
1818
 
1782
1819
static int myisam_init(void *p)
1783
1820
{
1784
 
  handlerton *myisam_hton;
 
1821
  StorageEngine **engine= static_cast<StorageEngine **>(p);
 
1822
  
 
1823
  *engine= new MyisamEngine(engine_name);
 
1824
  (*engine)->state= SHOW_OPTION_YES;
 
1825
  (*engine)->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1785
1826
 
1786
 
  myisam_hton= (handlerton *)p;
1787
 
  myisam_hton->state= SHOW_OPTION_YES;
1788
 
  myisam_hton->create= myisam_create_handler;
1789
 
  myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
1790
1827
  return 0;
1791
1828
}
1792
1829
 
1797
1834
 ***************************************************************************/
1798
1835
 
1799
1836
int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
1800
 
                                     uint32_t n_ranges, uint32_t mode, 
 
1837
                                     uint32_t n_ranges, uint32_t mode,
1801
1838
                                     HANDLER_BUFFER *buf)
1802
1839
{
1803
 
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index], 
 
1840
  return ds_mrr.dsmrr_init(this, &table->key_info[active_index],
1804
1841
                           seq, seq_init_param, n_ranges, mode, buf);
1805
1842
}
1806
1843
 
1810
1847
}
1811
1848
 
1812
1849
ha_rows ha_myisam::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
1813
 
                                               void *seq_init_param, 
 
1850
                                               void *seq_init_param,
1814
1851
                                               uint32_t n_ranges, uint32_t *bufsz,
1815
1852
                                               uint32_t *flags, COST_VECT *cost)
1816
1853
{
1847
1884
  return NULL;
1848
1885
}
1849
1886
 
1850
 
 
1851
 
mysql_declare_plugin(myisam)
 
1887
static DRIZZLE_SYSVAR_UINT(block_size, block_size,
 
1888
                           PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
 
1889
                           N_("Block size to be used for MyISAM index pages."),
 
1890
                           NULL, NULL, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, 
 
1891
                           MI_MAX_KEY_BLOCK_LENGTH, 0);
 
1892
 
 
1893
static DRIZZLE_SYSVAR_UINT(repair_threads, repair_threads,
 
1894
                           PLUGIN_VAR_RQCMDARG,
 
1895
                           N_("Number of threads to use when repairing MyISAM tables. The value of "
 
1896
                              "1 disables parallel repair."),
 
1897
                           NULL, NULL, 1, 1, UINT32_MAX, 0);
 
1898
 
 
1899
static DRIZZLE_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size,
 
1900
                                PLUGIN_VAR_RQCMDARG,
 
1901
                                N_("Don't use the fast sort index method to created index if the temporary file would get bigger than this."),
 
1902
                                NULL, NULL, INT32_MAX, 0, UINT64_MAX, 0);
 
1903
 
 
1904
static DRIZZLE_SYSVAR_ULONGLONG(sort_buffer_size, sort_buffer_size,
 
1905
                                PLUGIN_VAR_RQCMDARG,
 
1906
                                N_("The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE."),
 
1907
                                NULL, NULL, 8192*1024, 1024, SIZE_MAX, 0);
 
1908
 
 
1909
extern uint32_t data_pointer_size;
 
1910
static DRIZZLE_SYSVAR_UINT(data_pointer_size, data_pointer_size,
 
1911
                           PLUGIN_VAR_RQCMDARG,
 
1912
                           N_("Default pointer size to be used for MyISAM tables."),
 
1913
                           NULL, NULL, 6, 2, 7, 0);
 
1914
 
 
1915
static struct st_mysql_sys_var* system_variables[]= {
 
1916
  DRIZZLE_SYSVAR(block_size),
 
1917
  DRIZZLE_SYSVAR(repair_threads),
 
1918
  DRIZZLE_SYSVAR(max_sort_file_size),
 
1919
  DRIZZLE_SYSVAR(sort_buffer_size),
 
1920
  DRIZZLE_SYSVAR(data_pointer_size),
 
1921
  NULL
 
1922
};
 
1923
 
 
1924
 
 
1925
drizzle_declare_plugin(myisam)
1852
1926
{
1853
1927
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1854
1928
  "MyISAM",
1859
1933
  myisam_init, /* Plugin Init */
1860
1934
  myisam_deinit, /* Plugin Deinit */
1861
1935
  NULL,                       /* status variables                */
1862
 
  NULL,                       /* system variables                */
 
1936
  system_variables,           /* system variables */
1863
1937
  NULL                        /* config options                  */
1864
1938
}
1865
 
mysql_declare_plugin_end;
 
1939
drizzle_declare_plugin_end;