Skip to content

Commit

Permalink
MDEV-28993 Spider: Push down CASE statement
Browse files Browse the repository at this point in the history
  • Loading branch information
mariadb-YuchenPei committed Apr 14, 2024
1 parent 99dc0f0 commit 18b93d6
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 30 deletions.
6 changes: 3 additions & 3 deletions storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
57 changes: 57 additions & 0 deletions storage/spider/mysql-test/spider/feature/r/pushdown_case.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#
# 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
#
50 changes: 50 additions & 0 deletions storage/spider/mysql-test/spider/feature/t/pushdown_case.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
--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 #
3 changes: 0 additions & 3 deletions storage/spider/spd_db_include.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

#define PLUGIN_VAR_CAN_MEMALLOC
/*
#define ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC
#define HASH_UPDATE_WITH_HASH_VALUE
*/

Expand Down Expand Up @@ -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 "
Expand All @@ -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)
Expand Down
57 changes: 33 additions & 24 deletions storage/spider/spd_db_mysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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? */
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
Expand All @@ -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)
{
Expand All @@ -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);
}
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down

0 comments on commit 18b93d6

Please sign in to comment.