diff options
author | Kentoku SHIBA <kentokushiba@gmail.com> | 2014-09-21 00:33:45 +0900 |
---|---|---|
committer | Kentoku SHIBA <kentokushiba@gmail.com> | 2014-09-21 00:33:45 +0900 |
commit | 0cc855cdc8cd0baa6ba50662632b299a3843ff13 (patch) | |
tree | eaf50856703412b5c1c43f8c0e5a6a5318601c17 /storage/mroonga/lib | |
parent | 989dd4d9ec09450ff7b25987b14ee9fdfd21ad4e (diff) | |
download | mariadb-git-0cc855cdc8cd0baa6ba50662632b299a3843ff13.tar.gz |
Update Mroonga to the latest version on 2014-09-21T00:33:44+0900
Diffstat (limited to 'storage/mroonga/lib')
36 files changed, 3395 insertions, 0 deletions
diff --git a/storage/mroonga/lib/Makefile.am b/storage/mroonga/lib/Makefile.am new file mode 100644 index 00000000000..300131db70a --- /dev/null +++ b/storage/mroonga/lib/Makefile.am @@ -0,0 +1,23 @@ +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir) \ + $(MYSQL_INCLUDES) \ + $(GROONGA_CFLAGS) \ + $(MYSQL_VERSION_CFLAGS) + +libmrn_need_mysql_la_CXXFLAGS = $(AM_CXXFLAGS) $(MYSQL_CFLAGS) + +if WITH_LIBMYSQLSERVICES_COMPAT +LIBMYSQLSERVICES_COMPAT = libmysqlservices.la +endif + +noinst_LTLIBRARIES = \ + $(LIBMYSQLSERVICES_COMPAT) \ + libmrn_no_mysql.la \ + libmrn_need_mysql.la + +include libmrn_no_mysql_sources.am +include libmrn_need_mysql_sources.am +if WITH_LIBMYSQLSERVICES_COMPAT +include libmysqlservices_compat_sources.am +endif diff --git a/storage/mroonga/lib/libmrn_need_mysql_sources.am b/storage/mroonga/lib/libmrn_need_mysql_sources.am new file mode 100644 index 00000000000..9dca2b6fb04 --- /dev/null +++ b/storage/mroonga/lib/libmrn_need_mysql_sources.am @@ -0,0 +1,25 @@ +libmrn_need_mysql_la_SOURCES = \ + mrn_index_table_name.cpp \ + mrn_index_table_name.hpp \ + mrn_index_column_name.cpp \ + mrn_index_column_name.hpp \ + mrn_debug_column_access.cpp \ + mrn_debug_column_access.hpp \ + mrn_auto_increment_value_lock.cpp \ + mrn_auto_increment_value_lock.hpp \ + mrn_external_lock.cpp \ + mrn_external_lock.hpp \ + mrn_multiple_column_key_codec.cpp \ + mrn_multiple_column_key_codec.hpp \ + mrn_field_normalizer.cpp \ + mrn_field_normalizer.hpp \ + mrn_encoding.cpp \ + mrn_encoding.hpp \ + mrn_parameters_parser.cpp \ + mrn_parameters_parser.hpp \ + mrn_lock.cpp \ + mrn_lock.hpp \ + mrn_condition_converter.cpp \ + mrn_condition_converter.hpp \ + mrn_time_converter.cpp \ + mrn_time_converter.hpp diff --git a/storage/mroonga/lib/libmrn_no_mysql_sources.am b/storage/mroonga/lib/libmrn_no_mysql_sources.am new file mode 100644 index 00000000000..89cfb277595 --- /dev/null +++ b/storage/mroonga/lib/libmrn_no_mysql_sources.am @@ -0,0 +1,8 @@ +libmrn_no_mysql_la_SOURCES = \ + mrn_match_escalation_threshold_scope.cpp \ + mrn_match_escalation_threshold_scope.hpp \ + mrn_path_mapper.cpp \ + mrn_path_mapper.hpp \ + mrn_windows.hpp \ + mrn_smart_grn_obj.cpp \ + mrn_smart_grn_obj.hpp diff --git a/storage/mroonga/lib/libmysqlservices_compat_sources.am b/storage/mroonga/lib/libmysqlservices_compat_sources.am new file mode 100644 index 00000000000..bb0712a4add --- /dev/null +++ b/storage/mroonga/lib/libmysqlservices_compat_sources.am @@ -0,0 +1,2 @@ +libmysqlservices_la_SOURCES = \ + mrn_mysqlservices.cpp diff --git a/storage/mroonga/lib/mrn_auto_increment_value_lock.cpp b/storage/mroonga/lib/mrn_auto_increment_value_lock.cpp new file mode 100644 index 00000000000..3bac5e31c6c --- /dev/null +++ b/storage/mroonga/lib/mrn_auto_increment_value_lock.cpp @@ -0,0 +1,42 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_auto_increment_value_lock.hpp" + +#if MYSQL_VERSION_ID >= 50500 +# define AUTO_INCREMENT_VALUE_MUTEX(table_share) (&(table_share->LOCK_ha_data)) +#else +# define AUTO_INCREMENT_VALUE_MUTEX(table_share) (&(table_share->mutex)) +#endif + +namespace mrn { + AutoIncrementValueLock::AutoIncrementValueLock(TABLE_SHARE *table_share) + : table_share_(table_share), + need_lock_(table_share_->tmp_table == NO_TMP_TABLE) { + if (need_lock_) { + mysql_mutex_lock(AUTO_INCREMENT_VALUE_MUTEX(table_share_)); + } + } + + AutoIncrementValueLock::~AutoIncrementValueLock() { + if (need_lock_) { + mysql_mutex_unlock(AUTO_INCREMENT_VALUE_MUTEX(table_share_)); + } + } +} diff --git a/storage/mroonga/lib/mrn_auto_increment_value_lock.hpp b/storage/mroonga/lib/mrn_auto_increment_value_lock.hpp new file mode 100644 index 00000000000..8aabe6a8a7f --- /dev/null +++ b/storage/mroonga/lib/mrn_auto_increment_value_lock.hpp @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_AUTO_INCREMENT_VALUE_LOCK_HPP_ +#define MRN_AUTO_INCREMENT_VALUE_LOCK_HPP_ + +#include <mrn_mysql.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + class AutoIncrementValueLock { + TABLE_SHARE *table_share_; + bool need_lock_; + public: + AutoIncrementValueLock(TABLE_SHARE *table_share); + ~AutoIncrementValueLock(); + }; +} + +#endif // MRN_AUTO_INCREMENT_VALUE_LOCK_HPP_ diff --git a/storage/mroonga/lib/mrn_condition_converter.cpp b/storage/mroonga/lib/mrn_condition_converter.cpp new file mode 100644 index 00000000000..1bfae1d4f8a --- /dev/null +++ b/storage/mroonga/lib/mrn_condition_converter.cpp @@ -0,0 +1,608 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2014 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mrn_condition_converter.hpp" +#include "mrn_time_converter.hpp" +#include "mrn_smart_grn_obj.hpp" + +// for debug +#define MRN_CLASS_NAME "mrn::ConditionConverter" + +#ifdef MRN_ITEM_HAVE_ITEM_NAME +# define MRN_ITEM_FIELD_GET_NAME(item) ((item)->item_name.ptr()) +# define MRN_ITEM_FIELD_GET_NAME_LENGTH(item) ((item)->item_name.length()) +#else +# define MRN_ITEM_FIELD_GET_NAME(item) ((item)->name) +# define MRN_ITEM_FIELD_GET_NAME_LENGTH(item) (strlen((item)->name)) +#endif + +namespace mrn { + ConditionConverter::ConditionConverter(grn_ctx *ctx, grn_obj *table, + bool is_storage_mode) + : ctx_(ctx), + table_(table), + is_storage_mode_(is_storage_mode) { + GRN_TEXT_INIT(&column_name_, 0); + GRN_VOID_INIT(&value_); + } + + ConditionConverter::~ConditionConverter() { + grn_obj_unlink(ctx_, &column_name_); + grn_obj_unlink(ctx_, &value_); + } + + bool ConditionConverter::is_convertable(const Item *item) { + MRN_DBUG_ENTER_METHOD(); + + if (!item) { + DBUG_RETURN(false); + } + + switch (item->type()) { + case Item::COND_ITEM: + { + const Item_cond *cond_item = reinterpret_cast<const Item_cond *>(item); + bool convertable = is_convertable(cond_item); + DBUG_RETURN(convertable); + } + break; + case Item::FUNC_ITEM: + { + const Item_func *func_item = reinterpret_cast<const Item_func *>(item); + bool convertable = is_convertable(func_item); + DBUG_RETURN(convertable); + } + break; + default: + DBUG_RETURN(false); + break; + } + + DBUG_RETURN(false); + } + + bool ConditionConverter::is_convertable(const Item_cond *cond_item) { + MRN_DBUG_ENTER_METHOD(); + + if (!is_storage_mode_) { + DBUG_RETURN(false); + } + + if (cond_item->functype() != Item_func::COND_AND_FUNC) { + DBUG_RETURN(false); + } + + List<Item> *argument_list = + const_cast<Item_cond *>(cond_item)->argument_list(); + List_iterator<Item> iterator(*argument_list); + const Item *sub_item; + while ((sub_item = iterator++)) { + if (!is_convertable(sub_item)) { + DBUG_RETURN(false); + } + } + + DBUG_RETURN(true); + } + + bool ConditionConverter::is_convertable(const Item_func *func_item) { + MRN_DBUG_ENTER_METHOD(); + + switch (func_item->functype()) { + case Item_func::EQ_FUNC: + case Item_func::LT_FUNC: + case Item_func::LE_FUNC: + case Item_func::GE_FUNC: + case Item_func::GT_FUNC: + if (!is_storage_mode_) { + DBUG_RETURN(false); + } + { + Item **arguments = func_item->arguments(); + Item *left_item = arguments[0]; + Item *right_item = arguments[1]; + if (left_item->type() != Item::FIELD_ITEM) { + DBUG_RETURN(false); + } + if (!right_item->basic_const_item()) { + DBUG_RETURN(false); + } + + bool convertable = + is_convertable_binary_operation(static_cast<Item_field *>(left_item), + right_item, + func_item->functype()); + DBUG_RETURN(convertable); + } + break; + case Item_func::FT_FUNC: + DBUG_RETURN(true); + break; + case Item_func::BETWEEN: + if (!is_storage_mode_) { + DBUG_RETURN(false); + } + { + Item **arguments = func_item->arguments(); + Item *target_item = arguments[0]; + Item *min_item = arguments[1]; + Item *max_item = arguments[2]; + if (target_item->type() != Item::FIELD_ITEM) { + DBUG_RETURN(false); + } + if (!min_item->basic_const_item()) { + DBUG_RETURN(false); + } + if (!max_item->basic_const_item()) { + DBUG_RETURN(false); + } + + bool convertable = + is_convertable_between(static_cast<Item_field *>(target_item), + min_item, + max_item); + DBUG_RETURN(convertable); + } + default: + DBUG_RETURN(false); + break; + } + + DBUG_RETURN(true); + } + + bool ConditionConverter::is_convertable_binary_operation( + const Item_field *field_item, + Item *value_item, + Item_func::Functype func_type) { + MRN_DBUG_ENTER_METHOD(); + + bool convertable = false; + + enum_field_types field_type = field_item->field_type(); + NormalizedType normalized_type = normalize_field_type(field_type); + switch (normalized_type) { + case STRING_TYPE: + if (value_item->type() == Item::STRING_ITEM && + func_type == Item_func::EQ_FUNC) { + convertable = have_index(field_item, GRN_OP_EQUAL); + } + break; + case INT_TYPE: + convertable = value_item->type() == Item::INT_ITEM; + break; + case TIME_TYPE: + if (is_valid_time_value(field_item, value_item)) { + convertable = have_index(field_item, func_type); + } + break; + case UNSUPPORTED_TYPE: + break; + } + + DBUG_RETURN(convertable); + } + + bool ConditionConverter::is_convertable_between(const Item_field *field_item, + Item *min_item, + Item *max_item) { + MRN_DBUG_ENTER_METHOD(); + + bool convertable = false; + + enum_field_types field_type = field_item->field_type(); + NormalizedType normalized_type = normalize_field_type(field_type); + switch (normalized_type) { + case STRING_TYPE: + if (min_item->type() == Item::STRING_ITEM && + max_item->type() == Item::STRING_ITEM) { + convertable = have_index(field_item, GRN_OP_LESS); + } + break; + case INT_TYPE: + if (min_item->type() == Item::INT_ITEM && + max_item->type() == Item::INT_ITEM) { + convertable = have_index(field_item, GRN_OP_LESS); + } + break; + case TIME_TYPE: + if (is_valid_time_value(field_item, min_item) && + is_valid_time_value(field_item, max_item)) { + convertable = have_index(field_item, GRN_OP_LESS); + } + break; + case UNSUPPORTED_TYPE: + break; + } + + DBUG_RETURN(convertable); + } + + bool ConditionConverter::is_valid_time_value(const Item_field *field_item, + Item *value_item) { + MRN_DBUG_ENTER_METHOD(); + + MYSQL_TIME mysql_time; + bool error = get_time_value(field_item, value_item, &mysql_time); + + DBUG_RETURN(!error); + } + + bool ConditionConverter::get_time_value(const Item_field *field_item, + Item *value_item, + MYSQL_TIME *mysql_time) { + MRN_DBUG_ENTER_METHOD(); + + bool error; + Item *real_value_item = value_item->real_item(); + switch (field_item->field_type()) { + case MYSQL_TYPE_TIME: + error = real_value_item->get_time(mysql_time); + break; + case MYSQL_TYPE_YEAR: + mysql_time->year = static_cast<int>(value_item->val_int()); + mysql_time->month = 1; + mysql_time->day = 1; + mysql_time->hour = 0; + mysql_time->hour = 0; + mysql_time->minute = 0; + mysql_time->second_part = 0; + mysql_time->neg = false; + mysql_time->time_type = MYSQL_TIMESTAMP_DATE; + error = false; + break; + default: + error = real_value_item->get_date(mysql_time, TIME_FUZZY_DATE); + break; + } + + DBUG_RETURN(error); + } + + ConditionConverter::NormalizedType + ConditionConverter::normalize_field_type(enum_field_types field_type) { + MRN_DBUG_ENTER_METHOD(); + + NormalizedType type = UNSUPPORTED_TYPE; + + switch (field_type) { + case MYSQL_TYPE_DECIMAL: + type = STRING_TYPE; + break; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + type = INT_TYPE; + break; + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + type = UNSUPPORTED_TYPE; + break; + case MYSQL_TYPE_NULL: + type = UNSUPPORTED_TYPE; + break; + case MYSQL_TYPE_TIMESTAMP: + type = TIME_TYPE; + break; + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_INT24: + type = INT_TYPE; + break; + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_NEWDATE: + type = TIME_TYPE; + break; + case MYSQL_TYPE_VARCHAR: + type = STRING_TYPE; + break; + case MYSQL_TYPE_BIT: + type = INT_TYPE; + break; +#ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 + case MYSQL_TYPE_TIMESTAMP2: + type = TIME_TYPE; + break; +#endif +#ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 + case MYSQL_TYPE_DATETIME2: + type = TIME_TYPE; + break; +#endif +#ifdef MRN_HAVE_MYSQL_TYPE_TIME2 + case MYSQL_TYPE_TIME2: + type = TIME_TYPE; + break; +#endif + case MYSQL_TYPE_NEWDECIMAL: + type = STRING_TYPE; + break; + case MYSQL_TYPE_ENUM: + type = INT_TYPE; + break; + case MYSQL_TYPE_SET: + type = INT_TYPE; + break; + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + type = STRING_TYPE; + break; + case MYSQL_TYPE_GEOMETRY: + type = UNSUPPORTED_TYPE; + break; + } + + DBUG_RETURN(type); + } + + bool ConditionConverter::have_index(const Item_field *field_item, + grn_operator _operator) { + MRN_DBUG_ENTER_METHOD(); + + grn_obj *column; + column = grn_obj_column(ctx_, table_, + MRN_ITEM_FIELD_GET_NAME(field_item), + MRN_ITEM_FIELD_GET_NAME_LENGTH(field_item)); + if (!column) { + DBUG_RETURN(false); + } + mrn::SmartGrnObj smart_column(ctx_, column); + + int n_indexes = grn_column_index(ctx_, column, _operator, NULL, 0, NULL); + bool convertable = (n_indexes > 0); + + DBUG_RETURN(convertable); + } + + bool ConditionConverter::have_index(const Item_field *field_item, + Item_func::Functype func_type) { + MRN_DBUG_ENTER_METHOD(); + + bool have = false; + switch (func_type) { + case Item_func::EQ_FUNC: + have = have_index(field_item, GRN_OP_EQUAL); + break; + case Item_func::LT_FUNC: + have = have_index(field_item, GRN_OP_LESS); + break; + case Item_func::LE_FUNC: + have = have_index(field_item, GRN_OP_LESS_EQUAL); + break; + case Item_func::GE_FUNC: + have = have_index(field_item, GRN_OP_GREATER_EQUAL); + break; + case Item_func::GT_FUNC: + have = have_index(field_item, GRN_OP_GREATER); + break; + default: + break; + } + + DBUG_RETURN(have); + } + + const Item_func *ConditionConverter::find_match_against(const Item *item) { + MRN_DBUG_ENTER_METHOD(); + + if (!item) { + DBUG_RETURN(NULL); + } + + switch (item->type()) { + case Item::COND_ITEM: + if (is_storage_mode_) { + Item_cond *cond_item = (Item_cond *)item; + if (cond_item->functype() == Item_func::COND_AND_FUNC) { + List_iterator<Item> iterator(*((cond_item)->argument_list())); + const Item *sub_item; + while ((sub_item = iterator++)) { + const Item_func *match_against = find_match_against(sub_item); + if (match_against) { + DBUG_RETURN(match_against); + } + } + } + } + break; + case Item::FUNC_ITEM: + { + const Item_func *func_item = (const Item_func *)item; + switch (func_item->functype()) { + case Item_func::FT_FUNC: + DBUG_RETURN(func_item); + break; + default: + break; + } + } + break; + default: + break; + } + + DBUG_RETURN(NULL); + } + + void ConditionConverter::convert(const Item *where, grn_obj *expression) { + MRN_DBUG_ENTER_METHOD(); + + if (!where || where->type() != Item::COND_ITEM) { + DBUG_VOID_RETURN; + } + + Item_cond *cond_item = (Item_cond *)where; + List_iterator<Item> iterator(*((cond_item)->argument_list())); + const Item *sub_item; + while ((sub_item = iterator++)) { + switch (sub_item->type()) { + case Item::FUNC_ITEM: + { + const Item_func *func_item = (const Item_func *)sub_item; + switch (func_item->functype()) { + case Item_func::EQ_FUNC: + convert_binary_operation(func_item, expression, GRN_OP_EQUAL); + break; + case Item_func::LT_FUNC: + convert_binary_operation(func_item, expression, GRN_OP_LESS); + break; + case Item_func::LE_FUNC: + convert_binary_operation(func_item, expression, GRN_OP_LESS_EQUAL); + break; + case Item_func::GE_FUNC: + convert_binary_operation(func_item, expression, + GRN_OP_GREATER_EQUAL); + break; + case Item_func::GT_FUNC: + convert_binary_operation(func_item, expression, GRN_OP_GREATER); + break; + case Item_func::BETWEEN: + convert_between(func_item, expression); + break; + default: + break; + } + } + break; + default: + break; + } + } + + DBUG_VOID_RETURN; + } + + void ConditionConverter::convert_binary_operation(const Item_func *func_item, + grn_obj *expression, + grn_operator _operator) { + Item **arguments = func_item->arguments(); + Item *left_item = arguments[0]; + Item *right_item = arguments[1]; + if (left_item->type() == Item::FIELD_ITEM) { + const Item_field *field_item = static_cast<const Item_field *>(left_item); + append_field_value(field_item, expression); + append_const_item(field_item, right_item, expression); + grn_expr_append_op(ctx_, expression, _operator, 2); + grn_expr_append_op(ctx_, expression, GRN_OP_AND, 2); + } + } + + void ConditionConverter::convert_between(const Item_func *func_item, + grn_obj *expression) { + MRN_DBUG_ENTER_METHOD(); + + Item **arguments = func_item->arguments(); + Item *target_item = arguments[0]; + Item *min_item = arguments[1]; + Item *max_item = arguments[2]; + + grn_obj *between_func = grn_ctx_get(ctx_, "between", strlen("between")); + grn_expr_append_obj(ctx_, expression, between_func, GRN_OP_PUSH, 1); + + const Item_field *field_item = static_cast<const Item_field *>(target_item); + append_field_value(field_item, expression); + + grn_obj include; + mrn::SmartGrnObj smart_include(ctx_, &include); + GRN_TEXT_INIT(&include, 0); + GRN_TEXT_PUTS(ctx_, &include, "include"); + append_const_item(field_item, min_item, expression); + grn_expr_append_const(ctx_, expression, &include, GRN_OP_PUSH, 1); + append_const_item(field_item, max_item, expression); + grn_expr_append_const(ctx_, expression, &include, GRN_OP_PUSH, 1); + + grn_expr_append_op(ctx_, expression, GRN_OP_CALL, 5); + + grn_expr_append_op(ctx_, expression, GRN_OP_AND, 2); + + DBUG_VOID_RETURN; + } + + void ConditionConverter::append_field_value(const Item_field *field_item, + grn_obj *expression) { + MRN_DBUG_ENTER_METHOD(); + + GRN_BULK_REWIND(&column_name_); + GRN_TEXT_PUT(ctx_, &column_name_, + MRN_ITEM_FIELD_GET_NAME(field_item), + MRN_ITEM_FIELD_GET_NAME_LENGTH(field_item)); + grn_expr_append_const(ctx_, expression, &column_name_, + GRN_OP_PUSH, 1); + grn_expr_append_op(ctx_, expression, GRN_OP_GET_VALUE, 1); + + DBUG_VOID_RETURN; + } + + void ConditionConverter::append_const_item(const Item_field *field_item, + Item *const_item, + grn_obj *expression) { + MRN_DBUG_ENTER_METHOD(); + + enum_field_types field_type = field_item->field_type(); + NormalizedType normalized_type = normalize_field_type(field_type); + + switch (normalized_type) { + case STRING_TYPE: + grn_obj_reinit(ctx_, &value_, GRN_DB_TEXT, 0); + { + String *string; + string = const_item->val_str(NULL); + GRN_TEXT_SET(ctx_, &value_, string->ptr(), string->length()); + } + break; + case INT_TYPE: + grn_obj_reinit(ctx_, &value_, GRN_DB_INT64, 0); + GRN_INT64_SET(ctx_, &value_, const_item->val_int()); + break; + case TIME_TYPE: + grn_obj_reinit(ctx_, &value_, GRN_DB_TIME, 0); + { + MYSQL_TIME mysql_time; + get_time_value(field_item, const_item, &mysql_time); + bool truncated = false; + TimeConverter time_converter; + long long int time = + time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); + GRN_TIME_SET(ctx_, &value_, time); + } + break; + case UNSUPPORTED_TYPE: + // Should not be occurred. + DBUG_PRINT("error", + ("mroonga: append_const_item: unsupported type: <%d> " + "This case should not be occurred.", + field_type)); + grn_obj_reinit(ctx_, &value_, GRN_DB_VOID, 0); + break; + } + grn_expr_append_const(ctx_, expression, &value_, GRN_OP_PUSH, 1); + + DBUG_VOID_RETURN; + } +} diff --git a/storage/mroonga/lib/mrn_condition_converter.hpp b/storage/mroonga/lib/mrn_condition_converter.hpp new file mode 100644 index 00000000000..3cf97c62bbe --- /dev/null +++ b/storage/mroonga/lib/mrn_condition_converter.hpp @@ -0,0 +1,82 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_CONDITION_CONVERTER_HPP_ +#define MRN_CONDITION_CONVERTER_HPP_ + +#include <groonga.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + class ConditionConverter { + public: + ConditionConverter(grn_ctx *ctx, grn_obj *table, bool is_storage_mode); + ~ConditionConverter(); + + bool is_convertable(const Item *item); + const Item_func *find_match_against(const Item *item); + // caller must check "where" can be convertable by + // is_convertable(). This method doesn't validate "where". + void convert(const Item *where, grn_obj *expression); + + private: + enum NormalizedType { + STRING_TYPE, + INT_TYPE, + TIME_TYPE, + UNSUPPORTED_TYPE, + }; + + grn_ctx *ctx_; + grn_obj *table_; + bool is_storage_mode_; + grn_obj column_name_; + grn_obj value_; + + bool is_convertable(const Item_cond *cond_item); + bool is_convertable(const Item_func *func_item); + bool is_convertable_binary_operation(const Item_field *field_item, + Item *value_item, + Item_func::Functype func_type); + bool is_convertable_between(const Item_field *field_item, + Item *min_item, + Item *max_item); + bool is_valid_time_value(const Item_field *field_item, + Item *value_item); + bool get_time_value(const Item_field *field_item, + Item *value_item, + MYSQL_TIME *mysql_time); + bool have_index(const Item_field *field_item, grn_operator _operator); + bool have_index(const Item_field *field_item, Item_func::Functype func_type); + + NormalizedType normalize_field_type(enum_field_types field_type); + + void convert_binary_operation(const Item_func *func_item, + grn_obj *expression, + grn_operator _operator); + void convert_between(const Item_func *func_item, grn_obj *expression); + void append_field_value(const Item_field *field_item, + grn_obj *expression); + void append_const_item(const Item_field *field_item, + Item *const_item, + grn_obj *expression); + }; +} + +#endif /* MRN_CONDITION_CONVERTER_HPP_ */ diff --git a/storage/mroonga/lib/mrn_debug_column_access.cpp b/storage/mroonga/lib/mrn_debug_column_access.cpp new file mode 100644 index 00000000000..ed7cacae90f --- /dev/null +++ b/storage/mroonga/lib/mrn_debug_column_access.cpp @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_debug_column_access.hpp" + +namespace mrn { + DebugColumnAccess::DebugColumnAccess(TABLE *table, MY_BITMAP *bitmap) + : table_(table), + bitmap_(bitmap) { +#ifndef DBUG_OFF + map_ = dbug_tmp_use_all_columns(table_, bitmap_); +#endif + } + + DebugColumnAccess::~DebugColumnAccess() { +#ifndef DBUG_OFF + dbug_tmp_restore_column_map(bitmap_, map_); +#endif + } +} diff --git a/storage/mroonga/lib/mrn_debug_column_access.hpp b/storage/mroonga/lib/mrn_debug_column_access.hpp new file mode 100644 index 00000000000..1548b4d8459 --- /dev/null +++ b/storage/mroonga/lib/mrn_debug_column_access.hpp @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_DEBUG_COLUMN_ACCESS_HPP_ +#define MRN_DEBUG_COLUMN_ACCESS_HPP_ + +#include <mrn_mysql.h> + +namespace mrn { + class DebugColumnAccess { + TABLE *table_; + MY_BITMAP *bitmap_; +#ifndef DBUG_OFF + my_bitmap_map *map_; +#endif + public: + DebugColumnAccess(TABLE *table, MY_BITMAP *bitmap); + ~DebugColumnAccess(); + }; +} + +#endif // MRN_DEBUG_COLUMN_ACCESS_HPP_ diff --git a/storage/mroonga/lib/mrn_encoding.cpp b/storage/mroonga/lib/mrn_encoding.cpp new file mode 100644 index 00000000000..a69a849c053 --- /dev/null +++ b/storage/mroonga/lib/mrn_encoding.cpp @@ -0,0 +1,222 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2011-2013 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <mrn_err.h> +#include "mrn_encoding.hpp" + +namespace mrn { + namespace encoding { + CHARSET_INFO *mrn_charset_utf8 = NULL; + CHARSET_INFO *mrn_charset_utf8mb4 = NULL; + CHARSET_INFO *mrn_charset_binary = NULL; + CHARSET_INFO *mrn_charset_ascii = NULL; + CHARSET_INFO *mrn_charset_latin1_1 = NULL; + CHARSET_INFO *mrn_charset_latin1_2 = NULL; + CHARSET_INFO *mrn_charset_cp932 = NULL; + CHARSET_INFO *mrn_charset_sjis = NULL; + CHARSET_INFO *mrn_charset_eucjpms = NULL; + CHARSET_INFO *mrn_charset_ujis = NULL; + CHARSET_INFO *mrn_charset_koi8r = NULL; + + void init(void) { + CHARSET_INFO **cs; + MRN_DBUG_ENTER_FUNCTION(); + for (cs = all_charsets; cs < all_charsets + MY_ALL_CHARSETS_SIZE; cs++) + { + if (!cs[0]) + continue; + if (!strcmp(cs[0]->csname, "utf8")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_utf8) + mrn_charset_utf8 = cs[0]; + else if (mrn_charset_utf8->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "utf8mb4")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_utf8mb4) + mrn_charset_utf8mb4 = cs[0]; + else if (mrn_charset_utf8mb4->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "binary")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_binary) + mrn_charset_binary = cs[0]; + else if (mrn_charset_binary->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "ascii")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_ascii) + mrn_charset_ascii = cs[0]; + else if (mrn_charset_ascii->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "latin1")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_latin1_1) + mrn_charset_latin1_1 = cs[0]; + else if (mrn_charset_latin1_1->cset != cs[0]->cset) + { + if (!mrn_charset_latin1_2) + mrn_charset_latin1_2 = cs[0]; + else if (mrn_charset_latin1_2->cset != cs[0]->cset) + DBUG_ASSERT(0); + } + continue; + } + if (!strcmp(cs[0]->csname, "cp932")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_cp932) + mrn_charset_cp932 = cs[0]; + else if (mrn_charset_cp932->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "sjis")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_sjis) + mrn_charset_sjis = cs[0]; + else if (mrn_charset_sjis->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "eucjpms")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_eucjpms) + mrn_charset_eucjpms = cs[0]; + else if (mrn_charset_eucjpms->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "ujis")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_ujis) + mrn_charset_ujis = cs[0]; + else if (mrn_charset_ujis->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + if (!strcmp(cs[0]->csname, "koi8r")) + { + DBUG_PRINT("info", ("mroonga: %s is %s [%p]", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + if (!mrn_charset_koi8r) + mrn_charset_koi8r = cs[0]; + else if (mrn_charset_koi8r->cset != cs[0]->cset) + DBUG_ASSERT(0); + continue; + } + DBUG_PRINT("info", ("mroonga: %s[%s][%p] is not supported", + cs[0]->name, cs[0]->csname, cs[0]->cset)); + } + DBUG_VOID_RETURN; + } + + bool set(grn_ctx *ctx, const CHARSET_INFO *charset) { + MRN_DBUG_ENTER_FUNCTION(); + if (!charset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_NONE); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_utf8->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_UTF8); + DBUG_RETURN(true); + } + if (mrn_charset_utf8mb4 && charset->cset == mrn_charset_utf8mb4->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_UTF8); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_cp932->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_SJIS); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_eucjpms->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_EUC_JP); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_latin1_1->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_LATIN1); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_latin1_2->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_LATIN1); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_koi8r->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_KOI8R); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_binary->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_NONE); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_ascii->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_UTF8); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_sjis->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_SJIS); + DBUG_RETURN(true); + } + if (charset->cset == mrn_charset_ujis->cset) + { + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_EUC_JP); + DBUG_RETURN(true); + } + GRN_CTX_SET_ENCODING(ctx, GRN_ENC_NONE); + DBUG_RETURN(false); + } + } +} diff --git a/storage/mroonga/lib/mrn_encoding.hpp b/storage/mroonga/lib/mrn_encoding.hpp new file mode 100644 index 00000000000..b4f21e1a274 --- /dev/null +++ b/storage/mroonga/lib/mrn_encoding.hpp @@ -0,0 +1,35 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_ENCODING_HPP_ +#define MRN_ENCODING_HPP_ + +#include <groonga.h> + +#include <mrn_mysql.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + namespace encoding { + void init(void); + bool set(grn_ctx *ctx, const CHARSET_INFO *charset); + } +} + +#endif // MRN_ENCODING_HPP_ diff --git a/storage/mroonga/lib/mrn_external_lock.cpp b/storage/mroonga/lib/mrn_external_lock.cpp new file mode 100644 index 00000000000..b266b6594ca --- /dev/null +++ b/storage/mroonga/lib/mrn_external_lock.cpp @@ -0,0 +1,43 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_external_lock.hpp" + +namespace mrn { + ExternalLock::ExternalLock(THD *thd, handler *handler, int lock_type) + : thd_(thd), + handler_(handler), + lock_type_(lock_type) { + if (lock_type_ != F_UNLCK) { + error_ = handler_->ha_external_lock(thd_, lock_type); + } else { + error_ = 0; + } + } + + ExternalLock::~ExternalLock() { + if (lock_type_ != F_UNLCK) { + handler_->ha_external_lock(thd_, F_UNLCK); + } + } + + int ExternalLock::error() { + return error_; + } +} diff --git a/storage/mroonga/lib/mrn_external_lock.hpp b/storage/mroonga/lib/mrn_external_lock.hpp new file mode 100644 index 00000000000..f78b436f6e8 --- /dev/null +++ b/storage/mroonga/lib/mrn_external_lock.hpp @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_EXTERNAL_LOCK_HPP_ +#define MRN_EXTERNAL_LOCK_HPP_ + +#include <mrn_mysql.h> + +namespace mrn { + class ExternalLock { + THD *thd_; + handler *handler_; + int lock_type_; + int error_; + public: + ExternalLock(THD *thd, handler *handler, int lock_type); + ~ExternalLock(); + int error(); + }; +} + +#endif // MRN_EXTERNAL_LOCK_HPP_ diff --git a/storage/mroonga/lib/mrn_field_normalizer.cpp b/storage/mroonga/lib/mrn_field_normalizer.cpp new file mode 100644 index 00000000000..bb91b3ab98d --- /dev/null +++ b/storage/mroonga/lib/mrn_field_normalizer.cpp @@ -0,0 +1,142 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_field_normalizer.hpp" +#include "mrn_encoding.hpp" + +// for debug +#define MRN_CLASS_NAME "mrn::FieldNormalizer" + +namespace mrn { + FieldNormalizer::FieldNormalizer(grn_ctx *ctx, THD *thread, Field *field) + : ctx_(ctx), + thread_(thread), + field_(field) { + } + + FieldNormalizer::~FieldNormalizer() { + } + + bool FieldNormalizer::should_normalize() { + MRN_DBUG_ENTER_METHOD(); + + DBUG_PRINT("info", + ("mroonga: result_type = %u", field_->result_type())); + DBUG_PRINT("info", + ("mroonga: charset->name = %s", field_->charset()->name)); + DBUG_PRINT("info", + ("mroonga: charset->csname = %s", field_->charset()->csname)); + DBUG_PRINT("info", + ("mroonga: charset->state = %u", field_->charset()->state)); + bool need_normalize_p; + if (field_->charset()->state & (MY_CS_BINSORT | MY_CS_CSSORT)) { + need_normalize_p = false; + DBUG_PRINT("info", + ("mroonga: should_normalize: false: sort is required")); + } else { + if (is_text_type()) { + need_normalize_p = true; + DBUG_PRINT("info", ("mroonga: should_normalize: true: text type")); + } else { + need_normalize_p = false; + DBUG_PRINT("info", ("mroonga: should_normalize: false: no text type")); + } + } + + DBUG_RETURN(need_normalize_p); + } + + bool FieldNormalizer::is_text_type() { + MRN_DBUG_ENTER_METHOD(); + bool text_type_p; + switch (field_->type()) { + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VAR_STRING: + text_type_p = true; + break; + case MYSQL_TYPE_STRING: + switch (field_->real_type()) { + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + text_type_p = false; + break; + default: + text_type_p = true; + break; + } + break; + default: + text_type_p = false; + break; + } + DBUG_RETURN(text_type_p); + } + + grn_obj *FieldNormalizer::normalize(const char *string, + unsigned int string_length) { + MRN_DBUG_ENTER_METHOD(); + grn_obj *normalizer = find_grn_normalizer(); + int flags = 0; + grn_encoding original_encoding = GRN_CTX_GET_ENCODING(ctx_); + encoding::set(ctx_, field_->charset()); + grn_obj *grn_string = grn_string_open(ctx_, string, string_length, + normalizer, flags); + GRN_CTX_SET_ENCODING(ctx_, original_encoding); + DBUG_RETURN(grn_string); + } + + grn_obj *FieldNormalizer::find_grn_normalizer() { + MRN_DBUG_ENTER_METHOD(); + + const CHARSET_INFO *charset_info = field_->charset(); + const char *normalizer_name = NULL; + const char *default_normalizer_name = "NormalizerAuto"; + if ((strcmp(charset_info->name, "utf8_general_ci") == 0) || + (strcmp(charset_info->name, "utf8mb4_general_ci") == 0)) { + normalizer_name = "NormalizerMySQLGeneralCI"; + } else if ((strcmp(charset_info->name, "utf8_unicode_ci") == 0) || + (strcmp(charset_info->name, "utf8mb4_unicode_ci") == 0)) { + normalizer_name = "NormalizerMySQLUnicodeCI"; + } + + grn_obj *normalizer = NULL; + if (normalizer_name) { + normalizer = grn_ctx_get(ctx_, normalizer_name, -1); + if (!normalizer) { + char error_message[MRN_MESSAGE_BUFFER_SIZE]; + snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, + "%s normalizer isn't found for %s. " + "Install groonga-normalizer-mysql normalizer. " + "%s is used as fallback.", + normalizer_name, + charset_info->name, + default_normalizer_name); + push_warning(thread_, Sql_condition::WARN_LEVEL_WARN, + HA_ERR_UNSUPPORTED, error_message); + } + } + + if (!normalizer) { + normalizer = grn_ctx_get(ctx_, default_normalizer_name, -1); + } + + DBUG_RETURN(normalizer); + } +} diff --git a/storage/mroonga/lib/mrn_field_normalizer.hpp b/storage/mroonga/lib/mrn_field_normalizer.hpp new file mode 100644 index 00000000000..5fd8974ce5b --- /dev/null +++ b/storage/mroonga/lib/mrn_field_normalizer.hpp @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_FIELD_NORMALIZER_HPP_ +#define MRN_FIELD_NORMALIZER_HPP_ + +#include <groonga.h> + +#include <mrn_mysql.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + class FieldNormalizer { + public: + FieldNormalizer(grn_ctx *ctx, THD *thread, Field *field); + ~FieldNormalizer(); + + bool should_normalize(); + grn_obj *normalize(const char *string, unsigned int string_length); + grn_obj *find_grn_normalizer(); + + private: + grn_ctx *ctx_; + THD *thread_; + Field *field_; + + bool is_text_type(); + }; +} + +#endif // MRN_FIELD_NORMALIZER_HPP_ diff --git a/storage/mroonga/lib/mrn_index_column_name.cpp b/storage/mroonga/lib/mrn_index_column_name.cpp new file mode 100644 index 00000000000..14e83ec8e34 --- /dev/null +++ b/storage/mroonga/lib/mrn_index_column_name.cpp @@ -0,0 +1,96 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2013 Kentoku SHIBA + Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <mrn_mysql.h> + +#include "mrn_index_column_name.hpp" + +#define MRN_MIN_INDEX_COLUMN_NAME_LENGTH 65 + +// for debug +#define MRN_CLASS_NAME "mrn::IndexColumnName" + +namespace mrn { + IndexColumnName::IndexColumnName(const char *table_name, + const char *mysql_column_name) + : table_name_(table_name), + mysql_column_name_(mysql_column_name) { + uchar encoded_mysql_column_name_multibyte[MRN_MAX_KEY_SIZE]; + const uchar *mysql_column_name_multibyte = + reinterpret_cast<const uchar *>(mysql_column_name_); + encode(encoded_mysql_column_name_multibyte, + encoded_mysql_column_name_multibyte + MRN_MAX_KEY_SIZE, + mysql_column_name_multibyte, + mysql_column_name_multibyte + strlen(mysql_column_name_)); + snprintf(name_, MRN_MAX_KEY_SIZE, + "%s-%s", table_name_, encoded_mysql_column_name_multibyte); + length_ = strlen(name_); + if (length_ < MRN_MIN_INDEX_COLUMN_NAME_LENGTH) { + memset(name_ + length_, '-', MRN_MIN_INDEX_COLUMN_NAME_LENGTH - length_); + length_ = MRN_MIN_INDEX_COLUMN_NAME_LENGTH; + name_[length_] = '\0'; + } + } + + const char *IndexColumnName::c_str() { + return name_; + } + + size_t IndexColumnName::length() { + return length_; + } + + uint IndexColumnName::encode(uchar *encoded_start, + uchar *encoded_end, + const uchar *mysql_string_start, + const uchar *mysql_string_end) { + MRN_DBUG_ENTER_METHOD(); + my_charset_conv_mb_wc mb_wc = system_charset_info->cset->mb_wc; + my_charset_conv_wc_mb wc_mb = my_charset_filename.cset->wc_mb; + DBUG_PRINT("info", ("mroonga: in=%s", mysql_string_start)); + encoded_end--; + uchar *encoded = encoded_start; + const uchar *mysql_string = mysql_string_start; + while (mysql_string < mysql_string_end && encoded < encoded_end) { + my_wc_t wc; + int mb_wc_converted_length; + int wc_mb_converted_length; + mb_wc_converted_length = + (*mb_wc)(NULL, &wc, mysql_string, mysql_string_end); + if (mb_wc_converted_length > 0) { + wc_mb_converted_length = (*wc_mb)(NULL, wc, encoded, encoded_end); + if (wc_mb_converted_length <= 0) { + break; + } + } else if (mb_wc_converted_length == MY_CS_ILSEQ) { + *encoded = *mysql_string; + mb_wc_converted_length = 1; + wc_mb_converted_length = 1; + } else { + break; + } + mysql_string += mb_wc_converted_length; + encoded += wc_mb_converted_length; + } + *encoded = '\0'; + DBUG_PRINT("info", ("mroonga: out=%s", encoded_start)); + DBUG_RETURN(encoded - encoded_start); + } +} diff --git a/storage/mroonga/lib/mrn_index_column_name.hpp b/storage/mroonga/lib/mrn_index_column_name.hpp new file mode 100644 index 00000000000..5cd24623abd --- /dev/null +++ b/storage/mroonga/lib/mrn_index_column_name.hpp @@ -0,0 +1,43 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2013 Kentoku SHIBA + Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_INDEX_COLUMN_NAME_HPP_ +#define MRN_INDEX_COLUMN_NAME_HPP_ + +#include <mrn_constants.hpp> + +namespace mrn { + class IndexColumnName { + public: + IndexColumnName(const char *table_name, const char *mysql_column_name); + const char *c_str(); + size_t length(); + private: + const char *table_name_; + const char *mysql_column_name_; + char name_[MRN_MAX_KEY_SIZE]; + size_t length_; + + uint encode(uchar *encoded_start, uchar *encoded_end, + const uchar *mysql_string_start, const uchar *mysql_string_end); + }; +} + +#endif /* MRN_INDEX_COLUMN_NAME_HPP_ */ diff --git a/storage/mroonga/lib/mrn_index_table_name.cpp b/storage/mroonga/lib/mrn_index_table_name.cpp new file mode 100644 index 00000000000..93f4ff8f8fd --- /dev/null +++ b/storage/mroonga/lib/mrn_index_table_name.cpp @@ -0,0 +1,89 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011 Kentoku SHIBA + Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <mrn_mysql.h> + +#include "mrn_index_table_name.hpp" + +// for debug +#define MRN_CLASS_NAME "mrn::IndexTableName" + +namespace mrn { + IndexTableName::IndexTableName(const char *table_name, + const char *mysql_index_name) + : table_name_(table_name), + mysql_index_name_(mysql_index_name) { + uchar encoded_mysql_index_name_multibyte[MRN_MAX_KEY_SIZE]; + const uchar *mysql_index_name_multibyte = + reinterpret_cast<const uchar *>(mysql_index_name_); + encode(encoded_mysql_index_name_multibyte, + encoded_mysql_index_name_multibyte + MRN_MAX_KEY_SIZE, + mysql_index_name_multibyte, + mysql_index_name_multibyte + strlen(mysql_index_name_)); + snprintf(name_, MRN_MAX_KEY_SIZE, + "%s-%s", table_name_, encoded_mysql_index_name_multibyte); + length_ = strlen(name_); + } + + const char *IndexTableName::c_str() { + return name_; + } + + size_t IndexTableName::length() { + return length_; + } + + uint IndexTableName::encode(uchar *encoded_start, + uchar *encoded_end, + const uchar *mysql_string_start, + const uchar *mysql_string_end) { + MRN_DBUG_ENTER_METHOD(); + my_charset_conv_mb_wc mb_wc = system_charset_info->cset->mb_wc; + my_charset_conv_wc_mb wc_mb = my_charset_filename.cset->wc_mb; + DBUG_PRINT("info", ("mroonga: in=%s", mysql_string_start)); + encoded_end--; + uchar *encoded = encoded_start; + const uchar *mysql_string = mysql_string_start; + while (mysql_string < mysql_string_end && encoded < encoded_end) { + my_wc_t wc; + int mb_wc_converted_length; + int wc_mb_converted_length; + mb_wc_converted_length = + (*mb_wc)(NULL, &wc, mysql_string, mysql_string_end); + if (mb_wc_converted_length > 0) { + wc_mb_converted_length = (*wc_mb)(NULL, wc, encoded, encoded_end); + if (wc_mb_converted_length <= 0) { + break; + } + } else if (mb_wc_converted_length == MY_CS_ILSEQ) { + *encoded = *mysql_string; + mb_wc_converted_length = 1; + wc_mb_converted_length = 1; + } else { + break; + } + mysql_string += mb_wc_converted_length; + encoded += wc_mb_converted_length; + } + *encoded = '\0'; + DBUG_PRINT("info", ("mroonga: out=%s", encoded_start)); + DBUG_RETURN(encoded - encoded_start); + } +} diff --git a/storage/mroonga/lib/mrn_index_table_name.hpp b/storage/mroonga/lib/mrn_index_table_name.hpp new file mode 100644 index 00000000000..4ac4bfe087b --- /dev/null +++ b/storage/mroonga/lib/mrn_index_table_name.hpp @@ -0,0 +1,43 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011 Kentoku SHIBA + Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_INDEX_TABLE_NAME_HPP_ +#define MRN_INDEX_TABLE_NAME_HPP_ + +#include <mrn_constants.hpp> + +namespace mrn { + class IndexTableName { + public: + IndexTableName(const char *table_name, const char *mysql_index_name); + const char *c_str(); + size_t length(); + private: + const char *table_name_; + const char *mysql_index_name_; + char name_[MRN_MAX_KEY_SIZE]; + size_t length_; + + uint encode(uchar *encoded_start, uchar *encoded_end, + const uchar *mysql_string_start, const uchar *mysql_string_end); + }; +} + +#endif /* MRN_INDEX_TABLE_NAME_HPP_ */ diff --git a/storage/mroonga/lib/mrn_lock.cpp b/storage/mroonga/lib/mrn_lock.cpp new file mode 100644 index 00000000000..94f8a4774af --- /dev/null +++ b/storage/mroonga/lib/mrn_lock.cpp @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_lock.hpp" + +namespace mrn { + Lock::Lock(pthread_mutex_t *mutex) + : mutex_(mutex) { + pthread_mutex_lock(mutex_); + } + + Lock::~Lock() { + pthread_mutex_unlock(mutex_); + } +} diff --git a/storage/mroonga/lib/mrn_lock.hpp b/storage/mroonga/lib/mrn_lock.hpp new file mode 100644 index 00000000000..31dd7b3e53b --- /dev/null +++ b/storage/mroonga/lib/mrn_lock.hpp @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_LOCK_HPP_ +#define MRN_LOCK_HPP_ + +#include <mrn_mysql.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + class Lock { + public: + Lock(pthread_mutex_t *mutex); + ~Lock(); + private: + pthread_mutex_t *mutex_; + }; +} + +#endif /* MRN_LOCK_HPP_ */ diff --git a/storage/mroonga/lib/mrn_match_escalation_threshold_scope.cpp b/storage/mroonga/lib/mrn_match_escalation_threshold_scope.cpp new file mode 100644 index 00000000000..c944b4a4bc0 --- /dev/null +++ b/storage/mroonga/lib/mrn_match_escalation_threshold_scope.cpp @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_match_escalation_threshold_scope.hpp" + +namespace mrn { + MatchEscalationThresholdScope::MatchEscalationThresholdScope( + grn_ctx *ctx, long long int threshold) + : ctx_(ctx), + original_threshold_(grn_ctx_get_match_escalation_threshold(ctx_)) { + grn_ctx_set_match_escalation_threshold(ctx_, threshold); + } + + MatchEscalationThresholdScope::~MatchEscalationThresholdScope() { + grn_ctx_set_match_escalation_threshold(ctx_, original_threshold_); + } +} diff --git a/storage/mroonga/lib/mrn_match_escalation_threshold_scope.hpp b/storage/mroonga/lib/mrn_match_escalation_threshold_scope.hpp new file mode 100644 index 00000000000..352e6589f0d --- /dev/null +++ b/storage/mroonga/lib/mrn_match_escalation_threshold_scope.hpp @@ -0,0 +1,35 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_MATCH_ESCALATION_THRESHOLD_SCOPE_HPP_ +#define MRN_MATCH_ESCALATION_THRESHOLD_SCOPE_HPP_ + +#include <groonga.h> + +namespace mrn { + class MatchEscalationThresholdScope { + grn_ctx *ctx_; + long long int original_threshold_; + public: + MatchEscalationThresholdScope(grn_ctx *ctx, long long int threshold); + ~MatchEscalationThresholdScope(); + }; +} + +#endif // MRN_MATCH_ESCALATION_THRESHOLD_SCOPE_HPP_ diff --git a/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp b/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp new file mode 100644 index 00000000000..5ce736a49b8 --- /dev/null +++ b/storage/mroonga/lib/mrn_multiple_column_key_codec.cpp @@ -0,0 +1,548 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012-2014 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2013 Kentoku SHIBA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <mrn_mysql.h> + +#include "mrn_multiple_column_key_codec.hpp" +#include "mrn_field_normalizer.hpp" +#include "mrn_smart_grn_obj.hpp" + +// for debug +#define MRN_CLASS_NAME "mrn::MultipleColumnKeyCodec" + +#ifdef WORDS_BIGENDIAN +#define mrn_byte_order_host_to_network(buf, key, size) \ +{ \ + uint32 size_ = (uint32)(size); \ + uint8 *buf_ = (uint8 *)(buf); \ + uint8 *key_ = (uint8 *)(key); \ + while (size_--) { *buf_++ = *key_++; } \ +} +#else /* WORDS_BIGENDIAN */ +#define mrn_byte_order_host_to_network(buf, key, size) \ +{ \ + uint32 size_ = (uint32)(size); \ + uint8 *buf_ = (uint8 *)(buf); \ + uint8 *key_ = (uint8 *)(key) + size_; \ + while (size_--) { *buf_++ = *(--key_); } \ +} +#endif /* WORDS_BIGENDIAN */ + +namespace mrn { + MultipleColumnKeyCodec::MultipleColumnKeyCodec(grn_ctx *ctx, + THD *thread, + KEY *key_info) + : ctx_(ctx), + thread_(thread), + key_info_(key_info) { + } + + MultipleColumnKeyCodec::~MultipleColumnKeyCodec() { + } + + int MultipleColumnKeyCodec::encode(const uchar *mysql_key, + uint mysql_key_length, + uchar *grn_key, + uint *grn_key_length) { + MRN_DBUG_ENTER_METHOD(); + int error = 0; + const uchar *current_mysql_key = mysql_key; + const uchar *mysql_key_end = mysql_key + mysql_key_length; + uchar *current_grn_key = grn_key; + + int n_key_parts = KEY_N_KEY_PARTS(key_info_); + DBUG_PRINT("info", ("mroonga: n_key_parts=%d", n_key_parts)); + *grn_key_length = 0; + for (int i = 0; i < n_key_parts && current_mysql_key < mysql_key_end; i++) { + KEY_PART_INFO *key_part = &(key_info_->key_part[i]); + Field *field = key_part->field; + DBUG_PRINT("info", ("mroonga: key_part->length=%u", key_part->length)); + + if (field->null_bit) { + DBUG_PRINT("info", ("mroonga: field has null bit")); + *current_grn_key = 0; + current_mysql_key += 1; + current_grn_key += 1; + (*grn_key_length)++; + } + + DataType data_type = TYPE_UNKNOWN; + uint data_size = 0; + get_key_info(key_part, &data_type, &data_size); + + switch (data_type) { + case TYPE_UNKNOWN: + // TODO: This will not be happen. This is just for + // suppressing warnings by gcc -O2. :< + error = HA_ERR_UNSUPPORTED; + break; + case TYPE_LONG_LONG_NUMBER: + { + long long int long_long_value = 0; + switch (data_size) { + case 3: + long_long_value = (long long int)sint3korr(current_mysql_key); + break; + case 8: + long_long_value = (long long int)sint8korr(current_mysql_key); + break; + } + mrn_byte_order_host_to_network(current_grn_key, &long_long_value, + data_size); + *((uint8 *)(current_grn_key)) ^= 0x80; + } + break; + case TYPE_NUMBER: + mrn_byte_order_host_to_network(current_grn_key, current_mysql_key, data_size); + { + Field_num *number_field = (Field_num *)field; + if (!number_field->unsigned_flag) { + *((uint8 *)(current_grn_key)) ^= 0x80; + } + } + break; + case TYPE_FLOAT: + { + float value; + float4get(value, current_mysql_key); + encode_float(value, data_size, current_grn_key); + } + break; + case TYPE_DOUBLE: + { + double value; + float8get(value, current_mysql_key); + encode_double(value, data_size, current_grn_key); + } + break; + case TYPE_BYTE_SEQUENCE: + memcpy(current_grn_key, current_mysql_key, data_size); + break; + case TYPE_BYTE_REVERSE: + encode_reverse(current_mysql_key, data_size, current_grn_key); + break; + case TYPE_BYTE_BLOB: + encode_blob(field, current_mysql_key, current_grn_key, &data_size); + break; + } + + if (error) { + break; + } + + current_mysql_key += data_size; + current_grn_key += data_size; + *grn_key_length += data_size; + } + + DBUG_RETURN(error); + } + + int MultipleColumnKeyCodec::decode(const uchar *grn_key, + uint grn_key_length, + uchar *mysql_key, + uint *mysql_key_length) { + MRN_DBUG_ENTER_METHOD(); + int error = 0; + const uchar *current_grn_key = grn_key; + const uchar *grn_key_end = grn_key + grn_key_length; + uchar *current_mysql_key = mysql_key; + + int n_key_parts = KEY_N_KEY_PARTS(key_info_); + DBUG_PRINT("info", ("mroonga: n_key_parts=%d", n_key_parts)); + *mysql_key_length = 0; + for (int i = 0; i < n_key_parts && current_grn_key < grn_key_end; i++) { + KEY_PART_INFO *key_part = &(key_info_->key_part[i]); + Field *field = key_part->field; + DBUG_PRINT("info", ("mroonga: key_part->length=%u", key_part->length)); + + if (field->null_bit) { + DBUG_PRINT("info", ("mroonga: field has null bit")); + *current_mysql_key = 0; + current_grn_key += 1; + current_mysql_key += 1; + (*mysql_key_length)++; + } + + DataType data_type = TYPE_UNKNOWN; + uint data_size = 0; + get_key_info(key_part, &data_type, &data_size); + + switch (data_type) { + case TYPE_UNKNOWN: + // TODO: This will not be happen. This is just for + // suppressing warnings by gcc -O2. :< + error = HA_ERR_UNSUPPORTED; + break; + case TYPE_LONG_LONG_NUMBER: + { + long long int long_long_value = 0; + switch (data_size) { + case 3: + long_long_value = (long long int)sint3korr(current_grn_key); + break; + case 8: + long_long_value = (long long int)sint8korr(current_grn_key); + break; + } + *((uint8 *)(&long_long_value)) ^= 0x80; + mrn_byte_order_host_to_network(current_mysql_key, &long_long_value, + data_size); + } + break; + case TYPE_NUMBER: + { + uchar buffer[8]; + memcpy(buffer, current_grn_key, data_size); + Field_num *number_field = (Field_num *)field; + if (!number_field->unsigned_flag) { + buffer[0] ^= 0x80; + } + mrn_byte_order_host_to_network(current_mysql_key, buffer, + data_size); + } + break; + case TYPE_FLOAT: + decode_float(current_grn_key, current_mysql_key, data_size); + break; + case TYPE_DOUBLE: + decode_double(current_grn_key, current_mysql_key, data_size); + break; + case TYPE_BYTE_SEQUENCE: + memcpy(current_mysql_key, current_grn_key, data_size); + break; + case TYPE_BYTE_REVERSE: + decode_reverse(current_grn_key, current_mysql_key, data_size); + break; + case TYPE_BYTE_BLOB: + memcpy(current_mysql_key, + current_grn_key + data_size, + HA_KEY_BLOB_LENGTH); + memcpy(current_mysql_key + HA_KEY_BLOB_LENGTH, + current_grn_key, + data_size); + data_size += HA_KEY_BLOB_LENGTH; + break; + } + + if (error) { + break; + } + + current_grn_key += data_size; + current_mysql_key += data_size; + *mysql_key_length += data_size; + } + + DBUG_RETURN(error); + } + + uint MultipleColumnKeyCodec::size() { + MRN_DBUG_ENTER_METHOD(); + + int n_key_parts = KEY_N_KEY_PARTS(key_info_); + DBUG_PRINT("info", ("mroonga: n_key_parts=%d", n_key_parts)); + + uint total_size = 0; + for (int i = 0; i < n_key_parts; ++i) { + KEY_PART_INFO *key_part = &(key_info_->key_part[i]); + Field *field = key_part->field; + DBUG_PRINT("info", ("mroonga: key_part->length=%u", key_part->length)); + + if (field->null_bit) { + DBUG_PRINT("info", ("mroonga: field has null bit")); + ++total_size; + } + + DataType data_type = TYPE_UNKNOWN; + uint data_size = 0; + get_key_info(key_part, &data_type, &data_size); + total_size += data_size; + if (data_type == TYPE_BYTE_BLOB) { + total_size += HA_KEY_BLOB_LENGTH; + } + } + + DBUG_RETURN(total_size); + } + + void MultipleColumnKeyCodec::get_key_info(KEY_PART_INFO *key_part, + DataType *data_type, + uint *data_size) { + MRN_DBUG_ENTER_METHOD(); + + *data_type = TYPE_UNKNOWN; + *data_size = 0; + + Field *field = key_part->field; + switch (field->real_type()) { + case MYSQL_TYPE_DECIMAL: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DECIMAL")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_YEAR: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TINY")); + *data_type = TYPE_NUMBER; + *data_size = 1; + break; + case MYSQL_TYPE_SHORT: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_SHORT")); + *data_type = TYPE_NUMBER; + *data_size = 2; + break; + case MYSQL_TYPE_LONG: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_LONG")); + *data_type = TYPE_NUMBER; + *data_size = 4; + break; + case MYSQL_TYPE_FLOAT: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_FLOAT")); + *data_type = TYPE_FLOAT; + *data_size = 4; + break; + case MYSQL_TYPE_DOUBLE: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DOUBLE")); + *data_type = TYPE_DOUBLE; + *data_size = 8; + break; + case MYSQL_TYPE_NULL: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_NULL")); + *data_type = TYPE_NUMBER; + *data_size = 1; + break; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_NEWDATE: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DATETIME")); + *data_type = TYPE_BYTE_REVERSE; + *data_size = key_part->length; + break; + case MYSQL_TYPE_LONGLONG: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_LONGLONG")); + *data_type = TYPE_NUMBER; + *data_size = 8; + break; + case MYSQL_TYPE_INT24: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_INT24")); + *data_type = TYPE_NUMBER; + *data_size = 3; + break; + case MYSQL_TYPE_TIME: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIME")); + *data_type = TYPE_LONG_LONG_NUMBER; + *data_size = 3; + break; + case MYSQL_TYPE_VARCHAR: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_VARCHAR")); + *data_type = TYPE_BYTE_BLOB; + *data_size = key_part->length; + break; + case MYSQL_TYPE_BIT: + // TODO + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_BIT")); + *data_type = TYPE_NUMBER; + *data_size = 1; + break; +#ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 + case MYSQL_TYPE_TIMESTAMP2: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIMESTAMP2")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; +#endif +#ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 + case MYSQL_TYPE_DATETIME2: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DATETIME2")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; +#endif +#ifdef MRN_HAVE_MYSQL_TYPE_TIME2 + case MYSQL_TYPE_TIME2: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIME2")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; +#endif + case MYSQL_TYPE_NEWDECIMAL: + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_NEWDECIMAL")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; + case MYSQL_TYPE_ENUM: + // TODO + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_ENUM")); + *data_type = TYPE_NUMBER; + *data_size = 1; + break; + case MYSQL_TYPE_SET: + // TODO + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_SET")); + *data_type = TYPE_NUMBER; + *data_size = 1; + break; + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + // TODO + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_BLOB")); + *data_type = TYPE_BYTE_BLOB; + *data_size = key_part->length; + break; + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + // TODO + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_STRING")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; + case MYSQL_TYPE_GEOMETRY: + // TODO + DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_GEOMETRY")); + *data_type = TYPE_BYTE_SEQUENCE; + *data_size = key_part->length; + break; + } + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::encode_float(volatile float value, uint data_size, + uchar *grn_key) { + MRN_DBUG_ENTER_METHOD(); + int n_bits = (data_size * 8 - 1); + volatile int *int_value_pointer = (int *)(&value); + int int_value = *int_value_pointer; + int_value ^= ((int_value >> n_bits) | (1 << n_bits)); + mrn_byte_order_host_to_network(grn_key, &int_value, data_size); + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::decode_float(const uchar *grn_key, + uchar *mysql_key, + uint data_size) { + MRN_DBUG_ENTER_METHOD(); + int int_value; + mrn_byte_order_host_to_network(&int_value, grn_key, data_size); + int max_bit = (data_size * 8 - 1); + *((int *)mysql_key) = + int_value ^ (((int_value ^ (1 << max_bit)) >> max_bit) | + (1 << max_bit)); + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::encode_double(volatile double value, uint data_size, + uchar *grn_key) { + MRN_DBUG_ENTER_METHOD(); + int n_bits = (data_size * 8 - 1); + volatile long long int *long_long_value_pointer = (long long int *)(&value); + volatile long long int long_long_value = *long_long_value_pointer; + long_long_value ^= ((long_long_value >> n_bits) | (1LL << n_bits)); + mrn_byte_order_host_to_network(grn_key, &long_long_value, data_size); + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::decode_double(const uchar *grn_key, + uchar *mysql_key, + uint data_size) { + MRN_DBUG_ENTER_METHOD(); + long long int long_long_value; + mrn_byte_order_host_to_network(&long_long_value, grn_key, data_size); + int max_bit = (data_size * 8 - 1); + *((long long int *)mysql_key) = + long_long_value ^ (((long_long_value ^ (1LL << max_bit)) >> max_bit) | + (1LL << max_bit)); + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::encode_reverse(const uchar *mysql_key, uint data_size, + uchar *grn_key) { + MRN_DBUG_ENTER_METHOD(); + for (uint i = 0; i < data_size; i++) { + grn_key[i] = mysql_key[data_size - i - 1]; + } + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::decode_reverse(const uchar *grn_key, + uchar *mysql_key, + uint data_size) { + MRN_DBUG_ENTER_METHOD(); + for (uint i = 0; i < data_size; i++) { + mysql_key[i] = grn_key[data_size - i - 1]; + } + DBUG_VOID_RETURN; + } + + void MultipleColumnKeyCodec::encode_blob(Field *field, + const uchar *mysql_key, + uchar *grn_key, + uint *data_size) { + FieldNormalizer normalizer(ctx_, thread_, field); + if (normalizer.should_normalize()) { +#if HA_KEY_BLOB_LENGTH != 2 +# error "TODO: support HA_KEY_BLOB_LENGTH != 2 case if it is needed" +#endif + const char *blob_data = + reinterpret_cast<const char *>(mysql_key + HA_KEY_BLOB_LENGTH); + uint16 blob_data_length = *((uint16 *)(mysql_key)); + grn_obj *grn_string = normalizer.normalize(blob_data, + blob_data_length); + mrn::SmartGrnObj smart_grn_string(ctx_, grn_string); + const char *normalized; + unsigned int normalized_length = 0; + grn_string_get_normalized(ctx_, grn_string, + &normalized, &normalized_length, NULL); + uint16 new_blob_data_length; + if (normalized_length <= UINT_MAX16) { + memcpy(grn_key, normalized, normalized_length); + if (normalized_length < *data_size) { + memset(grn_key + normalized_length, + '\0', *data_size - normalized_length); + } + new_blob_data_length = normalized_length; + } else { + push_warning_printf(thread_, + Sql_condition::WARN_LEVEL_WARN, + WARN_DATA_TRUNCATED, + "normalized data truncated " + "for multiple column index: " + "normalized-data-size: <%u> " + "max-data-size: <%u> " + "column-name: <%s> " + "data: <%.*s>", + normalized_length, + UINT_MAX16, + field->field_name, + blob_data_length, blob_data); + memcpy(grn_key, normalized, blob_data_length); + new_blob_data_length = blob_data_length; + } + memcpy(grn_key + *data_size, &new_blob_data_length, HA_KEY_BLOB_LENGTH); + } else { + memcpy(grn_key + *data_size, mysql_key, HA_KEY_BLOB_LENGTH); + memcpy(grn_key, mysql_key + HA_KEY_BLOB_LENGTH, *data_size); + } + *data_size += HA_KEY_BLOB_LENGTH; + } +} diff --git a/storage/mroonga/lib/mrn_multiple_column_key_codec.hpp b/storage/mroonga/lib/mrn_multiple_column_key_codec.hpp new file mode 100644 index 00000000000..fc6ae285357 --- /dev/null +++ b/storage/mroonga/lib/mrn_multiple_column_key_codec.hpp @@ -0,0 +1,70 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_MULTIPLE_COLUMN_KEY_CODEC_HPP_ +#define MRN_MULTIPLE_COLUMN_KEY_CODEC_HPP_ + +#include <groonga.h> + +#include <mrn_mysql.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + class MultipleColumnKeyCodec { + public: + MultipleColumnKeyCodec(grn_ctx *ctx, THD *thread, KEY *key_info); + ~MultipleColumnKeyCodec(); + + int encode(const uchar *mysql_key, uint mysql_key_length, + uchar *grn_key, uint *grn_key_length); + int decode(const uchar *grn_key, uint grn_key_length, + uchar *mysql_key, uint *mysql_key_length); + uint size(); + + private: + enum DataType { + TYPE_UNKNOWN, + TYPE_LONG_LONG_NUMBER, + TYPE_NUMBER, + TYPE_FLOAT, + TYPE_DOUBLE, + TYPE_BYTE_SEQUENCE, + TYPE_BYTE_REVERSE, + TYPE_BYTE_BLOB + }; + + grn_ctx *ctx_; + THD *thread_; + KEY *key_info_; + + void get_key_info(KEY_PART_INFO *key_part, + DataType *data_type, uint *data_size); + + void encode_float(volatile float value, uint data_size, uchar *grn_key); + void decode_float(const uchar *grn_key, uchar *mysql_key, uint data_size); + void encode_double(volatile double value, uint data_size, uchar *grn_key); + void decode_double(const uchar *grn_key, uchar *mysql_key, uint data_size); + void encode_reverse(const uchar *mysql_key, uint data_size, uchar *grn_key); + void decode_reverse(const uchar *grn_key, uchar *mysql_key, uint data_size); + void encode_blob(Field *field, + const uchar *mysql_key, uchar *grn_key, uint *data_size); + }; +} + +#endif // MRN_MULTIPLE_COLUMN_KEY_CODEC_HPP_ diff --git a/storage/mroonga/lib/mrn_mysqlservices.cpp b/storage/mroonga/lib/mrn_mysqlservices.cpp new file mode 100644 index 00000000000..9c7af9acfe0 --- /dev/null +++ b/storage/mroonga/lib/mrn_mysqlservices.cpp @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* + Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <mrn_mysql.h> +#include <mrn_mysql_compat.h> + +/* +void *thd_alloc(MYSQL_THD thd, unsigned int size) +{ + return thd->alloc(size); +} +*/ diff --git a/storage/mroonga/lib/mrn_parameters_parser.cpp b/storage/mroonga/lib/mrn_parameters_parser.cpp new file mode 100644 index 00000000000..9a05097e548 --- /dev/null +++ b/storage/mroonga/lib/mrn_parameters_parser.cpp @@ -0,0 +1,176 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2013 Kentoku SHIBA + Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "mrn_parameters_parser.hpp" + +#include <mrn_mysql_compat.h> + +namespace mrn { + class Parameter { + public: + char *key_; + char *value_; + + Parameter(const char *key, unsigned int key_length, + const char *value, unsigned int value_length) + : key_(my_strndup(key, key_length, MYF(0))), + value_(my_strndup(value, value_length, MYF(0))) { + }; + ~Parameter() { + if (key_) { + my_free(key_, MYF(0)); + } + if (value_) { + my_free(value_, MYF(0)); + } + }; + }; + + ParametersParser::ParametersParser(const char *input, + unsigned int input_length) + : input_(input), + input_length_(input_length), + parameters_(NULL) { + } + + ParametersParser::~ParametersParser() { + for (LIST *next = parameters_; next; next = next->next) { + Parameter *parameter = static_cast<Parameter *>(next->data); + delete parameter; + } + list_free(parameters_, false); + } + + void ParametersParser::parse() { + const char *current = input_; + const char *end = input_ + input_length_; + for (; current < end; ++current) { + if (is_white_space(current[0])) { + continue; + } + + const char *key = current; + unsigned int key_length = 0; + while (current < end && + !is_white_space(current[0]) && + current[0] != '\'' && current[0] != '"' && current[0] != ',') { + ++current; + ++key_length; + } + if (current == end) { + break; + } + + while (current < end && is_white_space(current[0])) { + ++current; + } + if (current == end) { + break; + } + current = parse_value(current, end, key, key_length); + if (!current) { + break; + } + + while (current < end && is_white_space(current[0])) { + ++current; + } + if (current == end) { + break; + } + if (current[0] != ',') { + // TODO: report error + break; + } + } + } + + const char *ParametersParser::parse_value(const char *current, + const char *end, + const char *key, + unsigned int key_length) { + char quote = current[0]; + if (quote != '\'' && quote != '"') { + // TODO: report error + return NULL; + } + ++current; + + bool found = false; + static const unsigned int max_value_length = 4096; + char value[max_value_length]; + unsigned int value_length = 0; + for (; current < end && value_length < max_value_length; ++current) { + if (current[0] == quote) { + Parameter *parameter = new Parameter(key, key_length, + value, value_length); + list_push(parameters_, parameter); + found = true; + ++current; + break; + } + + switch (current[0]) { + case '\\': + if (current + 1 == end) { + break; + } + switch (current[1]) { + case 'b': + value[value_length] = '\b'; + break; + case 'n': + value[value_length] = '\n'; + break; + case 'r': + value[value_length] = '\r'; + break; + case 't': + value[value_length] = '\t'; + break; + default: + value[value_length] = current[1]; + break; + } + break; + default: + value[value_length] = current[0]; + break; + } + ++value_length; + } + + if (!found) { + // TODO: report error + } + + return current; + } + + const char *ParametersParser::operator[](const char *key) { + for (LIST *next = parameters_; next; next = next->next) { + Parameter *parameter = static_cast<Parameter *>(next->data); + if (strcasecmp(parameter->key_, key) == 0) { + return parameter->value_; + } + } + return NULL; + } +} diff --git a/storage/mroonga/lib/mrn_parameters_parser.hpp b/storage/mroonga/lib/mrn_parameters_parser.hpp new file mode 100644 index 00000000000..a15371ca72e --- /dev/null +++ b/storage/mroonga/lib/mrn_parameters_parser.hpp @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2013 Kentoku SHIBA + Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_PARAMETERS_PARSER_HPP_ +#define MRN_PARAMETERS_PARSER_HPP_ + +#include <mrn_mysql.h> +#include <my_list.h> + +namespace mrn { + class ParametersParser { + public: + ParametersParser(const char *input, unsigned int input_length); + ~ParametersParser(); + void parse(); + const char *operator[](const char *key); + + private: + const char *input_; + unsigned int input_length_; + + LIST *parameters_; + + bool is_white_space(char character) { + switch (character) { + case ' ': + case '\r': + case '\n': + case '\t': + return true; + break; + default: + return false; + break; + } + }; + const char *parse_value(const char *current, const char *end, + const char *key, unsigned int key_length); + }; +} + +#endif /* MRN_PARAMETERS_PARSER_HPP_ */ diff --git a/storage/mroonga/lib/mrn_path_mapper.cpp b/storage/mroonga/lib/mrn_path_mapper.cpp new file mode 100644 index 00000000000..8856e6f6082 --- /dev/null +++ b/storage/mroonga/lib/mrn_path_mapper.cpp @@ -0,0 +1,196 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010 Tetsuro IKEDA + Copyright(C) 2011-2013 Kentoku SHIBA + Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mrn_path_mapper.hpp" + +#include <string.h> + +#include <mrn_mysql.h> + +namespace mrn { + char *PathMapper::default_path_prefix = NULL; + char *PathMapper::default_mysql_data_home_path = NULL; + + PathMapper::PathMapper(const char *mysql_path, + const char *path_prefix, + const char *mysql_data_home_path) + : mysql_path_(mysql_path), + path_prefix_(path_prefix), + mysql_data_home_path_(mysql_data_home_path) { + db_path_[0] = '\0'; + db_name_[0] = '\0'; + table_name_[0] = '\0'; + mysql_table_name_[0] = '\0'; + } + + /** + * "./${db}/${table}" ==> "${db}.mrn" + * "./${db}/" ==> "${db}.mrn" + * "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0" ==> + * "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0.mrn" + */ + const char *PathMapper::db_path() { + if (db_path_[0] != '\0') { + return db_path_; + } + + if (mysql_path_[0] == FN_CURLIB && mysql_path_[1] == FN_LIBCHAR) { + if (path_prefix_) { + strcpy(db_path_, path_prefix_); + } + + int i = 2, j = strlen(db_path_), len; + len = strlen(mysql_path_); + while (mysql_path_[i] != FN_LIBCHAR && i < len) { + db_path_[j++] = mysql_path_[i++]; + } + db_path_[j] = '\0'; + } else if (mysql_data_home_path_) { + int len = strlen(mysql_path_); + int mysql_data_home_len = strlen(mysql_data_home_path_); + if (len > mysql_data_home_len && + !strncmp(mysql_path_, mysql_data_home_path_, mysql_data_home_len)) { + int i = mysql_data_home_len, j; + if (path_prefix_ && path_prefix_[0] == FN_LIBCHAR) { + strcpy(db_path_, path_prefix_); + j = strlen(db_path_); + } else { + memcpy(db_path_, mysql_data_home_path_, mysql_data_home_len); + if (path_prefix_) { + if (path_prefix_[0] == FN_CURLIB && + path_prefix_[1] == FN_LIBCHAR) { + strcpy(&db_path_[mysql_data_home_len], &path_prefix_[2]); + } else { + strcpy(&db_path_[mysql_data_home_len], path_prefix_); + } + j = strlen(db_path_); + } else { + j = mysql_data_home_len; + } + } + + while (mysql_path_[i] != FN_LIBCHAR && i < len) { + db_path_[j++] = mysql_path_[i++]; + } + if (i == len) { + memcpy(db_path_, mysql_path_, len); + } else { + db_path_[j] = '\0'; + } + } else { + strcpy(db_path_, mysql_path_); + } + } else { + strcpy(db_path_, mysql_path_); + } + strcat(db_path_, MRN_DB_FILE_SUFFIX); + return db_path_; + } + + /** + * "./${db}/${table}" ==> "${db}" + * "./${db}/" ==> "${db}" + * "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0" ==> + * "/tmp/mysql-test/var/tmp/mysqld.1/#sql27c5_1_0" + */ + const char *PathMapper::db_name() { + if (db_name_[0] != '\0') { + return db_name_; + } + + if (mysql_path_[0] == FN_CURLIB && mysql_path_[1] == FN_LIBCHAR) { + int i = 2, j = 0, len; + len = strlen(mysql_path_); + while (mysql_path_[i] != FN_LIBCHAR && i < len) { + db_name_[j++] = mysql_path_[i++]; + } + db_name_[j] = '\0'; + } else if (mysql_data_home_path_) { + int len = strlen(mysql_path_); + int mysql_data_home_len = strlen(mysql_data_home_path_); + if (len > mysql_data_home_len && + !strncmp(mysql_path_, mysql_data_home_path_, mysql_data_home_len)) { + int i = mysql_data_home_len, j = 0; + while (mysql_path_[i] != FN_LIBCHAR && i < len) { + db_name_[j++] = mysql_path_[i++]; + } + if (i == len) { + memcpy(db_name_, mysql_path_, len); + } else { + db_name_[j] = '\0'; + } + } else { + strcpy(db_name_, mysql_path_); + } + } else { + strcpy(db_name_, mysql_path_); + } + return db_name_; + } + + /** + * "./${db}/${table}" ==> "${table}" (with encoding first '_') + */ + const char *PathMapper::table_name() { + if (table_name_[0] != '\0') { + return table_name_; + } + + int len = strlen(mysql_path_); + int i = len, j = 0; + for (; mysql_path_[--i] != FN_LIBCHAR ;) {} + if (mysql_path_[i + 1] == '_') { + table_name_[j++] = '@'; + table_name_[j++] = '0'; + table_name_[j++] = '0'; + table_name_[j++] = '5'; + table_name_[j++] = 'f'; + i++; + } + for (; i < len ;) { + table_name_[j++] = mysql_path_[++i]; + } + table_name_[j] = '\0'; + return table_name_; + } + + /** + * "./${db}/${table}" ==> "${table}" (without encoding first '_') + */ + const char *PathMapper::mysql_table_name() { + if (mysql_table_name_[0] != '\0') { + return mysql_table_name_; + } + + int len = strlen(mysql_path_); + int i = len, j = 0; + for (; mysql_path_[--i] != FN_LIBCHAR ;) {} + for (; i < len ;) { + mysql_table_name_[j++] = mysql_path_[++i]; + } + mysql_table_name_[j] = '\0'; + return mysql_table_name_; + } +} diff --git a/storage/mroonga/lib/mrn_path_mapper.hpp b/storage/mroonga/lib/mrn_path_mapper.hpp new file mode 100644 index 00000000000..f70cd7b5587 --- /dev/null +++ b/storage/mroonga/lib/mrn_path_mapper.hpp @@ -0,0 +1,51 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010 Tetsuro IKEDA + Copyright(C) 2010-2013 Kentoku SHIBA + Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_PATH_MAPPER_HPP_ +#define MRN_PATH_MAPPER_HPP_ + +#include <mrn_constants.hpp> + +namespace mrn { + class PathMapper { + public: + static char *default_path_prefix; + static char *default_mysql_data_home_path; + + PathMapper(const char *mysql_path, + const char *path_prefix=default_path_prefix, + const char *mysql_data_home_path=default_mysql_data_home_path); + const char *db_path(); + const char *db_name(); + const char *table_name(); + const char *mysql_table_name(); + private: + const char *mysql_path_; + const char *path_prefix_; + const char *mysql_data_home_path_; + char db_path_[MRN_MAX_PATH_SIZE]; + char db_name_[MRN_MAX_PATH_SIZE]; + char table_name_[MRN_MAX_PATH_SIZE]; + char mysql_table_name_[MRN_MAX_PATH_SIZE]; + }; +} + +#endif /* MRN_PATH_MAPPER_HPP_ */ diff --git a/storage/mroonga/lib/mrn_smart_grn_obj.cpp b/storage/mroonga/lib/mrn_smart_grn_obj.cpp new file mode 100644 index 00000000000..9dbae6528f9 --- /dev/null +++ b/storage/mroonga/lib/mrn_smart_grn_obj.cpp @@ -0,0 +1,53 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <string.h> + +#include "mrn_smart_grn_obj.hpp" + +namespace mrn { + SmartGrnObj::SmartGrnObj(grn_ctx *ctx, grn_obj *obj) + : ctx_(ctx), + obj_(obj) { + } + + SmartGrnObj::SmartGrnObj(grn_ctx *ctx, const char *name, int name_size) + : ctx_(ctx), + obj_(NULL) { + if (name_size < 0) { + name_size = strlen(name); + } + obj_ = grn_ctx_get(ctx_, name, name_size); + } + + SmartGrnObj::SmartGrnObj(grn_ctx *ctx, grn_id id) + : ctx_(ctx), + obj_(grn_ctx_at(ctx_, id)) { + } + + SmartGrnObj::~SmartGrnObj() { + if (obj_) { + grn_obj_unlink(ctx_, obj_); + } + } + + grn_obj *SmartGrnObj::get() { + return obj_; + } +} diff --git a/storage/mroonga/lib/mrn_smart_grn_obj.hpp b/storage/mroonga/lib/mrn_smart_grn_obj.hpp new file mode 100644 index 00000000000..c9c86f3e46e --- /dev/null +++ b/storage/mroonga/lib/mrn_smart_grn_obj.hpp @@ -0,0 +1,39 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_SMART_GRN_OBJ_HPP_ +#define MRN_SMART_GRN_OBJ_HPP_ + +#include <groonga.h> + +namespace mrn { + class SmartGrnObj { + grn_ctx *ctx_; + grn_obj *obj_; + public: + SmartGrnObj(grn_ctx *ctx, grn_obj *obj); + SmartGrnObj(grn_ctx *ctx, const char *name, int name_size=-1); + SmartGrnObj(grn_ctx *ctx, grn_id id); + ~SmartGrnObj(); + + grn_obj *get(); + }; +} + +#endif // MRN_SMART_GRN_OBJ_HPP_ diff --git a/storage/mroonga/lib/mrn_time_converter.cpp b/storage/mroonga/lib/mrn_time_converter.cpp new file mode 100644 index 00000000000..63b2e53766d --- /dev/null +++ b/storage/mroonga/lib/mrn_time_converter.cpp @@ -0,0 +1,260 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2013 Kentoku SHIBA + Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mrn_time_converter.hpp" + +#ifdef min +# undef min +#endif +#ifdef max +# undef max +#endif + +#include <limits> + +// for debug +#define MRN_CLASS_NAME "mrn::TimeConverter" + +namespace mrn { + TimeConverter::TimeConverter() { + } + + TimeConverter::~TimeConverter() { + } + + time_t TimeConverter::tm_to_time_gm(struct tm *time, bool *truncated) { + MRN_DBUG_ENTER_METHOD(); + *truncated = true; + struct tm gmdate; + time->tm_yday = -1; + time->tm_isdst = -1; + time_t sec_t = mktime(time); + if (time->tm_yday == -1) { + DBUG_RETURN(-1); + } + if (!gmtime_r(&sec_t, &gmdate)) { + DBUG_RETURN(-1); + } + int32 mrn_utc_diff_in_seconds = + ( + time->tm_mday > 25 && gmdate.tm_mday == 1 ? -1 : + time->tm_mday == 1 && gmdate.tm_mday > 25 ? 1 : + time->tm_mday - gmdate.tm_mday + ) * 24 * 60 * 60 + + (time->tm_hour - gmdate.tm_hour) * 60 * 60 + + (time->tm_min - gmdate.tm_min) * 60 + + (time->tm_sec - gmdate.tm_sec); + DBUG_PRINT("info", ("mroonga: time->tm_year=%d", time->tm_year)); + DBUG_PRINT("info", ("mroonga: time->tm_mon=%d", time->tm_mon)); + DBUG_PRINT("info", ("mroonga: time->tm_mday=%d", time->tm_mday)); + DBUG_PRINT("info", ("mroonga: time->tm_hour=%d", time->tm_hour)); + DBUG_PRINT("info", ("mroonga: time->tm_min=%d", time->tm_min)); + DBUG_PRINT("info", ("mroonga: time->tm_sec=%d", time->tm_sec)); + DBUG_PRINT("info", ("mroonga: mrn_utc_diff_in_seconds=%d", + mrn_utc_diff_in_seconds)); + if (mrn_utc_diff_in_seconds > 0) { + if (sec_t > std::numeric_limits<time_t>::max() - mrn_utc_diff_in_seconds) { + DBUG_RETURN(-1); + } + } else { + if (sec_t < std::numeric_limits<time_t>::min() - mrn_utc_diff_in_seconds) { + DBUG_RETURN(-1); + } + } + *truncated = false; + DBUG_RETURN(sec_t + mrn_utc_diff_in_seconds); + } + + long long int TimeConverter::tm_to_grn_time(struct tm *time, int usec, + bool *truncated) { + MRN_DBUG_ENTER_METHOD(); + + long long int sec = tm_to_time_gm(time, truncated); + + DBUG_PRINT("info", ("mroonga: sec=%lld", sec)); + DBUG_PRINT("info", ("mroonga: usec=%d", usec)); + + long long int grn_time = *truncated ? 0 : GRN_TIME_PACK(sec, usec); + + DBUG_RETURN(grn_time); + } + + long long int TimeConverter::mysql_time_to_grn_time(MYSQL_TIME *mysql_time, + bool *truncated) { + MRN_DBUG_ENTER_METHOD(); + + int usec = mysql_time->second_part; + long long int grn_time = 0; + + *truncated = false; + switch (mysql_time->time_type) { + case MYSQL_TIMESTAMP_DATE: + { + DBUG_PRINT("info", ("mroonga: MYSQL_TIMESTAMP_DATE")); + struct tm date; + memset(&date, 0, sizeof(struct tm)); + date.tm_year = mysql_time->year - TM_YEAR_BASE; + if (mysql_time->month > 0) { + date.tm_mon = mysql_time->month - 1; + } else { + date.tm_mon = 0; + *truncated = true; + } + if (mysql_time->day > 0) { + date.tm_mday = mysql_time->day; + } else { + date.tm_mday = 1; + *truncated = true; + } + DBUG_PRINT("info", ("mroonga: tm_year=%d", date.tm_year)); + DBUG_PRINT("info", ("mroonga: tm_mon=%d", date.tm_mon)); + DBUG_PRINT("info", ("mroonga: tm_mday=%d", date.tm_mday)); + bool tm_truncated = false; + grn_time = tm_to_grn_time(&date, usec, &tm_truncated); + if (tm_truncated) { + *truncated = true; + } + } + break; + case MYSQL_TIMESTAMP_DATETIME: + { + DBUG_PRINT("info", ("mroonga: MYSQL_TIMESTAMP_DATETIME")); + struct tm datetime; + memset(&datetime, 0, sizeof(struct tm)); + datetime.tm_year = mysql_time->year - TM_YEAR_BASE; + if (mysql_time->month > 0) { + datetime.tm_mon = mysql_time->month - 1; + } else { + datetime.tm_mon = 0; + *truncated = true; + } + if (mysql_time->day > 0) { + datetime.tm_mday = mysql_time->day; + } else { + datetime.tm_mday = 1; + *truncated = true; + } + datetime.tm_hour = mysql_time->hour; + datetime.tm_min = mysql_time->minute; + datetime.tm_sec = mysql_time->second; + DBUG_PRINT("info", ("mroonga: tm_year=%d", datetime.tm_year)); + DBUG_PRINT("info", ("mroonga: tm_mon=%d", datetime.tm_mon)); + DBUG_PRINT("info", ("mroonga: tm_mday=%d", datetime.tm_mday)); + DBUG_PRINT("info", ("mroonga: tm_hour=%d", datetime.tm_hour)); + DBUG_PRINT("info", ("mroonga: tm_min=%d", datetime.tm_min)); + DBUG_PRINT("info", ("mroonga: tm_sec=%d", datetime.tm_sec)); + bool tm_truncated = false; + grn_time = tm_to_grn_time(&datetime, usec, &tm_truncated); + if (tm_truncated) { + *truncated = true; + } + } + break; + case MYSQL_TIMESTAMP_TIME: + { + DBUG_PRINT("info", ("mroonga: MYSQL_TIMESTAMP_TIME")); + int sec = + mysql_time->hour * 60 * 60 + + mysql_time->minute * 60 + + mysql_time->second; + DBUG_PRINT("info", ("mroonga: sec=%d", sec)); + grn_time = GRN_TIME_PACK(sec, usec); + if (mysql_time->neg) { + grn_time = -grn_time; + } + } + break; + default: + DBUG_PRINT("info", ("mroonga: default")); + grn_time = 0; + break; + } + + DBUG_RETURN(grn_time); + } + + void TimeConverter::grn_time_to_mysql_time(long long int grn_time, + MYSQL_TIME *mysql_time) { + MRN_DBUG_ENTER_METHOD(); + long long int sec; + int usec; + GRN_TIME_UNPACK(grn_time, sec, usec); + DBUG_PRINT("info", ("mroonga: sec=%lld", sec)); + DBUG_PRINT("info", ("mroonga: usec=%d", usec)); + switch (mysql_time->time_type) { + case MYSQL_TIMESTAMP_DATE: + { + DBUG_PRINT("info", ("mroonga: MYSQL_TIMESTAMP_DATE")); + struct tm date; + time_t sec_t = sec; + // TODO: Add error check + gmtime_r(&sec_t, &date); + DBUG_PRINT("info", ("mroonga: tm_year=%d", date.tm_year)); + mysql_time->year = date.tm_year + TM_YEAR_BASE; + DBUG_PRINT("info", ("mroonga: tm_mon=%d", date.tm_mon)); + mysql_time->month = date.tm_mon + 1; + DBUG_PRINT("info", ("mroonga: tm_mday=%d", date.tm_mday)); + mysql_time->day = date.tm_mday; + } + break; + case MYSQL_TIMESTAMP_DATETIME: + { + DBUG_PRINT("info", ("mroonga: MYSQL_TIMESTAMP_DATETIME")); + struct tm date; + time_t sec_t = sec; + // TODO: Add error check + gmtime_r(&sec_t, &date); + DBUG_PRINT("info", ("mroonga: tm_year=%d", date.tm_year)); + mysql_time->year = date.tm_year + TM_YEAR_BASE; + DBUG_PRINT("info", ("mroonga: tm_mon=%d", date.tm_mon)); + mysql_time->month = date.tm_mon + 1; + DBUG_PRINT("info", ("mroonga: tm_mday=%d", date.tm_mday)); + mysql_time->day = date.tm_mday; + DBUG_PRINT("info", ("mroonga: tm_hour=%d", date.tm_hour)); + mysql_time->hour = date.tm_hour; + DBUG_PRINT("info", ("mroonga: tm_min=%d", date.tm_min)); + mysql_time->minute = date.tm_min; + DBUG_PRINT("info", ("mroonga: tm_sec=%d", date.tm_sec)); + mysql_time->second = date.tm_sec; + mysql_time->second_part = usec; + } + break; + case MYSQL_TIMESTAMP_TIME: + DBUG_PRINT("info", ("mroonga: MYSQL_TIMESTAMP_TIME")); + if (sec < 0) { + mysql_time->neg = true; + sec = -sec; + } + mysql_time->hour = static_cast<unsigned int>(sec / 60 / 60); + mysql_time->minute = sec / 60 % 60; + mysql_time->second = sec % 60; + mysql_time->second_part = usec; + break; + default: + DBUG_PRINT("info", ("mroonga: default")); + break; + } + DBUG_VOID_RETURN; + } +} diff --git a/storage/mroonga/lib/mrn_time_converter.hpp b/storage/mroonga/lib/mrn_time_converter.hpp new file mode 100644 index 00000000000..c5c69a0a8ad --- /dev/null +++ b/storage/mroonga/lib/mrn_time_converter.hpp @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2013 Kentoku SHIBA + Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_TIME_CONVERTER_HPP_ +#define MRN_TIME_CONVERTER_HPP_ + +#include <groonga.h> +#include <mrn_mysql_compat.h> + +namespace mrn { + class TimeConverter { + public: + static const long long int TM_YEAR_BASE = 1900; + + TimeConverter(); + ~TimeConverter(); + + long long int mysql_time_to_grn_time(MYSQL_TIME *mysql_time, + bool *truncated); + + long long int tm_to_grn_time(struct tm *time, int usec, bool *truncated); + + void grn_time_to_mysql_time(long long int grn_time, MYSQL_TIME *mysql_time); + + private: + time_t tm_to_time_gm(struct tm *time, bool *truncated); + }; +} + +#endif /* MRN_TIME_CONVERTER_HPP_ */ diff --git a/storage/mroonga/lib/mrn_windows.hpp b/storage/mroonga/lib/mrn_windows.hpp new file mode 100644 index 00000000000..f6ae4490254 --- /dev/null +++ b/storage/mroonga/lib/mrn_windows.hpp @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* + Copyright(C) 2010 Tetsuro IKEDA + Copyright(C) 2010-2013 Kentoku SHIBA + Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MRN_WINDOWS_HPP_ +#define MRN_WINDOWS_HPP_ + +#if defined(_WIN32) || defined(_WIN64) +# define MRN_API __declspec(dllexport) +#else +# define MRN_API +#endif + +#endif /* MRN_WINDOWS_HPP_ */ |