diff options
Diffstat (limited to 'storage/mroonga/ha_mroonga.cpp')
-rw-r--r-- | storage/mroonga/ha_mroonga.cpp | 1520 |
1 files changed, 1094 insertions, 426 deletions
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 8b9a08b59dc..83f03fcb272 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -2,7 +2,7 @@ /* Copyright(C) 2010 Tetsuro IKEDA Copyright(C) 2010-2013 Kentoku SHIBA - Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com> Copyright(C) 2013 Kenji Maruyama <mmmaru777@gmail.com> This library is free software; you can redistribute it and/or @@ -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> @@ -116,23 +124,14 @@ } \ } while (0) #else -# if MYSQL_VERSION_ID >= 50500 -# ifdef DBUG_OFF -# ifndef _WIN32 -extern mysql_mutex_t LOCK_open; -# endif -# endif -static mysql_mutex_t *mrn_LOCK_open; -# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open) -# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open) -# else +# ifdef DBUG_OFF # ifndef _WIN32 -extern pthread_mutex_t LOCK_open; +extern mysql_mutex_t LOCK_open; # endif -static pthread_mutex_t *mrn_LOCK_open; -# define mrn_open_mutex_lock(share) -# define mrn_open_mutex_unlock(share) # endif +static mysql_mutex_t *mrn_LOCK_open; +# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open) +# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open) #endif #if MYSQL_VERSION_ID >= 50600 @@ -157,7 +156,11 @@ static pthread_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 @@ -166,15 +169,10 @@ static pthread_mutex_t *mrn_LOCK_open; # else # define MRN_PLUGIN_LAST_VALUES NULL # endif -# define MRN_ABORT_ON_WARNING(thd) thd->abort_on_warning -#endif - -#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; +# 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 @@ -190,12 +188,69 @@ static pthread_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"; @@ -207,20 +262,55 @@ 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); +#ifdef HAVE_PSI_INTERFACE +# 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_log_mutex_key; +static PSI_mutex_key mrn_db_manager_mutex_key; + +static PSI_mutex_info mrn_mutexes[] = +{ + {&mrn_open_tables_mutex_key, "open_tables", PSI_FLAG_GLOBAL}, + {&mrn_long_term_share_mutex_key, "long_term_share", PSI_FLAG_GLOBAL}, + {&mrn_allocated_thds_mutex_key, "allocated_thds", PSI_FLAG_GLOBAL}, + {&mrn_share_mutex_key, "share", 0}, + {&mrn_long_term_share_auto_inc_mutex_key, + "long_term_share::auto_inc", 0}, + {&mrn_log_mutex_key, "log", PSI_FLAG_GLOBAL}, + {&mrn_db_manager_mutex_key, "DatabaseManager", PSI_FLAG_GLOBAL} +}; +#endif + /* global variables */ -static pthread_mutex_t mrn_log_mutex; handlerton *mrn_hton_ptr; HASH mrn_open_tables; -pthread_mutex_t mrn_open_tables_mutex; +mysql_mutex_t mrn_open_tables_mutex; HASH mrn_long_term_share; -pthread_mutex_t mrn_long_term_share_mutex; +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 static inline double round(double x) { @@ -272,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; @@ -506,6 +603,33 @@ static int mrn_lock_timeout = grn_get_lock_timeout(); static char *mrn_libgroonga_version = const_cast<char *>(grn_get_version()); static char *mrn_version = const_cast<char *>(MRN_VERSION); static char *mrn_vector_column_delimiter = NULL; +static my_bool mrn_libgroonga_support_zlib = FALSE; +static my_bool mrn_libgroonga_support_lz4 = FALSE; +typedef enum { + MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT = (1 << 0), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_QUERY = (1 << 1), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT = (1 << 2), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN = (1 << 3), + 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", + "SYNTAX_SCRIPT", + "ALLOW_COLUMN", + "ALLOW_UPDATE", + "ALLOW_LEADING_NOT", + NullS +}; +static TYPELIB mrn_boolean_mode_syntax_flags_typelib = { + array_elements(mrn_boolean_mode_sytnax_flag_names) - 1, + "", + mrn_boolean_mode_sytnax_flag_names, + NULL +}; +#endif typedef enum { MRN_ACTION_ON_ERROR_ERROR, @@ -552,9 +676,6 @@ static grn_logger mrn_logger = { NULL }; -/* global hashes and mutexes */ -HASH mrn_allocated_thds; -pthread_mutex_t mrn_allocated_thds_mutex; static uchar *mrn_allocated_thds_get_key(const uchar *record, size_t *length, my_bool not_used __attribute__ ((unused))) @@ -569,22 +690,42 @@ 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[] = { "NONE", "EMERG", "ALERT", - "CRIT", "ERROR", "WARNING", - "NOTICE", "INFO", "DEBUG", - "DUMP", NullS }; -static TYPELIB mrn_log_level_typelib = -{ - array_elements(mrn_log_level_type_names)-1, +static const char *mrn_log_level_type_names[] = { + "NONE", + "EMERG", + "ALERT", + "CRIT", + "ERROR", + "WARNING", + "NOTICE", + "INFO", + "DEBUG", + "DUMP", + NullS +}; +static TYPELIB mrn_log_level_typelib = { + array_elements(mrn_log_level_type_names) - 1, "mrn_log_level_typelib", mrn_log_level_type_names, NULL @@ -677,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)); - my_free(old_log_file_name, MYF(0)); + *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); @@ -717,8 +858,8 @@ 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, MYF(0)); - *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); + my_free(*old_value_ptr); + *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); #else *old_value_ptr = (char *)new_value; #endif @@ -760,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, @@ -771,8 +912,8 @@ static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var char **old_value_ptr = (char **)var_ptr; #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR - my_free(*old_value_ptr, MYF(0)); - *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); + my_free(*old_value_ptr); + *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); #else *old_value_ptr = (char *)new_value; #endif @@ -796,9 +937,9 @@ static void mrn_database_path_prefix_update(THD *thd, char **old_value_ptr = (char **)var_ptr; #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR if (*old_value_ptr) - my_free(*old_value_ptr, MYF(0)); + 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 @@ -876,6 +1017,73 @@ static MYSQL_SYSVAR_STR(version, mrn_version, NULL, MRN_VERSION); +static my_bool grn_check_zlib_support() +{ + bool is_zlib_support = false; + grn_obj grn_support_p; + + GRN_BOOL_INIT(&grn_support_p, 0); + grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZLIB, &grn_support_p); + is_zlib_support = (GRN_BOOL_VALUE(&grn_support_p)); + grn_obj_unlink(&mrn_ctx, &grn_support_p); + + return is_zlib_support; +} + +static my_bool grn_check_lz4_support() +{ + bool is_lz4_support = false; + grn_obj grn_support_p; + + GRN_BOOL_INIT(&grn_support_p, 0); + grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_LZ4, &grn_support_p); + is_lz4_support = (GRN_BOOL_VALUE(&grn_support_p)); + grn_obj_unlink(&mrn_ctx, &grn_support_p); + + return is_lz4_support; +} + +static MYSQL_SYSVAR_BOOL(libgroonga_support_zlib, mrn_libgroonga_support_zlib, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "The status of libgroonga supports zlib", + NULL, + NULL, + grn_check_zlib_support()); + +static MYSQL_SYSVAR_BOOL(libgroonga_support_lz4, mrn_libgroonga_support_lz4, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "The status of libgroonga supports LZ4", + NULL, + 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. " + "Available flags: " + "DEFAULT(=SYNTAX_QUERY,ALLOW_LEADING_NOT), " + "SYNTAX_QUERY, SYNTAX_SCRIPT, " + "ALLOW_COLUMN, ALLOW_UPDATE and ALLOW_LEADING_NOT", + NULL, + 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[] = { MYSQL_SYSVAR(log_level), @@ -891,6 +1099,12 @@ static struct st_mysql_sys_var *mrn_system_variables[] = MYSQL_SYSVAR(libgroonga_version), MYSQL_SYSVAR(version), 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 }; @@ -917,7 +1131,7 @@ static ST_FIELD_INFO i_s_mrn_stats_fields_info[] = MYSQL_TYPE_LONG, 0, 0, - "Rows written to groonga", + "Rows written to Groonga", SKIP_OPEN_TABLE }, { @@ -926,7 +1140,7 @@ static ST_FIELD_INFO i_s_mrn_stats_fields_info[] = MYSQL_TYPE_LONG, 0, 0, - "Rows read from groonga", + "Rows read from Groonga", SKIP_OPEN_TABLE } }; @@ -1010,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; @@ -1191,7 +1409,112 @@ static grn_builtin_type mrn_grn_type_from_field(grn_ctx *ctx, Field *field, return type; } -#ifdef HAVE_SPATIAL +grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd, + grn_ctx *ctx, + const char *flag_names, + uint flag_names_length) +{ + grn_obj_flags flags = 0; + const char *flag_names_end = flag_names + flag_names_length; + + 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 >= 13 && !memcmp(flag_names, "COLUMN_SCALAR", 13)) { + flags |= GRN_OBJ_COLUMN_SCALAR; + flag_names += 13; + } else if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_VECTOR", 13)) { + flags |= GRN_OBJ_COLUMN_VECTOR; + flag_names += 13; + } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZLIB", 13)) { + if (mrn_libgroonga_support_zlib) { + flags |= GRN_OBJ_COMPRESS_ZLIB; + } else { + push_warning_printf(thd, MRN_SEVERITY_WARNING, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, + "COMPRESS_ZLIB"); + } + flag_names += 13; + } else if (rest_length >= 12 && !memcmp(flag_names, "COMPRESS_LZ4", 12)) { + if (mrn_libgroonga_support_lz4) { + flags |= GRN_OBJ_COMPRESS_LZ4; + } else { + push_warning_printf(thd, MRN_SEVERITY_WARNING, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, + "COMPRESS_LZ4"); + } + flag_names += 12; + } 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_COLUMN_FLAG_NUM, + ER_MRN_INVALID_COLUMN_FLAG_STR, + invalid_flag_name, + "COLUMN_SCALAR"); + flags |= GRN_OBJ_COLUMN_SCALAR; + break; + } + } + return flags; +} + +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) { @@ -1228,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; @@ -1254,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) { @@ -1275,11 +1596,16 @@ static int mrn_init(void *p) hton = (handlerton *)p; hton->state = SHOW_OPTION_YES; hton->create = mrn_handler_create; - hton->flags = HTON_NO_PARTITION; + 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 @@ -1294,21 +1620,20 @@ static int mrn_init(void *p) # endif # ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE mrn_LOCK_open = -# if MYSQL_VERSION_ID >= 50500 (mysql_mutex_t *)GetProcAddress(current_module, "?LOCK_open@@3Ust_mysql_mutex@@A"); -# else - (pthread_mutex_t *)GetProcAddress(current_module, - "?LOCK_open@@3U_RTL_CRITICAL_SECTION@@A"); -# endif # 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; @@ -1321,7 +1646,14 @@ static int mrn_init(void *p) # endif #endif - // init groonga +#ifdef HAVE_PSI_INTERFACE + if (PSI_server) { + const char *category = "mroonga"; + int n_mutexes = array_elements(mrn_mutexes); + PSI_server->register_mutex(category, mrn_mutexes, n_mutexes); + } +#endif + if (grn_init() != GRN_SUCCESS) { goto err_grn_init; } @@ -1335,7 +1667,17 @@ static int mrn_init(void *p) if (mrn_change_encoding(ctx, system_charset_info)) goto err_mrn_change_encoding; - if (pthread_mutex_init(&mrn_log_mutex, NULL) != 0) { +#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) { goto err_log_mutex_init; } @@ -1358,25 +1700,39 @@ static int mrn_init(void *p) grn_ctx_init(&mrn_db_manager_ctx, 0); grn_logger_set(&mrn_db_manager_ctx, &mrn_logger); - mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx); + if (mysql_mutex_init(mrn_db_manager_mutex_key, + &mrn_db_manager_mutex, + MY_MUTEX_INIT_FAST) != 0) { + GRN_LOG(&mrn_db_manager_ctx, GRN_LOG_ERROR, + "failed to initialize mutex for database manager"); + goto err_db_manager_mutex_init; + } + mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx, + &mrn_db_manager_mutex); if (!mrn_db_manager->init()) { goto err_db_manager_init; } - if ((pthread_mutex_init(&mrn_allocated_thds_mutex, NULL) != 0)) { + if ((mysql_mutex_init(mrn_allocated_thds_mutex_key, + &mrn_allocated_thds_mutex, + MY_MUTEX_INIT_FAST) != 0)) { goto err_allocated_thds_mutex_init; } if (my_hash_init(&mrn_allocated_thds, system_charset_info, 32, 0, 0, mrn_allocated_thds_get_key, 0, 0)) { goto error_allocated_thds_hash_init; } - if ((pthread_mutex_init(&mrn_open_tables_mutex, NULL) != 0)) { + if ((mysql_mutex_init(mrn_open_tables_mutex_key, + &mrn_open_tables_mutex, + MY_MUTEX_INIT_FAST) != 0)) { goto err_allocated_open_tables_mutex_init; } if (my_hash_init(&mrn_open_tables, system_charset_info, 32, 0, 0, mrn_open_tables_get_key, 0, 0)) { goto error_allocated_open_tables_hash_init; } - if ((pthread_mutex_init(&mrn_long_term_share_mutex, NULL) != 0)) { + if ((mysql_mutex_init(mrn_long_term_share_mutex_key, + &mrn_long_term_share_mutex, + MY_MUTEX_INIT_FAST) != 0)) { goto error_allocated_long_term_share_mutex_init; } if (my_hash_init(&mrn_long_term_share, system_charset_info, 32, 0, 0, @@ -1391,18 +1747,20 @@ static int mrn_init(void *p) return 0; error_allocated_long_term_share_hash_init: - pthread_mutex_destroy(&mrn_long_term_share_mutex); + mysql_mutex_destroy(&mrn_long_term_share_mutex); error_allocated_long_term_share_mutex_init: my_hash_free(&mrn_open_tables); error_allocated_open_tables_hash_init: - pthread_mutex_destroy(&mrn_open_tables_mutex); + mysql_mutex_destroy(&mrn_open_tables_mutex); err_allocated_open_tables_mutex_init: my_hash_free(&mrn_allocated_thds); error_allocated_thds_hash_init: - pthread_mutex_destroy(&mrn_allocated_thds_mutex); + mysql_mutex_destroy(&mrn_allocated_thds_mutex); err_allocated_thds_mutex_init: err_db_manager_init: delete mrn_db_manager; + mysql_mutex_destroy(&mrn_db_manager_mutex); +err_db_manager_mutex_init: grn_ctx_fin(&mrn_db_manager_ctx); grn_obj_unlink(ctx, mrn_db); err_db_create: @@ -1411,7 +1769,7 @@ err_db_create: mrn_log_file_opened = false; } err_log_file_open: - pthread_mutex_destroy(&mrn_log_mutex); + mysql_mutex_destroy(&mrn_log_mutex); err_log_mutex_init: err_mrn_change_encoding: grn_ctx_fin(ctx); @@ -1450,12 +1808,13 @@ static int mrn_deinit(void *p) } my_hash_free(&mrn_long_term_share); - pthread_mutex_destroy(&mrn_long_term_share_mutex); + mysql_mutex_destroy(&mrn_long_term_share_mutex); my_hash_free(&mrn_open_tables); - pthread_mutex_destroy(&mrn_open_tables_mutex); + mysql_mutex_destroy(&mrn_open_tables_mutex); my_hash_free(&mrn_allocated_thds); - pthread_mutex_destroy(&mrn_allocated_thds_mutex); + mysql_mutex_destroy(&mrn_allocated_thds_mutex); delete mrn_db_manager; + mysql_mutex_destroy(&mrn_db_manager_mutex); grn_ctx_fin(&mrn_db_manager_ctx); grn_obj_unlink(ctx, mrn_db); @@ -1466,7 +1825,7 @@ static int mrn_deinit(void *p) fclose(mrn_log_file); mrn_log_file_opened = false; } - pthread_mutex_destroy(&mrn_log_mutex); + mysql_mutex_destroy(&mrn_log_mutex); return 0; } @@ -1489,6 +1848,18 @@ mrn_declare_plugin(MRN_PLUGIN_NAME) i_s_mrn_stats mrn_declare_plugin_end; +static double mrn_get_score_value(grn_obj *score) +{ + MRN_DBUG_ENTER_FUNCTION(); + double score_value; + if (score->header.domain == GRN_DB_FLOAT) { + score_value = GRN_FLOAT_VALUE(score); + } else { + score_value = (double)GRN_INT32_VALUE(score); + } + DBUG_RETURN(score_value); +} + static void mrn_generic_ft_clear(FT_INFO *handler) { MRN_DBUG_ENTER_FUNCTION(); @@ -1555,7 +1926,7 @@ static float mrn_wrapper_ft_find_relevance(FT_INFO *handler, uchar *record, GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } @@ -1593,7 +1964,7 @@ static float mrn_wrapper_ft_get_relevance(FT_INFO *handler) GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } @@ -1640,7 +2011,7 @@ static float mrn_storage_ft_find_relevance(FT_INFO *handler, uchar *record, GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } DBUG_PRINT("info", ("mroonga: record_id=%d score=%g", @@ -1672,7 +2043,7 @@ static float mrn_storage_ft_get_relevance(FT_INFO *handler) GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } DBUG_PRINT("info", @@ -1916,7 +2287,6 @@ ha_mroonga::ha_mroonga(handlerton *hton, TABLE_SHARE *share_arg) grn_column_ranges(NULL), grn_index_tables(NULL), grn_index_columns(NULL), - grn_table_is_referenced(false), grn_source_column_geo(NULL), cursor_geo(NULL), @@ -1967,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)); } @@ -2126,7 +2499,7 @@ uint ha_mroonga::wrapper_max_supported_key_length() const uint ha_mroonga::storage_max_supported_key_length() const { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(HA_MAX_REC_LENGTH); + DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE); } uint ha_mroonga::max_supported_key_length() const @@ -2173,7 +2546,7 @@ uint ha_mroonga::wrapper_max_supported_key_part_length() const uint ha_mroonga::storage_max_supported_key_part_length() const { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(HA_MAX_REC_LENGTH); + DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE); } uint ha_mroonga::max_supported_key_part_length() const @@ -2348,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)); @@ -2392,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; @@ -2467,7 +2842,7 @@ int ha_mroonga::wrapper_create(const char *name, TABLE *table, share = NULL; if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -2486,7 +2861,7 @@ int ha_mroonga::wrapper_create(const char *name, TABLE *table, if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -2544,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); @@ -2832,15 +3210,16 @@ 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) { grn_obj *normalizer = NULL; if (tmp_share->normalizer) { - normalizer = grn_ctx_get(ctx, - tmp_share->normalizer, - tmp_share->normalizer_length); + normalizer = grn_ctx_get(ctx, + tmp_share->normalizer, + tmp_share->normalizer_length); } else { Field *field = &(key_info.key_part->field[0]); if (should_normalize(field)) { @@ -2902,12 +3281,10 @@ int ha_mroonga::storage_create(const char *name, TABLE *table, grn_obj_flags col_flags = GRN_OBJ_PERSISTENT; if (tmp_share->col_flags[i]) { - // TODO: parse flags - if (strcmp(tmp_share->col_flags[i], "COLUMN_VECTOR") == 0) { - col_flags |= GRN_OBJ_COLUMN_VECTOR; - } else { - col_flags |= GRN_OBJ_COLUMN_SCALAR; - } + col_flags |= mrn_parse_grn_column_create_flags(ha_thd(), + ctx, + tmp_share->col_flags[i], + tmp_share->col_flags_length[i]); } else { col_flags |= GRN_OBJ_COLUMN_SCALAR; } @@ -2987,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; } @@ -3012,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); @@ -3020,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); @@ -3350,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]; @@ -3448,7 +3836,8 @@ int ha_mroonga::storage_create_indexes(TABLE *table, const char *grn_table_name, } if (error) { while (true) { - if (index_tables[i]) { + if (index_tables[i] && + !(tmp_share->index_table && tmp_share->index_table[i])) { grn_obj_remove(ctx, index_tables[i]); } if (!i) @@ -3557,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); @@ -3574,7 +3963,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) MRN_SET_BASE_TABLE_KEY(this, table); if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -3598,7 +3987,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) MRN_SET_BASE_TABLE_KEY(this, table); if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -3626,7 +4015,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) wrap_handler = NULL; if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -3792,67 +4181,20 @@ 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); - } - - storage_set_keys_in_use(); - - ref_length = sizeof(grn_id); - DBUG_RETURN(0); -} - -void ha_mroonga::update_grn_table_is_referenced() -{ - MRN_DBUG_ENTER_METHOD(); - - grn_table_is_referenced = false; - - grn_table_cursor *cursor; - int flags = GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING;; - cursor = grn_table_cursor_open(ctx, grn_ctx_db(ctx), - NULL, 0, - NULL, 0, - 0, -1, flags); - if (cursor) { - grn_id id; - grn_id grn_table_id; - - grn_table_id = grn_obj_id(ctx, grn_table); - while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { - grn_obj *object; - grn_id range = GRN_ID_NIL; - - object = grn_ctx_at(ctx, id); - if (!object) { - ctx->rc = GRN_SUCCESS; - continue; - } - - switch (object->header.type) { - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: - range = grn_obj_get_range(ctx, object); - break; - default: - break; - } - grn_obj_unlink(ctx, object); - - if (range == grn_table_id) { - grn_table_is_referenced = true; - break; - } + 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); } - grn_table_cursor_close(ctx, cursor); + storage_set_keys_in_use(); } - DBUG_VOID_RETURN; + ref_length = sizeof(grn_id); + DBUG_RETURN(0); } int ha_mroonga::open_table(const char *name) @@ -3881,8 +4223,6 @@ int ha_mroonga::open_table(const char *name) DBUG_RETURN(error); } - update_grn_table_is_referenced(); - DBUG_RETURN(0); } @@ -3898,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) @@ -3910,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); @@ -3920,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) @@ -4002,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], @@ -4104,7 +4470,7 @@ int ha_mroonga::wrapper_close() wrap_handler = NULL; if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -4323,7 +4689,6 @@ int ha_mroonga::delete_table(const char *name) } if (!tmp_table_share) { - mrn::PathMapper mapper(name); #ifdef MRN_TABLE_LIST_INIT_REQUIRE_ALIAS table_list.init_one_table(mapper.db_name(), strlen(mapper.db_name()), mapper.mysql_table_name(), @@ -5032,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); } @@ -5090,6 +5455,7 @@ int ha_mroonga::storage_write_row(uchar *buf) { MRN_DBUG_ENTER_METHOD(); int error = 0; + bool unique_indexes_are_processed = false; if (is_dry_write()) { DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__)); @@ -5098,7 +5464,6 @@ int ha_mroonga::storage_write_row(uchar *buf) THD *thd = ha_thd(); int i; - uint j; int n_columns = table->s->fields; if (table->next_number_field && buf == table->record[0]) @@ -5115,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)); @@ -5156,6 +5521,11 @@ int ha_mroonga::storage_write_row(uchar *buf) } } + if (grn_table->header.type != GRN_TABLE_NO_KEY && pkey_size == 0) { + my_message(ER_ERROR_ON_WRITE, "primary key is empty", MYF(0)); + DBUG_RETURN(ER_ERROR_ON_WRITE); + } + int added; record_id = grn_table_add(ctx, grn_table, pkey, pkey_size, &added); if (ctx->rc) { @@ -5179,6 +5549,7 @@ int ha_mroonga::storage_write_row(uchar *buf) { goto err; } + unique_indexes_are_processed = true; grn_obj colbuf; GRN_VOID_INIT(&colbuf); @@ -5189,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; @@ -5270,13 +5641,16 @@ int ha_mroonga::storage_write_row(uchar *buf) DBUG_RETURN(0); err: - for (j = 0; j < table->s->keys; j++) { - if (j == pkey_nr) { - continue; - } - KEY *key_info = &table->key_info[j]; - if (key_info->flags & HA_NOSAME) { - grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]); + if (unique_indexes_are_processed) { + uint j; + for (j = 0; j < table->s->keys; j++) { + if (j == pkey_nr) { + continue; + } + KEY *key_info = &table->key_info[j]; + if (key_info->flags & HA_NOSAME) { + grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]); + } } } grn_table_delete_by_id(ctx, grn_table, record_id); @@ -5363,6 +5737,7 @@ err: int ha_mroonga::storage_write_row_unique_index(uchar *buf, KEY *key_info, grn_obj *index_table, + grn_obj *index_column, grn_id *key_id) { char *ukey = NULL; @@ -5398,7 +5773,29 @@ int ha_mroonga::storage_write_row_unique_index(uchar *buf, if (!added) { // duplicated error error = HA_ERR_FOUND_DUPP_KEY; - memcpy(dup_ref, key_id, sizeof(grn_id)); + grn_id duplicated_record_id = GRN_ID_NIL; + { + grn_table_cursor *table_cursor; + table_cursor = grn_table_cursor_open(ctx, index_table, + ukey, ukey_size, + ukey, ukey_size, + 0, -1, 0); + if (table_cursor) { + grn_obj *index_cursor; + index_cursor = grn_index_cursor_open(ctx, table_cursor, index_column, + GRN_ID_NIL, GRN_ID_MAX, 0); + if (index_cursor) { + grn_posting *posting; + posting = grn_index_cursor_next(ctx, index_cursor, NULL); + if (posting) { + duplicated_record_id = posting->rid; + } + } + grn_obj_unlink(ctx, index_cursor); + } + grn_table_cursor_close(ctx, table_cursor); + } + memcpy(dup_ref, &duplicated_record_id, sizeof(grn_id)); if (!ignoring_duplicated_key) { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated id on insert: update unique index: <%.*s>", @@ -5431,9 +5828,14 @@ int ha_mroonga::storage_write_row_unique_indexes(uchar *buf) if (!index_table) { continue; } + grn_obj *index_column = grn_index_columns[i]; + if (!index_column) { + continue; + } if ((error = storage_write_row_unique_index(buf, key_info, - index_table, &key_id[i]))) + index_table, index_column, + &key_id[i]))) { if (error == HA_ERR_FOUND_DUPP_KEY) { @@ -5449,7 +5851,16 @@ err: mrn_change_encoding(ctx, NULL); do { i--; + + if (i == table->s->primary_key) { + continue; + } + KEY *key_info = &table->key_info[i]; + if (!(key_info->flags & HA_NOSAME)) { + continue; + } + if (key_info->flags & HA_NOSAME) { grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]); } @@ -5497,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); @@ -5661,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)); @@ -5719,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; @@ -5914,6 +6325,13 @@ int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data) continue; } + grn_obj *index_column = grn_index_columns[i]; + if (!index_column) { + key_id[i] = GRN_ID_NIL; + del_key_id[i] = GRN_ID_NIL; + continue; + } + if ( KEY_N_KEY_PARTS(key_info) == 1 && !bitmap_is_set(table->write_set, @@ -5926,7 +6344,8 @@ int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data) } if ((error = storage_write_row_unique_index(new_data, key_info, - index_table, &key_id[i]))) + index_table, index_column, + &key_id[i]))) { if (error == HA_ERR_FOUND_DUPP_KEY) { @@ -6276,28 +6695,40 @@ int ha_mroonga::delete_row(const uchar *buf) DBUG_RETURN(error); } -uint ha_mroonga::wrapper_max_supported_key_parts() +uint ha_mroonga::wrapper_max_supported_key_parts() const { MRN_DBUG_ENTER_METHOD(); DBUG_RETURN(MAX_REF_PARTS); } -uint ha_mroonga::storage_max_supported_key_parts() +uint ha_mroonga::storage_max_supported_key_parts() const { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(1); + DBUG_RETURN(MAX_REF_PARTS); } -uint ha_mroonga::max_supported_key_parts() +uint ha_mroonga::max_supported_key_parts() const { MRN_DBUG_ENTER_METHOD(); + uint parts; - if (share->wrapper_mode) - { + if (!share && !analyzed_for_create && + ( + thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE || + thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX || + thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE + ) + ) { + create_share_for_create(); + } + if (analyzed_for_create && share_for_create.wrapper_mode) { + parts = wrapper_max_supported_key_parts(); + } else if (wrap_handler && share && share->wrapper_mode) { parts = wrapper_max_supported_key_parts(); } else { parts = storage_max_supported_key_parts(); } + DBUG_RETURN(parts); } @@ -6393,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")); @@ -6400,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++; } @@ -6413,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); @@ -6606,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>, " @@ -6624,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; @@ -6810,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, @@ -7422,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); @@ -7594,6 +8028,37 @@ bool ha_mroonga::generic_ft_init_ext_parse_pragma_w(struct st_mrn_ft_info *info, DBUG_RETURN(n_weights > 0); } +grn_expr_flags ha_mroonga::expr_flags_in_boolean_mode() +{ + MRN_DBUG_ENTER_METHOD(); + + 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; + } else { + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT) { + expression_flags |= GRN_EXPR_SYNTAX_SCRIPT; + } else { + expression_flags |= GRN_EXPR_SYNTAX_QUERY; + } + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN) { + expression_flags |= GRN_EXPR_ALLOW_COLUMN; + } + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE) { + expression_flags |= GRN_EXPR_ALLOW_UPDATE; + } + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT) { + expression_flags |= GRN_EXPR_ALLOW_LEADING_NOT; + } + } + + DBUG_RETURN(expression_flags); +} + grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode( struct st_mrn_ft_info *info, String *key, @@ -7674,12 +8139,10 @@ grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode( if (!weight_specified) { grn_expr_append_obj(info->ctx, match_columns, index_column, GRN_OP_PUSH, 1); } - grn_expr_flags expression_flags = - GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT; rc = grn_expr_parse(info->ctx, expression, keyword, keyword_length, match_columns, GRN_OP_MATCH, default_operator, - expression_flags); + expr_flags_in_boolean_mode()); if (rc) { char error_message[MRN_MESSAGE_BUFFER_SIZE]; snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, @@ -7859,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); @@ -8138,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>", @@ -8351,7 +8814,8 @@ int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index) const char *table_name = target_share->index_table[key_index]; snprintf(target_name, GRN_TABLE_MAX_KEY_SIZE, "%s.%s", table_name, key_info[key_index].name); - grn_obj *index_column = grn_ctx_get(ctx, target_name, strlen(target_name)); + target_name_length = strlen(target_name); + grn_obj *index_column = grn_ctx_get(ctx, target_name, target_name_length); if (index_column) { rc = grn_obj_remove(ctx, index_column); } @@ -8366,6 +8830,8 @@ int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index) target_name_length = grn_obj_name(ctx, index_table, target_name, GRN_TABLE_MAX_KEY_SIZE); rc = grn_obj_remove(ctx, index_table); + } else { + target_name_length = 0; } } @@ -8401,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, @@ -8409,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); @@ -8421,6 +8887,7 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info) { MRN_DBUG_ENTER_METHOD(); grn_obj *normalizer = NULL; + bool use_normalizer = true; #if MYSQL_VERSION_ID >= 50500 if (key_info->comment.length > 0) { mrn::ParametersParser parser(key_info->comment.str, @@ -8428,11 +8895,15 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info) parser.parse(); const char *normalizer_name = parser["normalizer"]; if (normalizer_name) { - normalizer = grn_ctx_get(ctx, normalizer_name, -1); + if (strcmp(normalizer_name, "none") == 0) { + use_normalizer = false; + } else { + normalizer = grn_ctx_get(ctx, normalizer_name, -1); + } } } #endif - if (!normalizer) { + if (use_normalizer && !normalizer) { Field *field = key_info->key_part[0].field; mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field); normalizer = field_normalizer.find_grn_normalizer(); @@ -8440,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(); @@ -8476,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; } @@ -8536,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; } @@ -8808,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; @@ -8831,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) { @@ -8839,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; } @@ -8875,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) @@ -8932,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) @@ -8946,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) { @@ -8956,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 && @@ -8983,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", @@ -9011,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); @@ -9031,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, @@ -9047,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; @@ -9059,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; @@ -9087,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); @@ -9150,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; } @@ -9190,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; } @@ -9217,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; } @@ -9277,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); @@ -9297,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); @@ -9317,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); @@ -9349,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); @@ -9370,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); @@ -9391,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); @@ -9412,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); @@ -9438,9 +9985,9 @@ int ha_mroonga::generic_store_bulk_blob(Field *field, grn_obj *buf) int error = 0; String buffer; Field_blob *blob = (Field_blob *)field; - const char *value = blob->val_str(0, &buffer)->ptr(); + String *value = blob->val_str(0, &buffer); grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0); - GRN_TEXT_SET(ctx, buf, value, blob->get_length()); + GRN_TEXT_SET(ctx, buf, value->ptr(), value->length()); DBUG_RETURN(error); } @@ -9448,11 +9995,12 @@ 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; - const char *wkb = geometry->val_str(0, &buffer)->ptr(); - int len = geometry->get_length(); + String *value = geometry->val_str(0, &buffer); + const char *wkb = value->ptr(); + int len = value->length(); error = mrn_set_geometry(ctx, buf, wkb, len); #endif DBUG_RETURN(error); @@ -9633,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; @@ -9685,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; @@ -9878,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; @@ -9994,7 +10542,7 @@ void ha_mroonga::storage_store_field(Field *field, } } -void ha_mroonga::storage_store_field_column(Field *field, +void ha_mroonga::storage_store_field_column(Field *field, bool is_primary_key, int nth_column, grn_id record_id) { MRN_DBUG_ENTER_METHOD(); @@ -10009,7 +10557,6 @@ void ha_mroonga::storage_store_field_column(Field *field, grn_obj_reinit(ctx, value, range_id, GRN_OBJ_VECTOR); grn_obj_get_value(ctx, column, record_id, value); - // TODO: Check whether reference type or not grn_obj unvectored_value; GRN_TEXT_INIT(&unvectored_value, 0); int n_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id); @@ -10042,7 +10589,15 @@ void ha_mroonga::storage_store_field_column(Field *field, } else { grn_obj_reinit(ctx, value, range_id, 0); grn_obj_get_value(ctx, column, record_id, value); - storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value)); + if (is_primary_key && GRN_BULK_VSIZE(value) == 0) { + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_length; + key_length = grn_table_get_key(ctx, grn_table, record_id, + &key, GRN_TABLE_MAX_KEY_SIZE); + storage_store_field(field, key, key_length); + } else { + storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value)); + } } DBUG_VOID_RETURN; @@ -10056,9 +10611,11 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id) my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]); Field *primary_key_field = NULL; - if (grn_table_is_referenced && table->s->primary_key != MAX_INDEXES) { + if (table->s->primary_key != MAX_INDEXES) { KEY *key_info = &(table->s->key_info[table->s->primary_key]); - primary_key_field = key_info->key_part[0].field; + if (KEY_N_KEY_PARTS(key_info) == 1) { + primary_key_field = key_info->key_part[0].field; + } } int i; @@ -10087,13 +10644,9 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id) } else if (primary_key_field && strcmp(primary_key_field->field_name, column_name) == 0) { // for primary key column - char key[GRN_TABLE_MAX_KEY_SIZE]; - int key_length; - key_length = grn_table_get_key(ctx, grn_table, record_id, - &key, GRN_TABLE_MAX_KEY_SIZE); - storage_store_field(field, key, key_length); + storage_store_field_column(field, true, i, record_id); } else { - storage_store_field_column(field, i ,record_id); + storage_store_field_column(field, false, i, record_id); } field->move_field_offset(-ptr_diff); } @@ -10278,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); @@ -10325,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 @@ -10360,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); @@ -10409,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); @@ -10435,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); @@ -10462,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); @@ -10489,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); @@ -10511,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); } @@ -10623,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; @@ -10632,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; @@ -10659,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); @@ -10746,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); } @@ -10770,12 +11336,12 @@ int ha_mroonga::wrapper_reset() MRN_SET_BASE_TABLE_KEY(this, table); #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER if (alter_key_info_buffer) { - my_free(alter_key_info_buffer, MYF(0)); + my_free(alter_key_info_buffer); alter_key_info_buffer = NULL; } #else if (wrap_alter_key_info) { - my_free(wrap_alter_key_info, MYF(0)); + my_free(wrap_alter_key_info); wrap_alter_key_info = NULL; } #endif @@ -11787,24 +12353,24 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info) if (slot_data) { slot_data->alter_create_info = create_info; if (slot_data->alter_connect_string) { - my_free(slot_data->alter_connect_string, MYF(0)); + my_free(slot_data->alter_connect_string); slot_data->alter_connect_string = NULL; } 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, MYF(0)); + my_free(slot_data->alter_comment); slot_data->alter_comment = NULL; } 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; @@ -12117,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(); @@ -12136,52 +12703,90 @@ 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) +{ + MRN_DBUG_ENTER_METHOD(); + + int error = 0; + if (share->index_table[i]) { + char index_column_name[GRN_TABLE_MAX_KEY_SIZE]; + snprintf(index_column_name, GRN_TABLE_MAX_KEY_SIZE - 1, + "%s.%s", share->index_table[i], key_info[i].name); + grn_obj *index_column = grn_ctx_get(ctx, + index_column_name, + strlen(index_column_name)); + if (index_column) { + grn_obj_remove(ctx, index_column); + } + } else { + mrn::PathMapper mapper(share->table_name); + mrn::IndexTableName index_table_name(mapper.table_name(), + key_info[i].name); + grn_obj *index_table = grn_ctx_get(ctx, + index_table_name.c_str(), + index_table_name.length()); + if (index_table) { + grn_obj_remove(ctx, index_table); + } + } + if (ctx->rc == GRN_SUCCESS) { + grn_index_tables[i] = NULL; + grn_index_columns[i] = NULL; + } else { + // TODO: Implement ctx->rc to error converter and use it. + error = ER_ERROR_ON_WRITE; + my_message(error, ctx->errbuf, MYF(0)); + } + + DBUG_RETURN(error); } int ha_mroonga::wrapper_disable_indexes(uint mode) @@ -12212,23 +12817,16 @@ int ha_mroonga::wrapper_disable_indexes(uint mode) } } KEY *key_info = table_share->key_info; - mrn::PathMapper mapper(share->table_name); for (i = 0; i < table_share->keys; i++) { if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) { continue; } - mrn::IndexTableName index_table_name(mapper.table_name(), - key_info[i].name); - grn_obj *index_table = grn_ctx_get(ctx, - index_table_name.c_str(), - index_table_name.length()); - if (index_table) { - grn_obj_remove(ctx, index_table); + int sub_error = generic_disable_index(i, key_info); + if (error != 0 && sub_error != 0) { + error = sub_error; } - grn_index_tables[i] = NULL; - grn_index_columns[i] = NULL; } } else { error = HA_ERR_WRONG_COMMAND; @@ -12239,6 +12837,7 @@ int ha_mroonga::wrapper_disable_indexes(uint mode) int ha_mroonga::storage_disable_indexes(uint mode) { + int error = 0; MRN_DBUG_ENTER_METHOD(); if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) { uint i; @@ -12252,7 +12851,6 @@ int ha_mroonga::storage_disable_indexes(uint mode) } } KEY *key_info = table_share->key_info; - mrn::PathMapper mapper(share->table_name); for (i = 0; i < table_share->keys; i++) { if (i == table->s->primary_key) { continue; @@ -12262,21 +12860,15 @@ int ha_mroonga::storage_disable_indexes(uint mode) continue; } - mrn::IndexTableName index_table_name(mapper.table_name(), - key_info[i].name); - grn_obj *index_table = grn_ctx_get(ctx, - index_table_name.c_str(), - index_table_name.length()); - if (index_table) { - grn_obj_remove(ctx, index_table); + int sub_error = generic_disable_index(i, key_info); + if (error != 0 && sub_error != 0) { + error = sub_error; } - grn_index_tables[i] = NULL; - grn_index_columns[i] = NULL; } } else { DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - DBUG_RETURN(0); + DBUG_RETURN(error); } int ha_mroonga::disable_indexes(uint mode) @@ -12305,7 +12897,7 @@ int ha_mroonga::wrapper_enable_indexes(uint mode) if (share->wrap_key_nr[i] < MAX_KEY) { continue; } - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { break; } } @@ -12334,7 +12926,7 @@ int ha_mroonga::wrapper_enable_indexes(uint mode) } index_tables[i] = NULL; index_columns[i] = NULL; - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { if ( (key_info[i].flags & HA_FULLTEXT) && (error = wrapper_create_index_fulltext(mapper.table_name(), @@ -12394,7 +12986,7 @@ int ha_mroonga::storage_enable_indexes(uint mode) if (i == table->s->primary_key) { continue; } - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { break; } } @@ -12420,7 +13012,7 @@ int ha_mroonga::storage_enable_indexes(uint mode) break; } index_tables[i] = NULL; - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { if ((error = storage_create_index(table, mapper.table_name(), grn_table, share, &key_info[i], index_tables, index_columns, i))) @@ -12434,6 +13026,8 @@ int ha_mroonga::storage_enable_indexes(uint mode) mrn_set_bitmap_by_key(table->read_set, &key_info[i]); have_multiple_column_index = true; } + grn_index_tables[i] = index_tables[i]; + grn_index_columns[i] = index_columns[i]; } else { index_columns[i] = NULL; } @@ -12485,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) @@ -12654,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; @@ -12672,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) @@ -12691,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) @@ -12784,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); @@ -12793,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); } @@ -12902,6 +13563,7 @@ int ha_mroonga::storage_add_index_multiple_columns(KEY *key_info, if ((error = storage_write_row_unique_index(table->record[0], current_key_info, index_tables[i], + index_columns[i], &key_id))) { if (error == HA_ERR_FOUND_DUPP_KEY) @@ -12958,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); @@ -12991,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, @@ -13086,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; @@ -13204,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), @@ -13308,7 +13970,7 @@ bool ha_mroonga::wrapper_inplace_alter_table( result = true; } mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(result); @@ -13353,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, @@ -13434,6 +14096,12 @@ bool ha_mroonga::storage_inplace_alter_table_index( ha_alter_info->key_count, index_tables, index_columns, false); + if (error == HA_ERR_FOUND_DUPP_UNIQUE) { + my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0), + table_share->table_name); + } else if (error) { + my_message(error, "failed to create multiple column index", MYF(0)); + } for (i = 0; i < n_columns; ++i) { Field *field = altered_table->field[i]; field->move_field_offset(-ptr_diff); @@ -13460,7 +14128,7 @@ bool ha_mroonga::storage_inplace_alter_table_index( have_error = true; } mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); @@ -13481,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, @@ -13532,12 +14200,10 @@ bool ha_mroonga::storage_inplace_alter_table_add_column( grn_obj_flags col_flags = GRN_OBJ_PERSISTENT; if (tmp_share->col_flags[i]) { - // TODO: parse flags - if (strcmp(tmp_share->col_flags[i], "COLUMN_VECTOR") == 0) { - col_flags |= GRN_OBJ_COLUMN_VECTOR; - } else { - col_flags |= GRN_OBJ_COLUMN_SCALAR; - } + col_flags |= mrn_parse_grn_column_create_flags(ha_thd(), + ctx, + tmp_share->col_flags[i], + tmp_share->col_flags_length[i]); } else { col_flags |= GRN_OBJ_COLUMN_SCALAR; } @@ -13570,7 +14236,7 @@ bool ha_mroonga::storage_inplace_alter_table_add_column( grn_obj_unlink(ctx, table_obj); mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); DBUG_RETURN(have_error); } @@ -13752,7 +14418,7 @@ bool ha_mroonga::wrapper_commit_inplace_alter_table( bool result; MRN_DBUG_ENTER_METHOD(); if (!alter_handler_flags) { - my_free(alter_key_info_buffer, MYF(0)); + my_free(alter_key_info_buffer); alter_key_info_buffer = NULL; DBUG_RETURN(false); } @@ -13765,7 +14431,7 @@ bool ha_mroonga::wrapper_commit_inplace_alter_table( MRN_SET_BASE_ALTER_KEY(this, ha_alter_info); MRN_SET_BASE_SHARE_KEY(share, table->s); MRN_SET_BASE_TABLE_KEY(this, table); - my_free(alter_key_info_buffer, MYF(0)); + my_free(alter_key_info_buffer); alter_key_info_buffer = NULL; DBUG_RETURN(result); } @@ -13875,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); @@ -13885,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), @@ -13990,7 +14656,7 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info, } #endif mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(error); @@ -14019,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, @@ -14104,7 +14770,7 @@ int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info, } #endif mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(error); @@ -14383,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); @@ -14531,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; @@ -14567,6 +15234,7 @@ int ha_mroonga::reset_auto_increment(ulonglong value) } DBUG_RETURN(res); } +#endif void ha_mroonga::set_pk_bitmap() { @@ -14919,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()); @@ -15277,7 +15945,7 @@ void ha_mroonga::wrapper_free_foreign_key_create_info(char* str) void ha_mroonga::storage_free_foreign_key_create_info(char* str) { MRN_DBUG_ENTER_METHOD(); - my_free(str, MYF(0)); + my_free(str); DBUG_VOID_RETURN; } #else |