MDEV-37202 spider sh: add support for single partition read

This commit is contained in:
Yuchen Pei
2025-07-18 18:02:03 +10:00
parent 5bd72e55f1
commit b8f975ece9
4 changed files with 115 additions and 16 deletions

View File

@ -77,6 +77,51 @@ c
5
6
drop table t1, t2, t3, t4;
# single partition
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p VALUES LESS THAN MAXVALUE REMOTE_TABLE=t2
);
insert into t1 values (1), (2), (3);
explain
select * from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
select * from t1;
c
1
2
3
drop table t1, t2;
# multiple partitions
create table t3 (c int);
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p1 VALUES LESS THAN (3) REMOTE_TABLE=t2,
PARTITION p2 VALUES LESS THAN MAXVALUE REMOTE_TABLE=t3
);
insert into t1 values (1), (2), (3);
## single read partition: sh
explain
select * from t1 partition (p2);
id select_type table type possible_keys key key_len ref rows Extra
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
select * from t1 partition (p2);
c
3
## single read partition after pruning: gbh (see also MDEV-20250)
explain
select * from t1 where c > 2;
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 * from t1 where c > 2;
c
3
drop table t1, t2, t3;
#
# MDEV-37110 Spider select handler: implement one that handles
# testcases showcasing problems with the gbh

View File

@ -48,6 +48,39 @@ explain select c from t1 union all select c from t3;
select c from t1 union all select c from t3;
drop table t1, t2, t3, t4;
--echo # single partition
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p VALUES LESS THAN MAXVALUE REMOTE_TABLE=t2
);
insert into t1 values (1), (2), (3);
explain
select * from t1;
select * from t1;
drop table t1, t2;
--echo # multiple partitions
create table t3 (c int);
create table t2 (c int);
create table t1 (c int) ENGINE=Spider
WRAPPER=mysql REMOTE_SERVER=srv
PARTITION BY RANGE (c) (
PARTITION p1 VALUES LESS THAN (3) REMOTE_TABLE=t2,
PARTITION p2 VALUES LESS THAN MAXVALUE REMOTE_TABLE=t3
);
insert into t1 values (1), (2), (3);
--echo ## single read partition: sh
explain
select * from t1 partition (p2);
select * from t1 partition (p2);
--echo ## single read partition after pruning: gbh (see also MDEV-20250)
explain
select * from t1 where c > 2;
select * from t1 where c > 2;
drop table t1, t2, t3;
--echo #
--echo # MDEV-37110 Spider select handler: implement one that handles
--echo # testcases showcasing problems with the gbh

View File

@ -180,8 +180,7 @@ count(0)
connection child2_1;
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %';
argument
select `id`,`hr_status`,`region_code`,`region` from `auto_test_remote`.`tbl_person` where `id` = '24FC3F0A5119432BAE13DD65AABAA39C' and `region` = 510411
select count(0) `count(0)` from (select 1) t0 join `auto_test_remote`.`tbl_ncd_cm_person` t1 where ((t1.`person_id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t1.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816'))
select count(0) `count(0)` from (`auto_test_remote`.`tbl_person` t0 join `auto_test_remote`.`tbl_ncd_cm_person` t1 on (t0.`id` = t1.`person_id`)) where ((1 = 1) and (t0.`hr_status` <> '99') and (t0.`hr_status` <> '2') and (t0.`region_code` like (convert((concat((concat(_latin1'%' , _latin1'51041110620301' , _latin1'%')))) using utf8mb3))) and (t0.`id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t1.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816') and (t0.`region` = 510411))
SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %'
SELECT * FROM tbl_person;
id hr_status region_code region

View File

@ -20,6 +20,8 @@
#include "partition_element.h"
/* for spider_set_result_list_param */
#include "spd_table.h"
#include "partition_info.h"
#include "ha_partition.h"
extern handlerton *spider_hton_ptr;
constexpr int LINK_IDX= 0;
@ -80,13 +82,28 @@ static bool spider_sh_can_handle_query(SELECT_LEX *select_lex,
return true;
}
/*
Get the spider handler from a table. If the table is partitioned,
get its first read partition handler.
*/
static ha_spider *spider_sh_get_spider(TABLE* table)
{
if (table->part_info)
{
uint part= bitmap_get_first_set(&table->part_info->read_partitions);
ha_partition *partition= (ha_partition *) table->file;
return (ha_spider *) partition->get_child_handlers()[part];
}
return (ha_spider *) table->file;
}
select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex,
SELECT_LEX_UNIT *)
{
SPIDER_TABLE_HOLDER *table_holder;
uint n_tables= 0;
spider_fields *fields;
ha_spider *spider;
ha_spider *spider, *first_spider;
TABLE_LIST *from= select_lex->get_table_list();
int dbton_id = -1;
SPIDER_CONN *common_conn= NULL;
@ -103,33 +120,38 @@ select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex,
return NULL;
for (TABLE_LIST *tl= from; tl; n_tables++, tl= tl->next_local)
{
TABLE *table= tl->table;
/* Do not support temporary tables */
if (!tl->table)
if (!table)
return NULL;
/* TODO: support partition table with one (read) partition */
if (tl->table->part_info)
/*
Do not support partitioned table with more than one (read)
partition
*/
if (table->part_info &&
bitmap_bits_set(&table->part_info->read_partitions) != 1)
return NULL;
/* One of the join tables is not a spider table */
if (tl->table->file->partition_ht() != spider_hton_ptr)
if (table->file->partition_ht() != spider_hton_ptr)
return NULL;
spider = (ha_spider *) tl->table->file;
spider= spider_sh_get_spider(table);
/* needed for table holder (see spider_add_table_holder()) */
spider->idx_for_direct_join = n_tables;
/* only create if all tables have common first backend. */
/* Only create if all tables have common first backend. */
uint all_link_idx= spider->conn_link_idx[LINK_IDX];
if (dbton_id == -1)
dbton_id= spider->share->use_sql_dbton_ids[0];
else if (dbton_id != (int) spider->share->use_sql_dbton_ids[0])
dbton_id= spider->share->use_sql_dbton_ids[all_link_idx];
else if (dbton_id != (int) spider->share->use_sql_dbton_ids[all_link_idx])
return NULL;
}
if (!spider_sh_can_handle_query(select_lex,
((ha_spider *) from->table->file)->share,
thd))
first_spider= spider_sh_get_spider(from->table);
if (!spider_sh_can_handle_query(select_lex, first_spider->share, thd))
return NULL;
if (!(table_holder= spider_create_table_holder(n_tables)))
return NULL;
for (TABLE_LIST *tl= from; tl; tl= tl->next_local)
{
spider = (ha_spider *) tl->table->file;
spider= spider_sh_get_spider(tl->table);
spider_add_table_holder(spider, table_holder);
/*
As in dml_init, wide_handler->lock_mode == -2 is a relic from
@ -183,7 +205,7 @@ select_handler *spider_create_select_handler(THD *thd, SELECT_LEX *select_lex,
spider_check_and_set_trx_isolation(
common_conn, &spider->need_mons[LINK_IDX])))
goto free_table_holder;
trx= ((ha_spider *) from->table->file)->wide_handler->trx;
trx= first_spider->wide_handler->trx;
if (!common_conn->join_trx && !trx->trx_xa)
{
/* So that spider executes queries that start a transaction. */