Update Mroonga to the latest version on 2014-09-21T00:33:44+0900

This commit is contained in:
Kentoku SHIBA 2014-09-21 00:33:45 +09:00
commit 0cc855cdc8
2027 changed files with 460307 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
libmysqlservices_la_SOURCES = \
mrn_mysqlservices.cpp

View file

@ -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_));
}
}
}

View file

@ -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_

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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
}
}

View file

@ -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_

View file

@ -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);
}
}
}

View file

@ -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_

View file

@ -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_;
}
}

View file

@ -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_

View file

@ -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);
}
}

View file

@ -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_

View file

@ -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);
}
}

View file

@ -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_ */

View file

@ -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);
}
}

View file

@ -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_ */

View file

@ -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_);
}
}

View file

@ -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_ */

View file

@ -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_);
}
}

View file

@ -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_

View file

@ -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;
}
}

View file

@ -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_

View file

@ -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);
}
*/

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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_;
}
}

View file

@ -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_ */

View file

@ -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_;
}
}

View file

@ -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_

View file

@ -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;
}
}

View file

@ -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_ */

View file

@ -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_ */