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 ...@@ -66,9 +66,9 @@ id greeting
connection child2_1; connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %'; SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %';
argument argument
select `id`,`greeting` from `auto_test_remote`.`tbl_a` where `greeting` = '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 `id`,`greeting` from `auto_test_remote`.`tbl_b` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!')) 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 `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_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 %' SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %'
connection child2_1; connection child2_1;
SET @@global.general_log = @general_log_backup; 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 @@ ...@@ -25,7 +25,6 @@
#define PLUGIN_VAR_CAN_MEMALLOC #define PLUGIN_VAR_CAN_MEMALLOC
/* /*
#define ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC
#define HASH_UPDATE_WITH_HASH_VALUE #define HASH_UPDATE_WITH_HASH_VALUE
*/ */
...@@ -106,7 +105,6 @@ typedef st_spider_result SPIDER_RESULT; ...@@ -106,7 +105,6 @@ typedef st_spider_result SPIDER_RESULT;
#define SPIDER_SQL_HS_LTEQUAL_STR "<=" #define SPIDER_SQL_HS_LTEQUAL_STR "<="
#define SPIDER_SQL_HS_LTEQUAL_LEN (sizeof(SPIDER_SQL_HS_LTEQUAL_STR) - 1) #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_STR "case "
#define SPIDER_SQL_CASE_LEN (sizeof(SPIDER_SQL_CASE_STR) - 1) #define SPIDER_SQL_CASE_LEN (sizeof(SPIDER_SQL_CASE_STR) - 1)
#define SPIDER_SQL_WHEN_STR " when " #define SPIDER_SQL_WHEN_STR " when "
...@@ -117,7 +115,6 @@ typedef st_spider_result SPIDER_RESULT; ...@@ -117,7 +115,6 @@ typedef st_spider_result SPIDER_RESULT;
#define SPIDER_SQL_ELSE_LEN (sizeof(SPIDER_SQL_ELSE_STR) - 1) #define SPIDER_SQL_ELSE_LEN (sizeof(SPIDER_SQL_ELSE_STR) - 1)
#define SPIDER_SQL_END_STR " end" #define SPIDER_SQL_END_STR " end"
#define SPIDER_SQL_END_LEN (sizeof(SPIDER_SQL_END_STR) - 1) #define SPIDER_SQL_END_LEN (sizeof(SPIDER_SQL_END_STR) - 1)
#endif
#define SPIDER_SQL_USING_STR " using " #define SPIDER_SQL_USING_STR " using "
#define SPIDER_SQL_USING_LEN (sizeof(SPIDER_SQL_USING_STR) - 1) #define SPIDER_SQL_USING_LEN (sizeof(SPIDER_SQL_USING_STR) - 1)
......
...@@ -5547,10 +5547,6 @@ int spider_db_mbase_util::check_item_func( ...@@ -5547,10 +5547,6 @@ int spider_db_mbase_util::check_item_func(
switch (func_type) switch (func_type)
{ {
case Item_func::TRIG_COND_FUNC: 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); DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
case Item_func::NOT_FUNC: case Item_func::NOT_FUNC:
/* Why the following check is necessary? */ /* Why the following check is necessary? */
...@@ -5620,15 +5616,15 @@ int spider_db_mbase_util::print_item_func( ...@@ -5620,15 +5616,15 @@ int spider_db_mbase_util::print_item_func(
Item *item, **item_list = item_func->arguments(); Item *item, **item_list = item_func->arguments();
Field *field; Field *field;
spider_string tmp_str; 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, const char *func_name = SPIDER_SQL_NULL_CHAR_STR,
*separator_str = SPIDER_SQL_NULL_CHAR_STR, *separator_str = SPIDER_SQL_NULL_CHAR_STR,
*last_str = SPIDER_SQL_NULL_CHAR_STR; *last_str = SPIDER_SQL_NULL_CHAR_STR;
int func_name_length = SPIDER_SQL_NULL_CHAR_LEN, int func_name_length = SPIDER_SQL_NULL_CHAR_LEN,
separator_str_length = SPIDER_SQL_NULL_CHAR_LEN, separator_str_length = SPIDER_SQL_NULL_CHAR_LEN,
last_str_length = SPIDER_SQL_NULL_CHAR_LEN; last_str_length = SPIDER_SQL_NULL_CHAR_LEN;
int use_pushdown_udf; int use_pushdown_udf, case_when_start, case_when_count;
bool merge_func = FALSE; bool merge_func = FALSE, case_with_else;
DBUG_ENTER("spider_db_mbase_util::print_item_func"); DBUG_ENTER("spider_db_mbase_util::print_item_func");
DBUG_ASSERT(!check_item_func(item_func, spider, alias, alias_length, DBUG_ASSERT(!check_item_func(item_func, spider, alias, alias_length,
use_fields, fields)); use_fields, fields));
...@@ -6490,23 +6486,39 @@ int spider_db_mbase_util::print_item_func( ...@@ -6490,23 +6486,39 @@ int spider_db_mbase_util::print_item_func(
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
case Item_func::CASE_SEARCHED_FUNC: case Item_func::CASE_SEARCHED_FUNC:
case Item_func::CASE_SIMPLE_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)
{ {
if (str->reserve(SPIDER_SQL_CASE_LEN)) if (str->reserve(SPIDER_SQL_CASE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM); DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_CASE_STR, SPIDER_SQL_CASE_LEN); 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( 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))) alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num); DBUG_RETURN(error_num);
} }
for (roop_count = 0; roop_count < item_func_case->ncases; for (i = 0; i < (uint) case_when_count; i++)
roop_count += 2)
{ {
if (str) if (str)
{ {
...@@ -6515,7 +6527,7 @@ int spider_db_mbase_util::print_item_func( ...@@ -6515,7 +6527,7 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN); str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN);
} }
if ((error_num = spider_db_print_item_type( 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))) alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num); DBUG_RETURN(error_num);
if (str) if (str)
...@@ -6525,11 +6537,11 @@ int spider_db_mbase_util::print_item_func( ...@@ -6525,11 +6537,11 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN); str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN);
} }
if ((error_num = spider_db_print_item_type( 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))) alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num); DBUG_RETURN(error_num);
} }
if (item_func_case->else_expr_num != -1) if (case_with_else)
{ {
if (str) if (str)
{ {
...@@ -6538,7 +6550,7 @@ int spider_db_mbase_util::print_item_func( ...@@ -6538,7 +6550,7 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN); str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN);
} }
if ((error_num = spider_db_print_item_type( 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))) alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num); DBUG_RETURN(error_num);
} }
...@@ -6551,9 +6563,6 @@ int spider_db_mbase_util::print_item_func( ...@@ -6551,9 +6563,6 @@ int spider_db_mbase_util::print_item_func(
SPIDER_SQL_CLOSE_PAREN_LEN); SPIDER_SQL_CLOSE_PAREN_LEN);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
#else
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
#endif
case Item_func::JSON_EXTRACT_FUNC: case Item_func::JSON_EXTRACT_FUNC:
func_name = (char*) item_func->func_name(); func_name = (char*) item_func->func_name();
func_name_length = strlen(func_name); func_name_length = strlen(func_name);
...@@ -6607,13 +6616,13 @@ int spider_db_mbase_util::print_item_func( ...@@ -6607,13 +6616,13 @@ int spider_db_mbase_util::print_item_func(
Loop through the items of the current function expression to Loop through the items of the current function expression to
print its portion of the statement 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, if ((error_num = spider_db_print_item_type(item, field, spider, str,
alias, alias_length, dbton_id, use_fields, fields))) alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num); DBUG_RETURN(error_num);
if (roop_count == 1) if (i == 1)
{ {
/* Remaining operands need to be preceded by the separator */ /* Remaining operands need to be preceded by the separator */
func_name = separator_str; func_name = separator_str;
...@@ -6627,7 +6636,7 @@ int spider_db_mbase_util::print_item_func( ...@@ -6627,7 +6636,7 @@ int spider_db_mbase_util::print_item_func(
} }
/* Print the last operand value */ /* 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, if ((error_num = spider_db_print_item_type(item, field, spider, str,
alias, alias_length, dbton_id, use_fields, fields))) alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num); 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