Commit 44c88fae authored by Yuchen Pei's avatar Yuchen Pei

MDEV-28992 Spider group by handler: Push down TIMESTAMPDIFF function

Also removed ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC.

Similar to pr#2225, with the testcase adapted from that patch:

--8<---------------cut here---------------start------------->8---
From 884f7c6df16236748ca975339e0b1c267e195309 Mon Sep 17 00:00:00 2001
From: "Norio Akagi (norakagi)" <norakagi@amazon.com>
Date: Wed, 3 Aug 2022 23:30:34 -0700
Subject: [PATCH] [MDEV-28992] Push down TIMESTAMP_DIFF in spider

This changes so that TIMESTAMP_DIFF function in a query is pushed down and works natively in Spider.
Instead of directly accessing item's member, now we can rely on a public accessor method to make it work.
Unit tests are added under spider.pushdown_timestamp_diff.

All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the
BSD-new license. I am contributing on behalf of my employer
Amazon Web Services, Inc.
--8<---------------cut here---------------end--------------->8---
parent 11fe2ee0
#
# MDEV-28992 Spider: Push down TIMESTAMPDIFF function
#
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 (
a INT,
b CHAR(1),
c DATETIME,
PRIMARY KEY(a)
);
CREATE TABLE t1 (
a INT,
b CHAR(1),
c DATETIME,
PRIMARY KEY(a)
) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
INSERT INTO t1 (a, b, c) VALUES
(1, 'a', '2018-11-01 10:21:39'),
(2, 'b', '2015-06-30 23:59:59'),
(3, 'c', '2013-11-01 01:01:01');
interval year
explain select a, b, timestampdiff(year, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(year, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(year, '2000-01-01 00:00:00', c)
1 a 18
2 b 15
3 c 13
interval quarter
explain select a, b, timestampdiff(quarter, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(quarter, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(quarter, '2000-01-01 00:00:00', c)
1 a 75
2 b 61
3 c 55
interval month
explain select a, b, timestampdiff(month, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(month, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(month, '2000-01-01 00:00:00', c)
1 a 226
2 b 185
3 c 166
interval week
explain select a, b, timestampdiff(week, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(week, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(week, '2000-01-01 00:00:00', c)
1 a 982
2 b 808
3 c 721
interval day
explain select a, b, timestampdiff(day, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(day, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(day, '2000-01-01 00:00:00', c)
1 a 6879
2 b 5659
3 c 5053
internal hour
explain select a, b, timestampdiff(hour, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(hour, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(hour, '2000-01-01 00:00:00', c)
1 a 165106
2 b 135839
3 c 121273
internal minute
explain select a, b, timestampdiff(minute, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(minute, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(minute, '2000-01-01 00:00:00', c)
1 a 9906381
2 b 8150399
3 c 7276381
internal second
explain select a, b, timestampdiff(second, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(second, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(second, '2000-01-01 00:00:00', c)
1 a 594382899
2 b 489023999
3 c 436582861
internal microsecond
explain select a, b, timestampdiff(microsecond, '2000-01-01 00:00:00', c) 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 a, b, timestampdiff(microsecond, '2000-01-01 00:00:00', c) from t1;
a b timestampdiff(microsecond, '2000-01-01 00:00:00', c)
1 a 594382899000000
2 b 489023999000000
3 c 436582861000000
drop table t1, t2;
drop server srv;
for master_1
for child2
for child3
--echo #
--echo # MDEV-28992 Spider: Push down TIMESTAMPDIFF function
--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 (
a INT,
b CHAR(1),
c DATETIME,
PRIMARY KEY(a)
);
CREATE TABLE t1 (
a INT,
b CHAR(1),
c DATETIME,
PRIMARY KEY(a)
) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
INSERT INTO t1 (a, b, c) VALUES
(1, 'a', '2018-11-01 10:21:39'),
(2, 'b', '2015-06-30 23:59:59'),
(3, 'c', '2013-11-01 01:01:01');
--echo interval year
let $query=
select a, b, timestampdiff(year, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo interval quarter
let $query=
select a, b, timestampdiff(quarter, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo interval month
let $query=
select a, b, timestampdiff(month, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo interval week
let $query=
select a, b, timestampdiff(week, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo interval day
let $query=
select a, b, timestampdiff(day, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo internal hour
let $query=
select a, b, timestampdiff(hour, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo internal minute
let $query=
select a, b, timestampdiff(minute, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo internal second
let $query=
select a, b, timestampdiff(second, '2000-01-01 00:00:00', c) from t1;
eval explain $query;
eval $query;
--echo internal microsecond
let $query=
select a, b, timestampdiff(microsecond, '2000-01-01 00:00:00', c) 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
......@@ -3178,14 +3178,13 @@ int spider_db_handlersocket_util::open_item_func(
alias, alias_length, dbton_id, use_fields, fields));
} else if (!strncasecmp("timestampdiff", func_name, func_name_length))
{
#ifdef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC
Item_func_timestamp_diff *item_func_timestamp_diff =
(Item_func_timestamp_diff *) item_func;
if (str)
{
const char *interval_str;
uint interval_len;
switch (item_func_timestamp_diff->int_type)
switch (item_func_timestamp_diff->get_int_type())
{
case INTERVAL_YEAR:
interval_str = SPIDER_SQL_YEAR_STR;
......@@ -3257,9 +3256,6 @@ int spider_db_handlersocket_util::open_item_func(
SPIDER_SQL_CLOSE_PAREN_LEN);
}
DBUG_RETURN(0);
#else
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
#endif
}
} else if (func_name_length == 14)
{
......
......@@ -5533,14 +5533,6 @@ int spider_db_mbase_util::open_item_func(
alias_length, use_fields, fields));
}
static bool item_func_is_timestampdiff(
const char *func_name,
int func_name_length
) {
return func_name_length == 13 &&
!strncasecmp("timestampdiff", func_name, func_name_length);
}
static bool not_func_should_be_skipped(
Item_func *item_func
){
......@@ -5610,10 +5602,6 @@ int spider_db_mbase_util::check_item_func(
Item_func::Functype func_type = item_func->functype();
DBUG_PRINT("info",("spider functype = %d", func_type));
const char *func_name = (char*) item_func->func_name();
int func_name_length = strlen(func_name);
DBUG_PRINT("info",("spider func_name = %s", func_name));
/* The blacklist of the functions that cannot be pushed down */
switch (func_type)
{
......@@ -5628,14 +5616,6 @@ int spider_db_mbase_util::check_item_func(
break;
case Item_func::FUNC_SP:
case Item_func::UDF_FUNC:
/* Notes on merging regarding MDEV-29447: please refer to the
following commits for build error or merge conflicts:
10.5: d7b564da2a634dcf86798d6b86bd127e7eef9286
10.6: 1ed20b993b0dd4e95450cab2e8347e5bf4617a69
10.9: dd316b6e20265cfd832bb5585cb4c96e716387c8
10.10-11: 3f67f110ba1b23a89c5ede0fbeeb203cf5e164f4
11.0-1: 17ba6748afa8834df5658361088e6c8e65aca16f
Please remove this comment after merging. */
use_pushdown_udf= spider_param_use_pushdown_udf(
spider->trx->thd, spider->share->use_pushdown_udf);
if (!use_pushdown_udf)
......@@ -5645,12 +5625,6 @@ int spider_db_mbase_util::check_item_func(
if (spider_db_check_ft_idx(item_func, spider) == MAX_KEY)
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
break;
#ifndef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC
case Item_func::UNKNOWN_FUNC:
if (item_func_is_timestampdiff(func_name, func_name_length))
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
break;
#endif
default:
break;
}
......@@ -6015,12 +5989,11 @@ int spider_db_mbase_util::print_item_func(
alias, alias_length, dbton_id, use_fields, fields));
} else if (!strncasecmp("timestampdiff", func_name, func_name_length))
{
#ifdef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC
Item_func_timestamp_diff *item_func_timestamp_diff =
(Item_func_timestamp_diff *) item_func;
const char *interval_str;
uint interval_len;
switch (item_func_timestamp_diff->int_type)
switch (item_func_timestamp_diff->get_int_type())
{
case INTERVAL_YEAR:
interval_str = SPIDER_SQL_YEAR_STR;
......@@ -6071,7 +6044,7 @@ int spider_db_mbase_util::print_item_func(
str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN);
str->q_append(interval_str, interval_len);
str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider,
str, alias, alias_length, dbton_id, use_fields, fields)))
DBUG_RETURN(error_num);
......@@ -6092,9 +6065,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
}
} else if (func_name_length == 14)
{
......
......@@ -3424,14 +3424,13 @@ int spider_db_oracle_util::open_item_func(
alias, alias_length, dbton_id, use_fields, fields));
} else if (!strncasecmp("timestampdiff", func_name, func_name_length))
{
#ifdef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC
Item_func_timestamp_diff *item_func_timestamp_diff =
(Item_func_timestamp_diff *) item_func;
if (str)
{
const char *interval_str;
uint interval_len;
switch (item_func_timestamp_diff->int_type)
switch (item_func_timestamp_diff->get_int_type())
{
case INTERVAL_YEAR:
interval_str = SPIDER_SQL_YEAR_STR;
......@@ -3503,9 +3502,6 @@ int spider_db_oracle_util::open_item_func(
SPIDER_SQL_CLOSE_PAREN_LEN);
}
DBUG_RETURN(0);
#else
DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
#endif
}
} else if (func_name_length == 14)
{
......
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