Commit 18b93d6e authored by Yuchen Pei's avatar Yuchen Pei

MDEV-28993 Spider: Push down CASE statement

parent 99dc0f03
......@@ -66,9 +66,9 @@ id greeting
connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %';
argument
select `id`,`greeting` from `auto_test_remote`.`tbl_a` where `greeting` = 'Aloha!' and ((`greeting` = 'Aloha!'))
select `id`,`greeting` from `auto_test_remote`.`tbl_b` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!'))
select `id`,`greeting` from `auto_test_remote`.`tbl_c` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!'))
select t0.`id` `id`,t0.`greeting` `greeting` from `auto_test_remote`.`tbl_a` t0 where ((t0.`greeting` = 'Aloha!') and ((case t0.`greeting` when 'Aloha!' then _latin1'one' else _latin1'more' end) = _latin1'one'))
select t0.`id` `id`,t0.`greeting` `greeting` from `auto_test_remote`.`tbl_b` t0 where ((t0.`greeting` = 'Aloha!') and ((case t0.`greeting` when 'Aloha!' then _latin1'one' else _latin1'more' end) = _latin1'one'))
select t0.`id` `id`,t0.`greeting` `greeting` from `auto_test_remote`.`tbl_c` t0 where ((t0.`greeting` = 'Aloha!') and ((case t0.`greeting` when 'Aloha!' then _latin1'one' else _latin1'more' end) = _latin1'one'))
SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %'
connection child2_1;
SET @@global.general_log = @general_log_backup;
......
#
# MDEV-28993 Spider: Push down CASE statement
#
for master_1
for child2
for child3
set spider_same_server_link= 1;
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
insert into t1 values (42), (3), (848), (100);
explain select case c when 3 then "three" when 42 then "answer" else "other" end from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY
select case c when 3 then "three" when 42 then "answer" else "other" end from t1;
case c when 3 then "three" when 42 then "answer" else "other" end
answer
three
other
other
explain select case c when 3 then "three" when 42 then "answer" end from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY
select case c when 3 then "three" when 42 then "answer" end from t1;
case c when 3 then "three" when 42 then "answer" end
answer
three
NULL
NULL
explain select case when c = 3 then "three" when c = 42 then "answer" else "other" end from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY
select case when c = 3 then "three" when c = 42 then "answer" else "other" end from t1;
case when c = 3 then "three" when c = 42 then "answer" else "other" end
answer
three
other
other
explain select case when c = 3 then "three" when c = 42 then "answer" end from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY
select case when c = 3 then "three" when c = 42 then "answer" end from t1;
case when c = 3 then "three" when c = 42 then "answer" end
answer
three
NULL
NULL
drop table t1, t2;
drop server srv;
for master_1
for child2
for child3
#
# end of test pushdown_case
#
--echo #
--echo # MDEV-28993 Spider: Push down CASE statement
--echo #
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
set spider_same_server_link= 1;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
insert into t1 values (42), (3), (848), (100);
# everything
let $query=
select case c when 3 then "three" when 42 then "answer" else "other" end from t1;
eval explain $query;
eval $query;
# no else
let $query=
select case c when 3 then "three" when 42 then "answer" end from t1;
eval explain $query;
eval $query;
# no value
let $query=
select case when c = 3 then "three" when c = 42 then "answer" else "other" end from t1;
eval explain $query;
eval $query;
# neither
let $query=
select case when c = 3 then "three" when c = 42 then "answer" end from t1;
eval explain $query;
eval $query;
drop table t1, t2;
drop server srv;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log
--echo #
--echo # end of test pushdown_case
--echo #
......@@ -25,7 +25,6 @@
#define PLUGIN_VAR_CAN_MEMALLOC
/*
#define ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC
#define HASH_UPDATE_WITH_HASH_VALUE
*/
......@@ -106,7 +105,6 @@ typedef st_spider_result SPIDER_RESULT;
#define SPIDER_SQL_HS_LTEQUAL_STR "<="
#define SPIDER_SQL_HS_LTEQUAL_LEN (sizeof(SPIDER_SQL_HS_LTEQUAL_STR) - 1)
#ifdef ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC
#define SPIDER_SQL_CASE_STR "case "
#define SPIDER_SQL_CASE_LEN (sizeof(SPIDER_SQL_CASE_STR) - 1)
#define SPIDER_SQL_WHEN_STR " when "
......@@ -117,7 +115,6 @@ typedef st_spider_result SPIDER_RESULT;
#define SPIDER_SQL_ELSE_LEN (sizeof(SPIDER_SQL_ELSE_STR) - 1)
#define SPIDER_SQL_END_STR " end"
#define SPIDER_SQL_END_LEN (sizeof(SPIDER_SQL_END_STR) - 1)
#endif
#define SPIDER_SQL_USING_STR " using "
#define SPIDER_SQL_USING_LEN (sizeof(SPIDER_SQL_USING_STR) - 1)
......
......@@ -5547,10 +5547,6 @@ int spider_db_mbase_util::check_item_func(
switch (func_type)
{
case Item_func::TRIG_COND_FUNC:
case Item_func::CASE_SEARCHED_FUNC:
#ifndef ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC
case Item_func::CASE_SIMPLE_FUNC:
#endif
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
case Item_func::NOT_FUNC:
/* Why the following check is necessary? */
......@@ -5620,15 +5616,15 @@ int spider_db_mbase_util::print_item_func(
Item *item, **item_list = item_func->arguments();
Field *field;
spider_string tmp_str;
uint roop_count, item_count = item_func->argument_count(), start_item = 0;
uint i, item_count = item_func->argument_count(), start_item = 0;
const char *func_name = SPIDER_SQL_NULL_CHAR_STR,
*separator_str = SPIDER_SQL_NULL_CHAR_STR,
*last_str = SPIDER_SQL_NULL_CHAR_STR;
int func_name_length = SPIDER_SQL_NULL_CHAR_LEN,
separator_str_length = SPIDER_SQL_NULL_CHAR_LEN,
last_str_length = SPIDER_SQL_NULL_CHAR_LEN;
int use_pushdown_udf;
bool merge_func = FALSE;
int use_pushdown_udf, case_when_start, case_when_count;
bool merge_func = FALSE, case_with_else;
DBUG_ENTER("spider_db_mbase_util::print_item_func");
DBUG_ASSERT(!check_item_func(item_func, spider, alias, alias_length,
use_fields, fields));
......@@ -6490,23 +6486,39 @@ int spider_db_mbase_util::print_item_func(
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
case Item_func::CASE_SEARCHED_FUNC:
case Item_func::CASE_SIMPLE_FUNC:
#ifdef ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC
Item_func_case *item_func_case = (Item_func_case *) item_func;
/*
Arrangement of arguments:
- Item_func_case_searched:
when1 when2 ... whenk then1 then2 .. thenk [else]
- Item_func_case_simple:
value when1 when2 ... whenk then1 then2 .. thenk [else]
*/
if (item_func->functype() == Item_func::CASE_SEARCHED_FUNC)
{
case_when_start= 0;
case_when_count= item_count / 2;
case_with_else= item_count % 2;
}
else
{
case_when_start= 1;
case_when_count= (item_count - 1) / 2;
case_with_else= item_count % 2 == 0;
}
if (str)
{
if (str->reserve(SPIDER_SQL_CASE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_CASE_STR, SPIDER_SQL_CASE_LEN);
}
if (item_func_case->first_expr_num != -1)
if (case_when_start > 0)
{
if ((error_num = spider_db_print_item_type(
item_list[item_func_case->first_expr_num], NULL, spider, str,
item_list[0], NULL, spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
}
for (roop_count = 0; roop_count < item_func_case->ncases;
roop_count += 2)
for (i = 0; i < (uint) case_when_count; i++)
{
if (str)
{
......@@ -6515,7 +6527,7 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN);
}
if ((error_num = spider_db_print_item_type(
item_list[roop_count], NULL, spider, str,
item_list[i + case_when_start], NULL, spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
if (str)
......@@ -6525,11 +6537,11 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN);
}
if ((error_num = spider_db_print_item_type(
item_list[roop_count + 1], NULL, spider, str,
item_list[i + case_when_start + case_when_count], NULL, spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
}
if (item_func_case->else_expr_num != -1)
if (case_with_else)
{
if (str)
{
......@@ -6538,7 +6550,7 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN);
}
if ((error_num = spider_db_print_item_type(
item_list[item_func_case->else_expr_num], NULL, spider, str,
item_list[item_count - 1], NULL, spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
}
......@@ -6551,9 +6563,6 @@ int spider_db_mbase_util::print_item_func(
SPIDER_SQL_CLOSE_PAREN_LEN);
}
DBUG_RETURN(0);
#else
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
#endif
case Item_func::JSON_EXTRACT_FUNC:
func_name = (char*) item_func->func_name();
func_name_length = strlen(func_name);
......@@ -6607,13 +6616,13 @@ int spider_db_mbase_util::print_item_func(
Loop through the items of the current function expression to
print its portion of the statement
*/
for (roop_count = start_item; roop_count < item_count; roop_count++)
for (i = start_item; i < item_count; i++)
{
item = item_list[roop_count];
item = item_list[i];
if ((error_num = spider_db_print_item_type(item, field, spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
if (roop_count == 1)
if (i == 1)
{
/* Remaining operands need to be preceded by the separator */
func_name = separator_str;
......@@ -6627,7 +6636,7 @@ int spider_db_mbase_util::print_item_func(
}
/* Print the last operand value */
item = item_list[roop_count];
item = item_list[i];
if ((error_num = spider_db_print_item_type(item, field, spider, str,
alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment