mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 19:41:47 +01:00
609 lines
18 KiB
C++
609 lines
18 KiB
C++
|
/* -*- 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;
|
||
|
}
|
||
|
}
|