diff options
Diffstat (limited to 'storage/mroonga/ha_mroonga.cpp')
-rw-r--r-- | storage/mroonga/ha_mroonga.cpp | 876 |
1 files changed, 632 insertions, 244 deletions
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index dbc2f0ca6e3..83f03fcb272 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -21,6 +21,7 @@ */ #include "mrn_mysql.h" +#include "mrn_mysql_compat.h" #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation @@ -35,6 +36,11 @@ #endif #include <sql_select.h> +#include <item_sum.h> + +#ifdef MRN_HAVE_BINLOG_H +# include <binlog.h> +#endif #ifdef MRN_HAVE_SQL_OPTIMIZER_H # include <sql_optimizer.h> @@ -49,9 +55,6 @@ #ifdef WIN32 # include <math.h> # include <direct.h> -# define MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(type, variable_name, variable_size) \ - type *variable_name = (type *)_malloca(sizeof(type) * (variable_size)) -# define MRN_FREE_VARIABLE_LENGTH_ARRAYS(variable_name) _freea(variable_name) # define MRN_TABLE_SHARE_LOCK_SHARE_PROC "?key_TABLE_SHARE_LOCK_share@@3IA" # define MRN_TABLE_SHARE_LOCK_HA_DATA_PROC "?key_TABLE_SHARE_LOCK_ha_data@@3IA" # ifdef _WIN64 @@ -64,11 +67,14 @@ #else # include <dirent.h> # include <unistd.h> -# define MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(type, variable_name, variable_size) \ - type variable_name[variable_size] -# define MRN_FREE_VARIABLE_LENGTH_ARRAYS(variable_name) #endif +#define MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(type, variable_name, variable_size) \ + type *variable_name = \ + (type *)mrn_my_malloc(sizeof(type) * (variable_size), MYF(MY_WME)) +#define MRN_FREE_VARIABLE_LENGTH_ARRAYS(variable_name) \ + my_free(variable_name) + #include "mrn_err.h" #include "mrn_table.hpp" #include "ha_mroonga.hpp" @@ -89,6 +95,8 @@ #include <mrn_smart_grn_obj.hpp> #include <mrn_database_manager.hpp> #include <mrn_grn.hpp> +#include <mrn_value_decoder.hpp> +#include <mrn_database_repairer.hpp> #ifdef MRN_SUPPORT_FOREIGN_KEYS # include <sql_table.h> @@ -148,7 +156,11 @@ static mysql_mutex_t *mrn_LOCK_open; # define mrn_declare_plugin(NAME) maria_declare_plugin(NAME) # define mrn_declare_plugin_end maria_declare_plugin_end # define MRN_PLUGIN_LAST_VALUES MRN_VERSION, MariaDB_PLUGIN_MATURITY_STABLE -# define MRN_ABORT_ON_WARNING(thd) thd_kill_level(thd) +# if MYSQL_VERSION_ID >= 100000 +# define MRN_ABORT_ON_WARNING(thd) thd_kill_level(thd) +# else +# define MRN_ABORT_ON_WARNING(thd) thd->abort_on_warning +# endif #else # define mrn_declare_plugin(NAME) mysql_declare_plugin(NAME) # define mrn_declare_plugin_end mysql_declare_plugin_end @@ -157,7 +169,11 @@ static mysql_mutex_t *mrn_LOCK_open; # else # define MRN_PLUGIN_LAST_VALUES NULL # endif -# define MRN_ABORT_ON_WARNING(thd) thd->abort_on_warning +# if MYSQL_VERSION_ID >= 50706 +# define MRN_ABORT_ON_WARNING(thd) false +# else +# define MRN_ABORT_ON_WARNING(thd) thd->abort_on_warning +# endif #endif #if MYSQL_VERSION_ID >= 100007 && defined(MRN_MARIADB_P) @@ -172,12 +188,69 @@ static mysql_mutex_t *mrn_LOCK_open; # define MRN_GET_ERR_MSG(code) ER(code) #endif +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex->table_list.first +#else +# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex.table_list.first +#endif + +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define MRN_KEYTYPE_FOREIGN KEYTYPE_FOREIGN +#else +# define MRN_KEYTYPE_FOREIGN Key::FOREIGN_KEY +#endif + +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define mrn_calculate_key_len(table, key_index, buffer, keypart_map) \ + calculate_key_len(table, key_index, keypart_map) +#else +# define mrn_calculate_key_len(table, key_index, buffer, keypart_map) \ + calculate_key_len(table, key_index, buffer, keypart_map) +#endif + +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define MRN_SELECT_LEX_GET_WHERE_COND(select_lex) \ + ((select_lex)->where_cond()) +# define MRN_SELECT_LEX_GET_HAVING_COND(select_lex) \ + ((select_lex)->having_cond()) +# define MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(select_lex) \ + ((select_lex)->active_options()) +#else +# define MRN_SELECT_LEX_GET_WHERE_COND(select_lex) \ + ((select_lex)->where) +# define MRN_SELECT_LEX_GET_HAVING_COND(select_lex) \ + ((select_lex)->having) +# define MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(select_lex) \ + ((select_lex)->options) +#endif + +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define MRN_TABLE_LIST_GET_DERIVED(table_list) NULL +#else +# define MRN_TABLE_LIST_GET_DERIVED(table_list) (table_list)->derived +#endif + +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define MRN_GEOMETRY_FREE(geometry) +#else +# define MRN_GEOMETRY_FREE(geometry) delete (geometry) +#endif + Rpl_filter *mrn_binlog_filter; Time_zone *mrn_my_tz_UTC; #ifdef MRN_HAVE_TABLE_DEF_CACHE HASH *mrn_table_def_cache; #endif +#ifdef MRN_HAVE_PSI_MEMORY_KEY +PSI_memory_key mrn_memory_key; + +static PSI_memory_info mrn_all_memory_keys[]= +{ + {&mrn_memory_key, "Mroonga", 0} +}; +#endif + static const char *INDEX_COLUMN_NAME = "index"; static const char *MRN_PLUGIN_AUTHOR = "The Mroonga project"; @@ -189,31 +262,22 @@ extern "C" { int grn_atoi(const char *nptr, const char *end, const char **rest); uint grn_atoui(const char *nptr, const char *end, const char **rest); -/* global variables */ -handlerton *mrn_hton_ptr; -HASH mrn_open_tables; -mysql_mutex_t mrn_open_tables_mutex; -HASH mrn_long_term_share; -mysql_mutex_t mrn_long_term_share_mutex; - -HASH mrn_allocated_thds; -mysql_mutex_t mrn_allocated_thds_mutex; -/* internal variables */ -static grn_ctx mrn_ctx; -static mysql_mutex_t mrn_log_mutex; -static grn_obj *mrn_db; -static grn_ctx mrn_db_manager_ctx; -static mysql_mutex_t mrn_db_manager_mutex; -mrn::DatabaseManager *mrn_db_manager = NULL; - #ifdef HAVE_PSI_INTERFACE -PSI_mutex_key mrn_allocated_thds_mutex_key; +# ifdef WIN32 +# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE +PSI_mutex_key *mrn_table_share_lock_share; +# endif +# ifdef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA +PSI_mutex_key *mrn_table_share_lock_ha_data; +# endif +# endif static PSI_mutex_key mrn_open_tables_mutex_key; static PSI_mutex_key mrn_long_term_share_mutex_key; +static PSI_mutex_key mrn_allocated_thds_mutex_key; PSI_mutex_key mrn_share_mutex_key; PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key; -static PSI_mutex_key mrn_db_manager_mutex_key; static PSI_mutex_key mrn_log_mutex_key; +static PSI_mutex_key mrn_db_manager_mutex_key; static PSI_mutex_info mrn_mutexes[] = { @@ -226,20 +290,25 @@ static PSI_mutex_info mrn_mutexes[] = {&mrn_log_mutex_key, "log", PSI_FLAG_GLOBAL}, {&mrn_db_manager_mutex_key, "DatabaseManager", PSI_FLAG_GLOBAL} }; - -#ifdef WIN32 -# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE - PSI_mutex_key *mrn_table_share_lock_share; -# endif -# ifdef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA - PSI_mutex_key *mrn_table_share_lock_ha_data; -# endif #endif -#else -#undef MRN_TABLE_SHARE_HAVE_LOCK_SHARE -#undef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA -#endif +/* global variables */ +handlerton *mrn_hton_ptr; +HASH mrn_open_tables; +mysql_mutex_t mrn_open_tables_mutex; +HASH mrn_long_term_share; +mysql_mutex_t mrn_long_term_share_mutex; + +HASH mrn_allocated_thds; +mysql_mutex_t mrn_allocated_thds_mutex; + +/* internal variables */ +static grn_ctx mrn_ctx; +static mysql_mutex_t mrn_log_mutex; +static grn_obj *mrn_db; +static grn_ctx mrn_db_manager_ctx; +static mysql_mutex_t mrn_db_manager_mutex; +mrn::DatabaseManager *mrn_db_manager = NULL; #ifdef WIN32 @@ -293,12 +362,19 @@ static const char *mrn_inspect_thr_lock_type(enum thr_lock_type lock_type) inspected = "TL_WRITE_ALLOW_READ"; break; #endif +#ifdef MRN_HAVE_TL_WRITE_CONCURRENT_DEFAULT + case TL_WRITE_CONCURRENT_DEFAULT: + inspected = "TL_WRITE_CONCURRENT_DEFAULT"; + break; +#endif case TL_WRITE_CONCURRENT_INSERT: inspected = "TL_WRITE_CONCURRENT_INSERT"; break; +#ifdef MRN_HAVE_TL_WRITE_DELAYED case TL_WRITE_DELAYED: inspected = "TL_WRITE_DELAYED"; break; +#endif case TL_WRITE_DEFAULT: inspected = "TL_WRITE_DEFAULT"; break; @@ -537,6 +613,7 @@ typedef enum { MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE = (1 << 4), MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT = (1 << 5) } mrn_boolean_mode_syntax_flag; +#ifdef MRN_SUPPORT_THDVAR_SET static const char *mrn_boolean_mode_sytnax_flag_names[] = { "DEFAULT", "SYNTAX_QUERY", @@ -552,6 +629,7 @@ static TYPELIB mrn_boolean_mode_syntax_flags_typelib = { mrn_boolean_mode_sytnax_flag_names, NULL }; +#endif typedef enum { MRN_ACTION_ON_ERROR_ERROR, @@ -612,13 +690,25 @@ static uchar *mrn_allocated_thds_get_key(const uchar *record, static struct st_mysql_storage_engine storage_engine_structure = { MYSQL_HANDLERTON_INTERFACE_VERSION }; +#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) +# define MRN_STATUS_VARIABLE_ENTRY(name, value, type, scope) \ + {name, value, type, scope} +#else +# define MRN_STATUS_VARIABLE_ENTRY(name, value, type, scope) \ + {name, value, type} +#endif + static struct st_mysql_show_var mrn_status_variables[] = { - {MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_count_skip", - (char *)&mrn_count_skip, SHOW_LONG}, - {MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_fast_order_limit", - (char *)&mrn_fast_order_limit, SHOW_LONG}, - {NullS, NullS, SHOW_LONG} + MRN_STATUS_VARIABLE_ENTRY(MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_count_skip", + (char *)&mrn_count_skip, + SHOW_LONG, + SHOW_SCOPE_GLOBAL), + MRN_STATUS_VARIABLE_ENTRY(MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_fast_order_limit", + (char *)&mrn_fast_order_limit, + SHOW_LONG, + SHOW_SCOPE_GLOBAL), + MRN_STATUS_VARIABLE_ENTRY(NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL) }; static const char *mrn_log_level_type_names[] = { @@ -728,10 +818,10 @@ static void mrn_log_file_update(THD *thd, struct st_mysql_sys_var *var, #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR char *old_log_file_name = *old_value_ptr; - *old_value_ptr = my_strdup(new_log_file_name, MYF(MY_WME)); + *old_value_ptr = mrn_my_strdup(new_log_file_name, MYF(MY_WME)); my_free(old_log_file_name); #else - *old_value_ptr = my_strdup(new_log_file_name, MYF(MY_WME)); + *old_value_ptr = mrn_my_strdup(new_log_file_name, MYF(MY_WME)); #endif grn_ctx_fin(&ctx); @@ -769,7 +859,7 @@ static void mrn_default_parser_update(THD *thd, struct st_mysql_sys_var *var, #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR my_free(*old_value_ptr); - *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); + *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); #else *old_value_ptr = (char *)new_value; #endif @@ -811,7 +901,7 @@ static MYSQL_THDVAR_LONGLONG(match_escalation_threshold, NULL, grn_get_default_match_escalation_threshold(), -1, - LONGLONG_MAX, + INT_MAX64, 0); static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var *var, @@ -823,7 +913,7 @@ static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR my_free(*old_value_ptr); - *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); + *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); #else *old_value_ptr = (char *)new_value; #endif @@ -849,7 +939,7 @@ static void mrn_database_path_prefix_update(THD *thd, if (*old_value_ptr) my_free(*old_value_ptr); if (new_value) - *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); + *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); else *old_value_ptr = NULL; #else @@ -967,6 +1057,7 @@ static MYSQL_SYSVAR_BOOL(libgroonga_support_lz4, mrn_libgroonga_support_lz4, NULL, grn_check_lz4_support()); +#ifdef MRN_SUPPORT_THDVAR_SET static MYSQL_THDVAR_SET(boolean_mode_syntax_flags, PLUGIN_VAR_RQCMDARG, "The flags to custom syntax in BOOLEAN MODE. " @@ -978,6 +1069,20 @@ static MYSQL_THDVAR_SET(boolean_mode_syntax_flags, NULL, MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT, &mrn_boolean_mode_syntax_flags_typelib); +#endif + +static const int MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT = 1000; + +static MYSQL_THDVAR_INT(max_n_records_for_estimate, + PLUGIN_VAR_RQCMDARG, + "The max number of records to " + "estimate the number of matched records", + NULL, + NULL, + MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT, + -1, + INT_MAX, + 0); static struct st_mysql_sys_var *mrn_system_variables[] = { @@ -996,7 +1101,10 @@ static struct st_mysql_sys_var *mrn_system_variables[] = MYSQL_SYSVAR(vector_column_delimiter), MYSQL_SYSVAR(libgroonga_support_zlib), MYSQL_SYSVAR(libgroonga_support_lz4), +#ifdef MRN_SUPPORT_THDVAR_SET MYSQL_SYSVAR(boolean_mode_syntax_flags), +#endif + MYSQL_SYSVAR(max_n_records_for_estimate), NULL }; @@ -1116,7 +1224,11 @@ static int mrn_close_connection(handlerton *hton, THD *thd) DBUG_RETURN(0); } +#ifdef MRN_FLUSH_LOGS_HAVE_BINLOG_GROUP_FLUSH +static bool mrn_flush_logs(handlerton *hton, bool binlog_group_flush) +#else static bool mrn_flush_logs(handlerton *hton) +#endif { MRN_DBUG_ENTER_FUNCTION(); bool result = 0; @@ -1322,7 +1434,7 @@ grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd, if (mrn_libgroonga_support_zlib) { flags |= GRN_OBJ_COMPRESS_ZLIB; } else { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + push_warning_printf(thd, MRN_SEVERITY_WARNING, ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, "COMPRESS_ZLIB"); @@ -1332,7 +1444,7 @@ grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd, if (mrn_libgroonga_support_lz4) { flags |= GRN_OBJ_COMPRESS_LZ4; } else { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + push_warning_printf(thd, MRN_SEVERITY_WARNING, ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, "COMPRESS_LZ4"); @@ -1344,7 +1456,7 @@ grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd, "%.*s", static_cast<int>(rest_length), flag_names); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + push_warning_printf(thd, MRN_SEVERITY_WARNING, ER_MRN_INVALID_COLUMN_FLAG_NUM, ER_MRN_INVALID_COLUMN_FLAG_STR, invalid_flag_name, @@ -1356,7 +1468,53 @@ grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd, return flags; } -#ifdef HAVE_SPATIAL +bool mrn_parse_grn_index_column_flags(THD *thd, + grn_ctx *ctx, + const char *flag_names, + uint flag_names_length, + grn_obj_flags *index_column_flags) +{ + const char *flag_names_end = flag_names + flag_names_length; + bool found = false; + + while (flag_names < flag_names_end) { + uint rest_length = flag_names_end - flag_names; + + if (*flag_names == '|' || *flag_names == ' ') { + flag_names += 1; + continue; + } + if (rest_length >= 4 && !memcmp(flag_names, "NONE", 4)) { + flag_names += 4; + found = true; + } else if (rest_length >= 13 && !memcmp(flag_names, "WITH_POSITION", 13)) { + *index_column_flags |= GRN_OBJ_WITH_POSITION; + flag_names += 13; + found = true; + } else if (rest_length >= 12 && !memcmp(flag_names, "WITH_SECTION", 12)) { + *index_column_flags |= GRN_OBJ_WITH_SECTION; + flag_names += 12; + found = true; + } else if (rest_length >= 11 && !memcmp(flag_names, "WITH_WEIGHT", 11)) { + *index_column_flags |= GRN_OBJ_WITH_WEIGHT; + flag_names += 11; + found = true; + } else { + char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE]; + snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE, + "%.*s", + static_cast<int>(rest_length), + flag_names); + push_warning_printf(thd, MRN_SEVERITY_WARNING, + ER_MRN_INVALID_INDEX_FLAG_NUM, + ER_MRN_INVALID_INDEX_FLAG_STR, + invalid_flag_name); + } + } + return found; +} + +#ifdef MRN_HAVE_SPATIAL static int mrn_set_geometry(grn_ctx *ctx, grn_obj *buf, const char *wkb, uint wkb_size) { @@ -1393,12 +1551,13 @@ static int mrn_set_geometry(grn_ctx *ctx, grn_obj *buf, error = ER_MRN_GEOMETRY_NOT_SUPPORT_NUM; break; } - delete geometry; + MRN_GEOMETRY_FREE(geometry); return error; } #endif +#ifdef MRN_HAVE_HTON_ALTER_TABLE_FLAGS static uint mrn_alter_table_flags(uint flags) { uint alter_flags = 0; @@ -1419,18 +1578,15 @@ static uint mrn_alter_table_flags(uint flags) HA_INPLACE_DROP_INDEX_NO_READ_WRITE | HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE | HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE | - HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE | - HA_INPLACE_DROP_PK_INDEX_NO_READ_WRITE | HA_INPLACE_ADD_INDEX_NO_WRITE | HA_INPLACE_DROP_INDEX_NO_WRITE | HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE | - HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE | - HA_INPLACE_ADD_PK_INDEX_NO_WRITE | - HA_INPLACE_DROP_PK_INDEX_NO_WRITE; + HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE; } #endif return alter_flags; } +#endif static int mrn_init(void *p) { @@ -1440,11 +1596,16 @@ static int mrn_init(void *p) hton = (handlerton *)p; hton->state = SHOW_OPTION_YES; hton->create = mrn_handler_create; - hton->flags = 0; + hton->flags = HTON_NO_FLAGS; +#ifndef MRN_SUPPORT_PARTITION + hton->flags |= HTON_NO_PARTITION; +#endif hton->drop_database = mrn_drop_database; hton->close_connection = mrn_close_connection; hton->flush_logs = mrn_flush_logs; +#ifdef MRN_HAVE_HTON_ALTER_TABLE_FLAGS hton->alter_table_flags = mrn_alter_table_flags; +#endif mrn_hton_ptr = hton; #ifdef _WIN32 @@ -1462,13 +1623,17 @@ static int mrn_init(void *p) (mysql_mutex_t *)GetProcAddress(current_module, "?LOCK_open@@3Ust_mysql_mutex@@A"); # endif -# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE - mrn_table_share_lock_share = - (PSI_mutex_key *)GetProcAddress(current_module, MRN_TABLE_SHARE_LOCK_SHARE_PROC); -# endif -# ifdef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA - mrn_table_share_lock_ha_data = - (PSI_mutex_key *)GetProcAddress(current_module, MRN_TABLE_SHARE_LOCK_HA_DATA_PROC); +# ifdef HAVE_PSI_INTERFACE +# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE + mrn_table_share_lock_share = + (PSI_mutex_key *)GetProcAddress(current_module, + MRN_TABLE_SHARE_LOCK_SHARE_PROC); +# endif +# ifdef MRN_TABLE_SHARE_HAVE_LOCK_HA_DATA + mrn_table_share_lock_ha_data = + (PSI_mutex_key *)GetProcAddress(current_module, + MRN_TABLE_SHARE_LOCK_HA_DATA_PROC); +# endif # endif #else mrn_binlog_filter = binlog_filter; @@ -1502,6 +1667,14 @@ static int mrn_init(void *p) if (mrn_change_encoding(ctx, system_charset_info)) goto err_mrn_change_encoding; +#ifdef MRN_HAVE_PSI_MEMORY_KEY + { + const char *category = "ha_mroonga"; + int n_keys = array_elements(mrn_all_memory_keys); + mysql_memory_register(category, mrn_all_memory_keys, n_keys); + } +#endif + if (mysql_mutex_init(mrn_log_mutex_key, &mrn_log_mutex, MY_MUTEX_INIT_FAST) != 0) { @@ -2164,6 +2337,9 @@ ha_mroonga::~ha_mroonga() if (share_for_create.wrapper_mode) { plugin_unlock(NULL, share_for_create.plugin); } + if (share_for_create.table_name) { + my_free(share_for_create.table_name); + } mrn_free_share_alloc(&share_for_create); free_root(&mem_root_for_create, MYF(0)); } @@ -2545,7 +2721,7 @@ int ha_mroonga::create_share_for_create() const THD *thd = ha_thd(); LEX *lex = thd->lex; HA_CREATE_INFO *create_info = &lex->create_info; - TABLE_LIST *table_list = lex->select_lex.table_list.first; + TABLE_LIST *table_list = MRN_LEX_GET_TABLE_LIST(lex); MRN_DBUG_ENTER_METHOD(); wrap_handler_for_create = NULL; memset(&table_for_create, 0, sizeof(TABLE)); @@ -2589,10 +2765,12 @@ int ha_mroonga::create_share_for_create() const } } } - init_alloc_root(&mem_root_for_create, 1024, 0, MYF(0)); + mrn_init_alloc_root(&mem_root_for_create, 1024, 0, MYF(0)); analyzed_for_create = true; if (table_list) { - share_for_create.table_name = table_list->table_name; + share_for_create.table_name = mrn_my_strndup(table_list->table_name, + table_list->table_name_length, + MYF(MY_WME)); share_for_create.table_name_length = table_list->table_name_length; } share_for_create.table_share = &table_share_for_create; @@ -2741,10 +2919,13 @@ int ha_mroonga::wrapper_create_index_fulltext(const char *grn_table_name, GRN_OBJ_PERSISTENT; grn_obj *index_table; - grn_obj_flags index_column_flags = - GRN_OBJ_COLUMN_INDEX | GRN_OBJ_WITH_POSITION | GRN_OBJ_PERSISTENT; - if (KEY_N_KEY_PARTS(key_info) > 1) { - index_column_flags |= GRN_OBJ_WITH_SECTION; + grn_obj_flags index_column_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT; + + if (!find_index_column_flags(key_info, &index_column_flags)) { + index_column_flags |= GRN_OBJ_WITH_POSITION; + if (KEY_N_KEY_PARTS(key_info) > 1) { + index_column_flags |= GRN_OBJ_WITH_SECTION; + } } mrn::SmartGrnObj lexicon_key_type(ctx, GRN_DB_SHORT_TEXT); @@ -3029,7 +3210,8 @@ int ha_mroonga::storage_create(const char *name, TABLE *table, DBUG_RETURN(error); } - if (table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_PAT_KEY)) { + if (table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_PAT_KEY) || + table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_HASH_KEY)) { KEY key_info = table->s->key_info[pkey_nr]; int key_parts = KEY_N_KEY_PARTS(&key_info); if (key_parts == 1) { @@ -3182,7 +3364,7 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table, char ref_db_buff[NAME_LEN + 1], ref_table_buff[NAME_LEN + 1]; while ((key = key_iterator++)) { - if (key->type != Key::FOREIGN_KEY) + if (key->type != MRN_KEYTYPE_FOREIGN) { continue; } @@ -3207,7 +3389,11 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table, Key_part_spec *key_part_ref_col = key_part_ref_col_iterator++; LEX_STRING ref_field_name = key_part_ref_col->field_name; DBUG_PRINT("info", ("mroonga: ref_field_name=%s", ref_field_name.str)); +#ifdef MRN_FOREIGN_KEY_USE_CONST_STRING + LEX_CSTRING ref_db_name = fk->ref_db; +#else LEX_STRING ref_db_name = fk->ref_db; +#endif DBUG_PRINT("info", ("mroonga: ref_db_name=%s", ref_db_name.str)); if (ref_db_name.str && lower_case_table_names) { strmake(ref_db_buff, ref_db_name.str, sizeof(ref_db_buff) - 1); @@ -3215,7 +3401,11 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table, ref_db_name.str = ref_db_buff; DBUG_PRINT("info", ("mroonga: casedn ref_db_name=%s", ref_db_name.str)); } +#ifdef MRN_FOREIGN_KEY_USE_CONST_STRING + LEX_CSTRING ref_table_name = fk->ref_table; +#else LEX_STRING ref_table_name = fk->ref_table; +#endif DBUG_PRINT("info", ("mroonga: ref_table_name=%s", ref_table_name.str)); if (ref_table_name.str && lower_case_table_names) { strmake(ref_table_buff, ref_table_name.str, sizeof(ref_table_buff) - 1); @@ -3545,10 +3735,13 @@ int ha_mroonga::storage_create_index(TABLE *table, const char *grn_table_name, if (error) DBUG_RETURN(error); - grn_obj_flags index_column_flags = - GRN_OBJ_COLUMN_INDEX | GRN_OBJ_WITH_POSITION | GRN_OBJ_PERSISTENT; - if (is_multiple_column_index) { - index_column_flags |= GRN_OBJ_WITH_SECTION; + grn_obj_flags index_column_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT; + + if (!find_index_column_flags(key_info, &index_column_flags)) { + index_column_flags |= GRN_OBJ_WITH_POSITION; + if (is_multiple_column_index) { + index_column_flags |= GRN_OBJ_WITH_SECTION; + } } index_table = index_tables[i]; @@ -3753,7 +3946,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) } } - init_alloc_root(&mem_root, 1024, 0, MYF(0)); + mrn_init_alloc_root(&mem_root, 1024, 0, MYF(0)); wrap_key_info = mrn_create_key_info_for_table(share, table, &error); if (error) DBUG_RETURN(error); @@ -3988,15 +4181,17 @@ int ha_mroonga::storage_open(const char *name, int mode, uint test_if_locked) DBUG_RETURN(error); } - error = storage_open_indexes(name); - if (error) { - // TODO: free grn_columns and set NULL; - grn_obj_unlink(ctx, grn_table); - grn_table = NULL; - DBUG_RETURN(error); - } + if (!(ha_thd()->open_options & HA_OPEN_FOR_REPAIR)) { + error = storage_open_indexes(name); + if (error) { + // TODO: free grn_columns and set NULL; + grn_obj_unlink(ctx, grn_table); + grn_table = NULL; + DBUG_RETURN(error); + } - storage_set_keys_in_use(); + storage_set_keys_in_use(); + } ref_length = sizeof(grn_id); DBUG_RETURN(0); @@ -4043,6 +4238,11 @@ int ha_mroonga::storage_open_columns(void) int n_columns = table->s->fields; grn_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_columns); grn_column_ranges = (grn_obj **)malloc(sizeof(grn_obj *) * n_columns); + for (int i = 0; i < n_columns; i++) { + grn_columns[i] = NULL; + grn_column_ranges[i] = NULL; + } + if (table_share->blob_fields) { if (blob_buffers) @@ -4055,8 +4255,7 @@ int ha_mroonga::storage_open_columns(void) } } - int i; - for (i = 0; i < n_columns; i++) { + for (int i = 0; i < n_columns; i++) { Field *field = table->field[i]; const char *column_name = field->field_name; int column_name_size = strlen(column_name); @@ -4065,24 +4264,46 @@ int ha_mroonga::storage_open_columns(void) blob_buffers[i].set_charset(field->charset()); } if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) { - grn_columns[i] = NULL; - grn_column_ranges[i] = NULL; continue; } grn_columns[i] = grn_obj_column(ctx, grn_table, column_name, column_name_size); + if (!grn_columns[i]) { + error = ER_CANT_OPEN_FILE; + my_message(error, ctx->errbuf, MYF(0)); + break; + } + grn_id range_id = grn_obj_get_range(ctx, grn_columns[i]); grn_column_ranges[i] = grn_ctx_at(ctx, range_id); - if (ctx->rc) { - // TODO: free grn_columns and set NULL; - int error = ER_CANT_OPEN_FILE; + if (!grn_column_ranges[i]) { + error = ER_CANT_OPEN_FILE; my_message(error, ctx->errbuf, MYF(0)); - DBUG_RETURN(error); + break; } } - DBUG_RETURN(0); + if (error != 0) { + for (int i = 0; i < n_columns; i++) { + grn_obj *column = grn_columns[i]; + if (column) { + grn_obj_unlink(ctx, column); + } + + grn_obj *range = grn_column_ranges[i]; + if (range) { + grn_obj_unlink(ctx, range); + } + } + + free(grn_columns); + grn_columns = NULL; + free(grn_column_ranges); + grn_column_ranges = NULL; + } + + DBUG_RETURN(error); } int ha_mroonga::storage_open_indexes(const char *name) @@ -4147,7 +4368,7 @@ int ha_mroonga::storage_open_indexes(const char *name) grn_index_tables[i], INDEX_COLUMN_NAME, strlen(INDEX_COLUMN_NAME)); - if (!grn_index_columns[i]) { + if (!grn_index_columns[i] && ctx->rc == GRN_SUCCESS) { /* just for backward compatibility before 1.0. */ Field *field = key_info.key_part[0].field; grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i], @@ -5176,7 +5397,7 @@ int ha_mroonga::wrapper_write_row_index(uchar *buf) (int)GRN_TEXT_LEN(&key_buffer), GRN_TEXT_VALUE(&key_buffer)); error = ER_ERROR_ON_WRITE; - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, error, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, error, error_message); DBUG_RETURN(0); } @@ -5259,7 +5480,7 @@ int ha_mroonga::storage_write_row(uchar *buf) if (field->is_null()) continue; if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + push_warning_printf(thd, MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, MRN_GET_ERR_MSG(WARN_DATA_TRUNCATED), MRN_COLUMN_NAME_ID, MRN_GET_CURRENT_ROW_FOR_WARNING(thd)); @@ -5339,7 +5560,7 @@ int ha_mroonga::storage_write_row(uchar *buf) if (field->is_null()) continue; -#ifdef HAVE_SPATIAL +#ifdef MRN_HAVE_SPATIAL bool is_null_geometry_value = field->real_type() == MYSQL_TYPE_GEOMETRY && static_cast<Field_geom *>(field)->get_length() == 0; @@ -5687,7 +5908,7 @@ int ha_mroonga::wrapper_get_record_id(uchar *data, grn_id *record_id, "%s: key=<%.*s>", context, (int)GRN_TEXT_LEN(&key), GRN_TEXT_VALUE(&key)); error = ER_ERROR_ON_WRITE; - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, error, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, error, error_message); } grn_obj_unlink(ctx, &key); @@ -5851,7 +6072,7 @@ int ha_mroonga::storage_update_row(const uchar *old_data, uchar *new_data) if (bitmap_is_set(table->write_set, field->field_index)) { if (field->is_null()) continue; if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + push_warning_printf(thd, MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, MRN_GET_ERR_MSG(WARN_DATA_TRUNCATED), MRN_COLUMN_NAME_ID, MRN_GET_CURRENT_ROW_FOR_WARNING(thd)); @@ -5909,7 +6130,7 @@ int ha_mroonga::storage_update_row(const uchar *old_data, uchar *new_data) snprintf(message, MRN_BUFFER_SIZE, "data truncated for primary key column: <%s>", column_name); - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + push_warning(thd, MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, message); } have_pkey = true; @@ -6489,6 +6710,7 @@ uint ha_mroonga::storage_max_supported_key_parts() const uint ha_mroonga::max_supported_key_parts() const { MRN_DBUG_ENTER_METHOD(); + uint parts; if (!share && !analyzed_for_create && ( @@ -6506,6 +6728,7 @@ uint ha_mroonga::max_supported_key_parts() const } else { parts = storage_max_supported_key_parts(); } + DBUG_RETURN(parts); } @@ -6601,6 +6824,7 @@ ha_rows ha_mroonga::storage_records_in_range(uint key_nr, key_range *range_min, } } + int cursor_limit = THDVAR(ha_thd(), max_n_records_for_estimate); uint pkey_nr = table->s->primary_key; if (key_nr == pkey_nr) { DBUG_PRINT("info", ("mroonga: use primary key")); @@ -6608,7 +6832,7 @@ ha_rows ha_mroonga::storage_records_in_range(uint key_nr, key_range *range_min, cursor = grn_table_cursor_open(ctx, grn_table, key_min, size_min, key_max, size_max, - 0, -1, flags); + 0, cursor_limit, flags); while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) { row_count++; } @@ -6621,18 +6845,13 @@ ha_rows ha_mroonga::storage_records_in_range(uint key_nr, key_range *range_min, } grn_table_cursor *cursor; - grn_table_cursor *index_cursor; cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr], key_min, size_min, key_max, size_max, - 0, -1, flags); - index_cursor = grn_index_cursor_open(ctx, cursor, - grn_index_columns[key_nr], - 0, GRN_ID_MAX, 0); - while (grn_table_cursor_next(ctx, index_cursor) != GRN_ID_NIL) { - row_count++; - } - grn_obj_unlink(ctx, index_cursor); + 0, cursor_limit, flags); + grn_obj *index_column = grn_index_columns[key_nr]; + grn_ii *ii = reinterpret_cast<grn_ii *>(index_column); + row_count = grn_ii_estimate_size_for_lexicon_cursor(ctx, ii, cursor); grn_table_cursor_close(ctx, cursor); } DBUG_RETURN(row_count); @@ -6814,7 +7033,8 @@ int ha_mroonga::storage_index_read_map(uchar *buf, const uchar *key, bool is_multiple_column_index = KEY_N_KEY_PARTS(&key_info) > 1; if (is_multiple_column_index) { mrn_change_encoding(ctx, NULL); - uint key_length = calculate_key_len(table, active_index, key, keypart_map); + uint key_length = + mrn_calculate_key_len(table, active_index, key, keypart_map); DBUG_PRINT("info", ("mroonga: multiple column index: " "search key length=<%u>, " @@ -6832,6 +7052,10 @@ int ha_mroonga::storage_index_read_map(uchar *buf, const uchar *key, storage_encode_multiple_column_key(&key_info, key, key_length, key_min, &size_min); + if (find_flag == HA_READ_KEY_EXACT) { + key_max = key_min; + size_max = size_min; + } } } else { flags |= GRN_CURSOR_PREFIX; @@ -7018,7 +7242,8 @@ int ha_mroonga::storage_index_read_last_map(uchar *buf, const uchar *key, if (is_multiple_column_index) { mrn_change_encoding(ctx, NULL); flags |= GRN_CURSOR_PREFIX; - uint key_length = calculate_key_len(table, active_index, key, keypart_map); + uint key_length = + mrn_calculate_key_len(table, active_index, key, keypart_map); key_min = key_min_entity; storage_encode_multiple_column_key(&key_info, key, key_length, @@ -7630,7 +7855,8 @@ void ha_mroonga::generic_ft_init_ext_add_conditions_fast_order_limit( { MRN_DBUG_ENTER_METHOD(); - Item *where = table->pos_in_table_list->select_lex->where; + Item *where = + MRN_SELECT_LEX_GET_WHERE_COND(table->pos_in_table_list->select_lex); bool is_storage_mode = !(share->wrapper_mode); mrn::ConditionConverter converter(info->ctx, grn_table, is_storage_mode); @@ -7806,7 +8032,10 @@ grn_expr_flags ha_mroonga::expr_flags_in_boolean_mode() { MRN_DBUG_ENTER_METHOD(); - ulonglong syntax_flags = THDVAR(ha_thd(), boolean_mode_syntax_flags); + ulonglong syntax_flags = MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT; +#ifdef MRN_SUPPORT_THDVAR_SET + syntax_flags = THDVAR(ha_thd(), boolean_mode_syntax_flags); +#endif grn_expr_flags expression_flags = 0; if (syntax_flags == MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT) { expression_flags = GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT; @@ -8093,7 +8322,7 @@ FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key) for (int i = 0; i < n_sort_keys; i++) { grn_obj_unlink(info->ctx, sort_keys[i].key); } - free(sort_keys); + my_free(sort_keys); } DBUG_RETURN((FT_INFO *)info); @@ -8372,7 +8601,7 @@ void ha_mroonga::push_warning_unsupported_spatial_index_search(enum ha_rkey_func sprintf(search_name, "unknown: %d", flag); } push_warning_printf(ha_thd(), - Sql_condition::WARN_LEVEL_WARN, + MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, "spatial index search " "except MBRContains aren't supported: <%s>", @@ -8638,7 +8867,7 @@ grn_obj *ha_mroonga::find_tokenizer(const char *name, int name_length) name_length, name, MRN_PARSER_DEFAULT); push_warning(ha_thd(), - Sql_condition::WARN_LEVEL_WARN, ER_UNSUPPORTED_EXTENSION, + MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, message); tokenizer = grn_ctx_get(ctx, MRN_PARSER_DEFAULT, @@ -8646,7 +8875,7 @@ grn_obj *ha_mroonga::find_tokenizer(const char *name, int name_length) } if (!tokenizer) { push_warning(ha_thd(), - Sql_condition::WARN_LEVEL_WARN, ER_UNSUPPORTED_EXTENSION, + MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, "couldn't find fulltext parser. " "Bigram fulltext parser is used instead."); tokenizer = grn_ctx_at(ctx, GRN_DB_BIGRAM); @@ -8682,6 +8911,28 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info) DBUG_RETURN(normalizer); } +bool ha_mroonga::find_index_column_flags(KEY *key_info, grn_obj_flags *index_column_flags) +{ + MRN_DBUG_ENTER_METHOD(); + bool found = false; +#if MYSQL_VERSION_ID >= 50500 + if (key_info->comment.length > 0) { + mrn::ParametersParser parser(key_info->comment.str, + key_info->comment.length); + parser.parse(); + const char *names = parser["index_flags"]; + if (names) { + found = mrn_parse_grn_index_column_flags(ha_thd(), + ctx, + names, + strlen(names), + index_column_flags); + } + } +#endif + DBUG_RETURN(found); +} + bool ha_mroonga::find_token_filters(KEY *key_info, grn_obj *token_filters) { MRN_DBUG_ENTER_METHOD(); @@ -8718,7 +8969,7 @@ bool ha_mroonga::find_token_filters_put(grn_obj *token_filters, "nonexistent token filter: <%.*s>", token_filter_name_length, token_filter_name); push_warning(ha_thd(), - Sql_condition::WARN_LEVEL_WARN, ER_UNSUPPORTED_EXTENSION, + MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, message); return false; } @@ -8778,7 +9029,7 @@ break_loop: (int)(current - last_name_end), last_name_end, (int)(end - current), current); push_warning(ha_thd(), - Sql_condition::WARN_LEVEL_WARN, ER_UNSUPPORTED_EXTENSION, + MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, message); return false; } @@ -9050,9 +9301,9 @@ void ha_mroonga::check_count_skip(key_part_map start_key_part_map, if ( thd_sql_command(ha_thd()) == SQLCOM_SELECT && - !select_lex->non_agg_fields.elements && + select_lex->item_list.elements == 1 && !select_lex->group_list.elements && - !select_lex->having && + !MRN_SELECT_LEX_GET_HAVING_COND(select_lex) && select_lex->table_list.elements == 1 ) { Item *info = (Item *) select_lex->item_list.first_node()->info; @@ -9073,7 +9324,7 @@ void ha_mroonga::check_count_skip(key_part_map start_key_part_map, Item *where; if (fulltext) { DBUG_PRINT("info", ("mroonga: count skip: fulltext")); - where = select_lex->where; + where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex); if (!where || where->type() != Item::FUNC_ITEM || ((Item_func *)where)->functype() != Item_func::FT_FUNC) { @@ -9081,20 +9332,10 @@ void ha_mroonga::check_count_skip(key_part_map start_key_part_map, count_skip = false; DBUG_VOID_RETURN; } - where = where->next; - if (!where || - where->type() != Item::STRING_ITEM) { - DBUG_PRINT("info", ("mroonga: count skip: string item is not match")); - count_skip = false; - DBUG_VOID_RETURN; - } - for (where = where->next; where; where = where->next) { - if (where->type() != Item::FIELD_ITEM) - break; - DBUG_PRINT("info", ("mroonga: count skip: FIELD_ITEM=%p", where)); - } - if (where != info) { - DBUG_PRINT("info", ("mroonga: count skip: where clause is not match")); + if (select_lex->select_n_where_fields != 1) { + DBUG_PRINT("info", + ("mroonga: count skip: " + "where clause is not fulltext search only")); count_skip = false; DBUG_VOID_RETURN; } @@ -9117,10 +9358,29 @@ void ha_mroonga::check_count_skip(key_part_map start_key_part_map, uint key_nr = active_index; KEY key_info = table->key_info[key_nr]; KEY_PART_INFO *key_part = key_info.key_part; - for (where = select_lex->where; where; where = where->next) { - if (where->type() == Item::FIELD_ITEM) + for (where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex); + where; + where = where->next) { + Item *target = where; + + if (where->type() == Item::FUNC_ITEM) { + Item_func *func_item = static_cast<Item_func *>(where); + if (func_item->arg_count == 0) { + break; + } + target = func_item->key_item(); + where = where->next; + if (func_item->arguments()[0] == where) { + uint n_args = func_item->arg_count; + for (; n_args > 0; --n_args) { + where = where->next; + } + } + } + + if (target->type() == Item::FIELD_ITEM) { - Field *field = ((Item_field *)where)->field; + Field *field = ((Item_field *)target)->field; if (!field) break; if (field->table != table) @@ -9174,6 +9434,27 @@ bool ha_mroonga::is_grn_zero_column_value(grn_obj *column, grn_obj *value) DBUG_RETURN(true); } +bool ha_mroonga::is_primary_key_field(Field *field) const +{ + MRN_DBUG_ENTER_METHOD(); + + if (table->s->primary_key == MAX_INDEXES) { + DBUG_RETURN(false); + } + + KEY *key_info = &(table->s->key_info[table->s->primary_key]); + if (KEY_N_KEY_PARTS(key_info) != 1) { + DBUG_RETURN(false); + } + + if (strcmp(field->field_name, + key_info->key_part[0].field->field_name) == 0) { + DBUG_RETURN(true); + } else { + DBUG_RETURN(false); + } +} + void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, int *n_sort_keys, longlong *limit) @@ -9188,7 +9469,7 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, TABLE_LIST *table_list = table->pos_in_table_list; st_select_lex *select_lex = table_list->select_lex; - SELECT_LEX_UNIT *unit = table_list->derived; + SELECT_LEX_UNIT *unit = MRN_TABLE_LIST_GET_DERIVED(table_list); st_select_lex *first_select_lex; if (unit) { @@ -9198,13 +9479,13 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, } DBUG_PRINT("info", ("mroonga: first_select_lex->options=%llu", - first_select_lex ? first_select_lex->options : 0)); + first_select_lex ? MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(first_select_lex) : 0)); if ( thd_sql_command(ha_thd()) == SQLCOM_SELECT && !select_lex->with_sum_func && !select_lex->group_list.elements && - !select_lex->having && + !MRN_SELECT_LEX_GET_HAVING_COND(select_lex) && select_lex->table_list.elements == 1 && select_lex->order_list.elements && select_lex->explicit_limit && @@ -9225,17 +9506,18 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, fast_order_limit = false; DBUG_VOID_RETURN; } - if (first_select_lex && (first_select_lex->options & OPTION_FOUND_ROWS)) { + if (first_select_lex && + (MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(first_select_lex) & OPTION_FOUND_ROWS)) { DBUG_PRINT("info", ("mroonga: fast_order_limit = false: " "SQL_CALC_FOUND_ROWS is specified")); fast_order_limit = false; DBUG_VOID_RETURN; } - Item *where = select_lex->where; + bool is_storage_mode = !(share->wrapper_mode); + Item *where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex); const Item_func *match_against = NULL; if (where) { - bool is_storage_mode = !(share->wrapper_mode); mrn::ConditionConverter converter(ctx, grn_table, is_storage_mode); if (!converter.is_convertable(where)) { DBUG_PRINT("info", @@ -9253,18 +9535,22 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, DBUG_VOID_RETURN; } } - *n_sort_keys = select_lex->order_list.elements; - *sort_keys = (grn_table_sort_key *)malloc(sizeof(grn_table_sort_key) * - *n_sort_keys); + int n_max_sort_keys = select_lex->order_list.elements; + *n_sort_keys = 0; + size_t sort_keys_size = sizeof(grn_table_sort_key) * n_max_sort_keys; + *sort_keys = (grn_table_sort_key *)mrn_my_malloc(sort_keys_size, + MYF(MY_WME)); + memset(*sort_keys, 0, sort_keys_size); ORDER *order; int i; mrn_change_encoding(ctx, system_charset_info); - for (order = (ORDER *) select_lex->order_list.first, i = 0; order; + for (order = (ORDER *) select_lex->order_list.first, i = 0; + order; order = order->next, i++) { Item *item = *order->item; - if (grn_columns && item->type() == Item::FIELD_ITEM) + if (item->type() == Item::FIELD_ITEM) { - Field *field = ((Item_field *) (*order->item))->field; + Field *field = static_cast<Item_field *>(item)->field; const char *column_name = field->field_name; int column_name_size = strlen(column_name); @@ -9273,14 +9559,31 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, DBUG_PRINT("info", ("mroonga: fast_order_limit = false: " "sort by collated value isn't supported yet.")); fast_order_limit = false; - free(*sort_keys); + my_free(*sort_keys); *sort_keys = NULL; *n_sort_keys = 0; DBUG_VOID_RETURN; } - (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, - column_name, column_name_size); + if (is_storage_mode) { + (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, + column_name, column_name_size); + } else { + if (is_primary_key_field(field)) { + (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, + MRN_COLUMN_NAME_KEY, + strlen(MRN_COLUMN_NAME_KEY)); + } else { + DBUG_PRINT("info", ("mroonga: fast_order_limit = false: " + "sort by not primary key value " + "isn't supported in wrapper mode.")); + fast_order_limit = false; + my_free(*sort_keys); + *sort_keys = NULL; + *n_sort_keys = 0; + DBUG_VOID_RETURN; + } + } } else if (!match_against || match_against->eq(item, true)) { (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, MRN_COLUMN_NAME_SCORE, @@ -9289,7 +9592,7 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, DBUG_PRINT("info", ("mroonga: fast_order_limit = false: " "sort by computed value isn't supported.")); fast_order_limit = false; - free(*sort_keys); + my_free(*sort_keys); *sort_keys = NULL; *n_sort_keys = 0; DBUG_VOID_RETURN; @@ -9301,6 +9604,7 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, } else { (*sort_keys)[i].flags = GRN_TABLE_SORT_DESC; } + (*n_sort_keys)++; } DBUG_PRINT("info", ("mroonga: fast_order_limit = true")); fast_order_limit = true; @@ -9329,7 +9633,8 @@ int ha_mroonga::generic_store_bulk_variable_size_string(Field *field, String value; field->val_str(NULL, &value); grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0); - DBUG_PRINT("info", ("mroonga: length=%u", value.length())); + DBUG_PRINT("info", ("mroonga: length=%" MRN_FORMAT_STRING_LENGTH, + value.length())); DBUG_PRINT("info", ("mroonga: value=%s", value.c_ptr_safe())); GRN_TEXT_SET(ctx, buf, value.ptr(), value.length()); DBUG_RETURN(error); @@ -9392,7 +9697,7 @@ int ha_mroonga::generic_store_bulk_integer(Field *field, grn_obj *buf) "unknown integer value size: <%u>: " "available sizes: [1, 2, 3, 4, 8]", size); - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, error, error_message); break; } @@ -9432,7 +9737,7 @@ int ha_mroonga::generic_store_bulk_unsigned_integer(Field *field, grn_obj *buf) "unknown unsigned integer value size: <%u>: " "available sizes: [1, 2, 3, 4, 8]", size); - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, error, error_message); break; } @@ -9459,7 +9764,7 @@ int ha_mroonga::generic_store_bulk_float(Field *field, grn_obj *buf) "unknown float value size: <%u>: " "available sizes: [4, 8]", size); - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, error, error_message); break; } @@ -9519,7 +9824,7 @@ int ha_mroonga::generic_store_bulk_date(Field *field, grn_obj *buf) mrn::TimeConverter time_converter; long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9539,7 +9844,7 @@ int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf) long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9559,7 +9864,7 @@ int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf) long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9591,7 +9896,7 @@ int ha_mroonga::generic_store_bulk_year(Field *field, grn_obj *buf) mrn::TimeConverter time_converter; long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9612,7 +9917,7 @@ int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf) long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9633,7 +9938,7 @@ int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf) long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9654,7 +9959,7 @@ int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf) long long int time = time_converter.mysql_time_to_grn_time(&mysql_date, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); @@ -9690,7 +9995,7 @@ int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf) { MRN_DBUG_ENTER_METHOD(); int error = 0; -#ifdef HAVE_SPATIAL +#ifdef MRN_HAVE_SPATIAL String buffer; Field_geom *geometry = (Field_geom *)field; String *value = geometry->val_str(0, &buffer); @@ -9876,7 +10181,7 @@ void ha_mroonga::storage_store_field_integer(Field *field, "unknown integer value size: <%d>: " "available sizes: [1, 2, 4, 8]", value_length); - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, HA_ERR_UNSUPPORTED, error_message); storage_store_field_string(field, value, value_length); break; @@ -9928,7 +10233,7 @@ void ha_mroonga::storage_store_field_unsigned_integer(Field *field, "unknown integer value size: <%d>: " "available sizes: [1, 2, 4, 8]", value_length); - push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, + push_warning(ha_thd(), MRN_SEVERITY_WARNING, HA_ERR_UNSUPPORTED, error_message); storage_store_field_string(field, value, value_length); break; @@ -10121,7 +10426,7 @@ void ha_mroonga::storage_store_field_geometry(Field *field, uint value_length) { MRN_DBUG_ENTER_METHOD(); -#ifdef HAVE_SPATIAL +#ifdef MRN_HAVE_SPATIAL uchar wkb[SRID_SIZE + WKB_HEADER_SIZE + POINT_DATA_SIZE]; grn_geo_point *field_value = (grn_geo_point *)value; int latitude, longitude; @@ -10526,7 +10831,7 @@ int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key, mrn::TimeConverter time_converter; time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &time, 8); @@ -10573,7 +10878,7 @@ int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key, mrn::TimeConverter time_converter; time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } #else @@ -10608,7 +10913,7 @@ int ha_mroonga::storage_encode_key_year(Field *field, const uchar *key, long long int time = time_converter.tm_to_grn_time(&datetime, usec, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &time, 8); @@ -10657,7 +10962,7 @@ int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key, time = time_converter.tm_to_grn_time(&date, usec, &truncated); } if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &time, 8); @@ -10683,7 +10988,7 @@ int ha_mroonga::storage_encode_key_timestamp2(Field *field, const uchar *key, long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &grn_time, 8); @@ -10710,7 +11015,7 @@ int ha_mroonga::storage_encode_key_datetime2(Field *field, const uchar *key, long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &grn_time, 8); @@ -10737,7 +11042,7 @@ int ha_mroonga::storage_encode_key_time2(Field *field, const uchar *key, long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &grn_time, 8); @@ -10759,7 +11064,7 @@ int ha_mroonga::storage_encode_key_enum(Field *field, const uchar *key, memcpy(buf, &value, *size); } else { uint16 value; - shortget(value, key); + mrn::value_decoder::decode(&value, key); *size = 2; memcpy(buf, &value, *size); } @@ -10871,7 +11176,7 @@ int ha_mroonga::storage_encode_key(Field *field, const uchar *key, { float float_value; double double_value; - float4get(float_value, ptr); + mrn::value_decoder::decode(&float_value, ptr); double_value = float_value; memcpy(buf, &double_value, 8); *size = 8; @@ -10880,7 +11185,7 @@ int ha_mroonga::storage_encode_key(Field *field, const uchar *key, case MYSQL_TYPE_DOUBLE: { double val; - float8get(val, ptr); + mrn::value_decoder::decode(&val, ptr); memcpy(buf, &val, 8); *size = 8; break; @@ -10907,7 +11212,7 @@ int ha_mroonga::storage_encode_key(Field *field, const uchar *key, long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated); if (truncated) { - field->set_warning(Sql_condition::WARN_LEVEL_WARN, + field->set_warning(MRN_SEVERITY_WARNING, WARN_DATA_TRUNCATED, 1); } memcpy(buf, &time, 8); @@ -10994,16 +11299,29 @@ int ha_mroonga::generic_reset() { MRN_DBUG_ENTER_METHOD(); int error = 0; - if (thd_sql_command(ha_thd()) == SQLCOM_SELECT) { - st_select_lex *select_lex = table->pos_in_table_list->select_lex; - List_iterator<Item_func_match> iterator(*(select_lex->ftfunc_list)); - Item_func_match *item; - while ((item = iterator++)) { - if (item->ft_handler) { - mrn_generic_ft_clear(item->ft_handler); - } + + if (thd_sql_command(ha_thd()) != SQLCOM_SELECT) { + DBUG_RETURN(error); + } + + TABLE_LIST *table_list = table->pos_in_table_list; + if (!table_list) { + DBUG_RETURN(error); + } + + st_select_lex *select_lex = table_list->select_lex; + if (!select_lex) { + DBUG_RETURN(error); + } + + List_iterator<Item_func_match> iterator(*(select_lex->ftfunc_list)); + Item_func_match *item; + while ((item = iterator++)) { + if (item->ft_handler) { + mrn_generic_ft_clear(item->ft_handler); } } + DBUG_RETURN(error); } @@ -12040,9 +12358,9 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info) } if (create_info->connect_string.str) { slot_data->alter_connect_string = - my_strndup(create_info->connect_string.str, - create_info->connect_string.length, - MYF(MY_WME)); + mrn_my_strndup(create_info->connect_string.str, + create_info->connect_string.length, + MYF(MY_WME)); } if (slot_data->alter_comment) { my_free(slot_data->alter_comment); @@ -12050,9 +12368,9 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info) } if (create_info->comment.str) { slot_data->alter_comment = - my_strndup(create_info->comment.str, - create_info->comment.length, - MYF(MY_WME)); + mrn_my_strndup(create_info->comment.str, + create_info->comment.length, + MYF(MY_WME)); } if (share && share->disable_keys) { slot_data->disable_keys_create_info = create_info; @@ -12365,14 +12683,15 @@ bool ha_mroonga::wrapper_is_crashed() const bool ha_mroonga::storage_is_crashed() const { MRN_DBUG_ENTER_METHOD(); - bool crashed = handler::is_crashed(); + mrn::DatabaseRepairer repairer(ctx, ha_thd()); + bool crashed = repairer.is_crashed(); DBUG_RETURN(crashed); } bool ha_mroonga::is_crashed() const { MRN_DBUG_ENTER_METHOD(); - int crashed; + bool crashed; if (share->wrapper_mode) { crashed = wrapper_is_crashed(); @@ -12384,52 +12703,52 @@ bool ha_mroonga::is_crashed() const bool ha_mroonga::wrapper_auto_repair(int error) const { - bool crashed; + bool repaired; MRN_DBUG_ENTER_METHOD(); MRN_SET_WRAP_SHARE_KEY(share, table->s); MRN_SET_WRAP_TABLE_KEY(this, table); #ifdef MRN_HANDLER_AUTO_REPAIR_HAVE_ERROR - crashed = wrap_handler->auto_repair(error); + repaired = wrap_handler->auto_repair(error); #else - crashed = wrap_handler->auto_repair(); + repaired = wrap_handler->auto_repair(); #endif MRN_SET_BASE_SHARE_KEY(share, table->s); MRN_SET_BASE_TABLE_KEY(this, table); - DBUG_RETURN(crashed); + DBUG_RETURN(repaired); } bool ha_mroonga::storage_auto_repair(int error) const { MRN_DBUG_ENTER_METHOD(); - bool crashed; + bool repaired; #ifdef MRN_HANDLER_AUTO_REPAIR_HAVE_ERROR - crashed = handler::auto_repair(error); + repaired = handler::auto_repair(error); #else - crashed = handler::auto_repair(); + repaired = handler::auto_repair(); #endif - DBUG_RETURN(crashed); + DBUG_RETURN(repaired); } bool ha_mroonga::auto_repair(int error) const { MRN_DBUG_ENTER_METHOD(); - bool crashed; + bool repaired; // TODO: We should consider about creating share for error = // ER_CANT_OPEN_FILE. The following code just ignores the error. if (share && share->wrapper_mode) { - crashed = wrapper_auto_repair(error); + repaired = wrapper_auto_repair(error); } else { - crashed = storage_auto_repair(error); + repaired = storage_auto_repair(error); } - DBUG_RETURN(crashed); + DBUG_RETURN(repaired); } bool ha_mroonga::auto_repair() const { MRN_DBUG_ENTER_METHOD(); - bool crashed = auto_repair(HA_ERR_CRASHED_ON_USAGE); - DBUG_RETURN(crashed); + bool repaired = auto_repair(HA_ERR_CRASHED_ON_USAGE); + DBUG_RETURN(repaired); } int ha_mroonga::generic_disable_index(int i, KEY *key_info) @@ -12760,7 +13079,12 @@ int ha_mroonga::wrapper_check(THD* thd, HA_CHECK_OPT* check_opt) int ha_mroonga::storage_check(THD* thd, HA_CHECK_OPT* check_opt) { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + mrn::DatabaseRepairer repairer(ctx, thd); + if (repairer.repair()) { + DBUG_RETURN(HA_ADMIN_OK); + } else { + DBUG_RETURN(HA_ADMIN_CORRUPT); + } } int ha_mroonga::check(THD* thd, HA_CHECK_OPT* check_opt) @@ -12929,6 +13253,58 @@ int ha_mroonga::wrapper_recreate_indexes(THD *thd) DBUG_RETURN(error); } +int ha_mroonga::storage_recreate_indexes(THD *thd) +{ + MRN_DBUG_ENTER_METHOD(); + + if (share->disable_keys) + DBUG_RETURN(HA_ADMIN_OK); + + clear_indexes(); + + int n_columns = table->s->fields; + for (int i = 0; i < n_columns; i++) { + grn_obj *column = grn_columns[i]; + + if (!column) + continue; + + int n_hooks = grn_obj_get_nhooks(ctx, column, GRN_HOOK_SET); + for (int j = 0; j < n_hooks; j++) { + grn_obj_delete_hook(ctx, column, GRN_HOOK_SET, j); + } + } + + uint n_keys = table_share->keys; + mrn::PathMapper mapper(table_share->normalized_path.str); + for (uint i = 0; i < n_keys; i++) { + if (share->index_table && share->index_table[i]) + continue; + + if (i == table_share->primary_key) + continue; + + mrn::IndexTableName index_table_name(mapper.table_name(), + table_share->key_info[i].name); + char index_column_full_name[MRN_MAX_PATH_SIZE]; + snprintf(index_column_full_name, MRN_MAX_PATH_SIZE, + "%s.%s", index_table_name.c_str(), INDEX_COLUMN_NAME); + remove_grn_obj_force(index_column_full_name); + remove_grn_obj_force(index_table_name.c_str()); + } + + int error; + error = storage_create_indexes(table, mapper.table_name(), grn_table, share); + if (error) + DBUG_RETURN(HA_ADMIN_FAILED); + + error = storage_open_indexes(table_share->normalized_path.str); + if (error) + DBUG_RETURN(HA_ADMIN_FAILED); + + DBUG_RETURN(HA_ADMIN_OK); +} + int ha_mroonga::wrapper_repair(THD* thd, HA_CHECK_OPT* check_opt) { int error; @@ -12947,7 +13323,8 @@ int ha_mroonga::wrapper_repair(THD* thd, HA_CHECK_OPT* check_opt) int ha_mroonga::storage_repair(THD* thd, HA_CHECK_OPT* check_opt) { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED); + int error = storage_recreate_indexes(thd); + DBUG_RETURN(error); } int ha_mroonga::repair(THD* thd, HA_CHECK_OPT* check_opt) @@ -12966,35 +13343,36 @@ int ha_mroonga::repair(THD* thd, HA_CHECK_OPT* check_opt) bool ha_mroonga::wrapper_check_and_repair(THD *thd) { - // XXX: success is valid variable name? - bool success; + bool is_error_or_not_supported; MRN_DBUG_ENTER_METHOD(); MRN_SET_WRAP_SHARE_KEY(share, table->s); MRN_SET_WRAP_TABLE_KEY(this, table); - success = wrap_handler->ha_check_and_repair(thd); + is_error_or_not_supported = wrap_handler->ha_check_and_repair(thd); MRN_SET_BASE_SHARE_KEY(share, table->s); MRN_SET_BASE_TABLE_KEY(this, table); - DBUG_RETURN(success); + DBUG_RETURN(is_error_or_not_supported); } bool ha_mroonga::storage_check_and_repair(THD *thd) { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(true); + bool is_error = false; + mrn::DatabaseRepairer repairer(ctx, thd); + is_error = !repairer.repair(); + DBUG_RETURN(is_error); } bool ha_mroonga::check_and_repair(THD *thd) { MRN_DBUG_ENTER_METHOD(); - // XXX: success is valid variable name? - bool success; + bool is_error_or_not_supported; if (share->wrapper_mode) { - success = wrapper_check_and_repair(thd); + is_error_or_not_supported = wrapper_check_and_repair(thd); } else { - success = storage_check_and_repair(thd); + is_error_or_not_supported = storage_check_and_repair(thd); } - DBUG_RETURN(success); + DBUG_RETURN(is_error_or_not_supported); } int ha_mroonga::wrapper_analyze(THD* thd, HA_CHECK_OPT* check_opt) @@ -13059,7 +13437,11 @@ bool ha_mroonga::wrapper_is_fatal_error(int error_num, uint flags) MRN_DBUG_ENTER_METHOD(); MRN_SET_WRAP_SHARE_KEY(share, table->s); MRN_SET_WRAP_TABLE_KEY(this, table); +#ifdef MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS res = wrap_handler->is_fatal_error(error_num, flags); +#else + res = wrap_handler->is_fatal_error(error_num); +#endif MRN_SET_BASE_SHARE_KEY(share, table->s); MRN_SET_BASE_TABLE_KEY(this, table); DBUG_RETURN(res); @@ -13068,7 +13450,11 @@ bool ha_mroonga::wrapper_is_fatal_error(int error_num, uint flags) bool ha_mroonga::storage_is_fatal_error(int error_num, uint flags) { MRN_DBUG_ENTER_METHOD(); +#ifdef MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS bool is_fatal_error = handler::is_fatal_error(error_num, flags); +#else + bool is_fatal_error = handler::is_fatal_error(error_num); +#endif DBUG_RETURN(is_fatal_error); } @@ -13234,7 +13620,9 @@ enum_alter_inplace_result ha_mroonga::wrapper_check_if_supported_inplace_alter( uint n_keys; uint i; enum_alter_inplace_result result_mroonga = HA_ALTER_INPLACE_NO_LOCK; - DBUG_PRINT("info", ("mroonga: handler_flags=%lu", ha_alter_info->handler_flags)); + DBUG_PRINT("info", + ("mroonga: handler_flags=%lu", + static_cast<ulong>(ha_alter_info->handler_flags))); if (wrapper_is_comment_changed(table, altered_table)) { DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); @@ -13267,7 +13655,7 @@ enum_alter_inplace_result ha_mroonga::wrapper_check_if_supported_inplace_alter( alter_index_add_count = 0; alter_handler_flags = ha_alter_info->handler_flags; if (!(alter_key_info_buffer = (KEY *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &alter_key_info_buffer, sizeof(KEY) * ha_alter_info->key_count, &alter_index_drop_buffer, sizeof(KEY) * ha_alter_info->index_drop_count, &alter_index_add_buffer, sizeof(uint) * ha_alter_info->index_add_count, @@ -13362,8 +13750,6 @@ enum_alter_inplace_result ha_mroonga::storage_check_if_supported_inplace_alter( Alter_inplace_info::DROP_INDEX | Alter_inplace_info::ADD_UNIQUE_INDEX | Alter_inplace_info::DROP_UNIQUE_INDEX | - Alter_inplace_info::ADD_PK_INDEX | - Alter_inplace_info::DROP_PK_INDEX | Alter_inplace_info::ADD_COLUMN | Alter_inplace_info::DROP_COLUMN | Alter_inplace_info::ALTER_COLUMN_NAME; @@ -13480,7 +13866,7 @@ bool ha_mroonga::wrapper_inplace_alter_table( tmp_table_share.keys = ha_alter_info->key_count; tmp_table_share.fields = 0; if (!(tmp_share = (MRN_SHARE *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &tmp_share, sizeof(*tmp_share), &key_parser, sizeof(char *) * (tmp_table_share.keys), &key_parser_length, sizeof(uint) * (tmp_table_share.keys), @@ -13629,7 +14015,7 @@ bool ha_mroonga::storage_inplace_alter_table_index( tmp_table_share.keys = ha_alter_info->key_count; tmp_table_share.fields = 0; if (!(tmp_share = (MRN_SHARE *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &tmp_share, sizeof(*tmp_share), &index_table, sizeof(char *) * tmp_table_share.keys, &index_table_length, sizeof(uint) * tmp_table_share.keys, @@ -13763,7 +14149,7 @@ bool ha_mroonga::storage_inplace_alter_table_add_column( uint *index_table_length, *key_parser_length, *col_flags_length, *col_type_length; tmp_table_share.keys = 0; tmp_table_share.fields = altered_table->s->fields; - tmp_share = (MRN_SHARE *)my_multi_malloc( + tmp_share = (MRN_SHARE *)mrn_my_multi_malloc( MYF(MY_WME | MY_ZEROFILL), &tmp_share, sizeof(*tmp_share), &index_table, sizeof(char *) * tmp_table_share.keys, @@ -14155,8 +14541,8 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info, char **key_parser; uint *key_parser_length; MRN_DBUG_ENTER_METHOD(); - if (!(wrap_alter_key_info = (KEY *) my_malloc(sizeof(KEY) * num_of_keys, - MYF(MY_WME)))) { + if (!(wrap_alter_key_info = (KEY *) mrn_my_malloc(sizeof(KEY) * num_of_keys, + MYF(MY_WME)))) { MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -14165,7 +14551,7 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info, tmp_table_share.keys = n_keys + num_of_keys; tmp_table_share.fields = 0; if (!(tmp_share = (MRN_SHARE *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &tmp_share, sizeof(*tmp_share), &key_parser, sizeof(char *) * (n_keys + num_of_keys), &key_parser_length, sizeof(uint) * (n_keys + num_of_keys), @@ -14299,7 +14685,7 @@ int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info, tmp_table_share.keys = n_keys + num_of_keys; tmp_table_share.fields = 0; if (!(tmp_share = (MRN_SHARE *) - my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &tmp_share, sizeof(*tmp_share), &index_table, sizeof(char*) * tmp_table_share.keys, &index_table_length, sizeof(uint) * tmp_table_share.keys, @@ -14663,7 +15049,7 @@ void ha_mroonga::storage_get_auto_increment(ulonglong offset, *first_value = long_term_share->auto_inc_value; DBUG_PRINT("info", ("mroonga: *first_value(auto_inc_value)=%llu", *first_value)); - *nb_reserved_values = ULONGLONG_MAX; + *nb_reserved_values = UINT_MAX64; } else { handler::get_auto_increment(offset, increment, nb_desired_values, first_value, nb_reserved_values); @@ -14811,6 +15197,7 @@ int ha_mroonga::check_for_upgrade(HA_CHECK_OPT *check_opt) DBUG_RETURN(error); } +#ifdef MRN_HANDLER_HAVE_RESET_AUTO_INCREMENT int ha_mroonga::wrapper_reset_auto_increment(ulonglong value) { int res; @@ -14847,6 +15234,7 @@ int ha_mroonga::reset_auto_increment(ulonglong value) } DBUG_RETURN(res); } +#endif void ha_mroonga::set_pk_bitmap() { @@ -15199,8 +15587,8 @@ char *ha_mroonga::storage_get_foreign_key_create_info() } create_info_str.q_append(") ON DELETE RESTRICT ON UPDATE RESTRICT", 39); } - if (!(create_info = (char *) my_malloc(create_info_str.length() + 1, - MYF(MY_WME)))) { + if (!(create_info = (char *) mrn_my_malloc(create_info_str.length() + 1, + MYF(MY_WME)))) { DBUG_RETURN(NULL); } memcpy(create_info, create_info_str.ptr(), create_info_str.length()); |