From 77ed235d50bd9b1480f26d18ea0b70ca7480af23 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 15 Oct 2024 15:36:12 +1100 Subject: [PATCH] MDEV-26345 Spider GBH should execute original queries on the data node Stop skipping const items when selecting but skip them when storing their results to spider row to avoid storing in mismatching temporary table fields. Skip auxiliary fields in SELECTing, and do not store the (non-existing) results to the corresponding temporary table accordingly. When there are BOTH auxiliary fields AND const items in the auxiliary field items, do not use the spider GBH. This is a rare occasion if it happens at all and not worth the added complexity to cover it. Use the original item (item_ptr) in constructing GROUP BY and ORDER BY, which also means using item->name instead of field->field_name as aliases in constructing SELECT items. This fixes spurious regressions caused by the above changes in some tests using ORDER BY, such as mdev_24517.test. As a by-product, this also fixes MDEV-29546. Therefore we update mdev_29008.test to include the MDEV-29546 case. --- sql/group_by_handler.h | 7 +- sql/sql_select.cc | 4 +- sql/sql_select.h | 2 +- storage/spider/ha_spider.cc | 78 ++++--------------- storage/spider/ha_spider.h | 2 + .../spider/bugfix/r/mdev_20502.result | 8 +- .../spider/bugfix/r/mdev_26345.result | 48 ++++++++++++ .../spider/bugfix/r/mdev_29008.result | 15 ++++ .../bugfix/r/select_with_backquote.result | 2 +- .../spider/bugfix/t/mdev_26345.test | 63 +++++++++++++++ .../spider/bugfix/t/mdev_29008.test | 13 ++++ .../mysql-test/spider/r/direct_join.result | 2 +- .../spider/r/direct_join_using.result | 2 +- .../spider/r/direct_left_join.result | 2 +- .../spider/r/direct_right_join.result | 2 +- .../mysql-test/spider/r/timestamp.result | 2 +- storage/spider/spd_db_conn.cc | 10 ++- storage/spider/spd_db_include.h | 13 +++- storage/spider/spd_db_mysql.cc | 55 ++++++++----- storage/spider/spd_db_mysql.h | 8 +- storage/spider/spd_group_by_handler.cc | 47 +++++++++-- storage/spider/spd_group_by_handler.h | 10 ++- 22 files changed, 286 insertions(+), 109 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_26345.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_26345.test diff --git a/sql/group_by_handler.h b/sql/group_by_handler.h index 5457cb778f5..2a51956f3c1 100644 --- a/sql/group_by_handler.h +++ b/sql/group_by_handler.h @@ -53,6 +53,8 @@ class Select_limit_counters; struct Query { List *select; + /* Number of auxiliary fields. */ + int n_aux; bool distinct; TABLE_LIST *from; Item *where; @@ -71,7 +73,10 @@ public: /* Temporary table where all results should be stored in record[0] - The table has a field for every item from the Query::select list. + The table has a field for every item from the Query::select list, + except for const items and some other exceptions, see + Create_tmp_table::add_fields() for which items are included and + which are skipped. */ TABLE *table; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fcc1e4dbfea..37ec152141c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3400,7 +3400,9 @@ bool JOIN::make_aggr_tables_info() original DISTINCT. Thus, we set select_distinct || group_optimized_away to Query::distinct. */ - Query query= {&all_fields, select_distinct || group_optimized_away, + Query query= {&all_fields, + (int) all_fields.elements - (int) fields_list.elements, + select_distinct || group_optimized_away, tables_list, conds, group_list, order ? order : group_list, having, &select_lex->master_unit()->lim}; diff --git a/sql/sql_select.h b/sql/sql_select.h index 49632077ed8..86947fc0bc6 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1473,7 +1473,7 @@ public: Then, ORDER/GROUP BY and Window Function code add columns that need to be saved to be available in the post-group-by context. These extra columns - are added to the front, because this->all_fields points to the suffix of + are added to the front, because this->fields_list points to the suffix of this list. */ List all_fields; diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 25967862c4e..8aff2858c3a 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -52,13 +52,9 @@ extern pthread_mutex_t spider_lgtm_tblhnd_share_mutex; /* UTC time zone for timestamp columns */ extern Time_zone *UTC; -ha_spider::ha_spider( -) : handler(spider_hton_ptr, NULL) +void ha_spider::init_fields() { - DBUG_ENTER("ha_spider::ha_spider"); - DBUG_PRINT("info",("spider this=%p", this)); - spider_alloc_calc_mem_init(mem_calc, SPD_MID_HA_SPIDER_HA_SPIDER_1); - spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); + DBUG_ENTER("ha_spider::init_fields"); share = NULL; conns = NULL; need_mons = NULL; @@ -113,6 +109,20 @@ ha_spider::ha_spider( result_list.casual_read = NULL; result_list.use_both_key = FALSE; result_list.in_cmp_ref = FALSE; + result_list.skips= NULL; + result_list.n_aux= 0; + ref_length = sizeof(SPIDER_POSITION); + DBUG_VOID_RETURN; +} + +ha_spider::ha_spider( +) : handler(spider_hton_ptr, NULL) +{ + DBUG_ENTER("ha_spider::ha_spider"); + DBUG_PRINT("info",("spider this=%p", this)); + spider_alloc_calc_mem_init(mem_calc, SPD_MID_HA_SPIDER_HA_SPIDER_1); + spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); + init_fields(); DBUG_VOID_RETURN; } @@ -125,61 +135,7 @@ ha_spider::ha_spider( DBUG_PRINT("info",("spider this=%p", this)); spider_alloc_calc_mem_init(mem_calc, SPD_MID_HA_SPIDER_HA_SPIDER_2); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); - share = NULL; - conns = NULL; - need_mons = NULL; - blob_buff = NULL; - conn_keys = NULL; - spider_thread_id = 0; - trx_conn_adjustment = 0; - search_link_query_id = 0; -#ifdef WITH_PARTITION_STORAGE_ENGINE - partition_handler = NULL; -#endif -#ifdef HA_MRR_USE_DEFAULT_IMPL - multi_range_keys = NULL; - mrr_key_buff = NULL; -#endif - append_tblnm_alias = NULL; - use_index_merge = FALSE; - is_clone = FALSE; - pt_clone_source_handler = NULL; - pt_clone_last_searcher = NULL; - ft_handler = NULL; - ft_first = NULL; - ft_current = NULL; - ft_count = 0; - ft_init_without_index_init = FALSE; - sql_kinds = 0; - error_mode = 0; - use_spatial_index = FALSE; - use_fields = FALSE; - dml_inited = FALSE; - use_pre_call = FALSE; - use_pre_action = FALSE; - do_direct_update = FALSE; - prev_index_rnd_init = SPD_NONE; - direct_aggregate_item_first = NULL; - result_link_idx = 0; - result_list.have_sql_kind_backup = FALSE; - result_list.sqls = NULL; - result_list.insert_sqls = NULL; - result_list.update_sqls = NULL; - result_list.tmp_sqls = NULL; - result_list.tmp_tables_created = FALSE; - result_list.bgs_working = FALSE; - result_list.direct_order_limit = FALSE; - result_list.direct_limit_offset = FALSE; - result_list.set_split_read = FALSE; - result_list.insert_dup_update_pushdown = FALSE; - result_list.tmp_pos_row_first = NULL; - result_list.direct_aggregate = FALSE; - result_list.snap_direct_aggregate = FALSE; - result_list.direct_distinct = FALSE; - result_list.casual_read = NULL; - result_list.use_both_key = FALSE; - result_list.in_cmp_ref = FALSE; - ref_length = sizeof(SPIDER_POSITION); + init_fields(); DBUG_VOID_RETURN; } diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 6d2e0e40c57..34fad7eee96 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -910,6 +910,8 @@ public: int append_lock_tables_list(); int lock_tables(); int dml_init(); +private: + void init_fields(); }; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result index e5f16b81329..beea6837bd9 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_20502.result @@ -54,13 +54,13 @@ m const val sq connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`id` `id`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 -select t0.`id` `id`,t0.`val` `val`,(t0.`val` + 10) `val+10` from `auto_test_remote`.`tbl_a` t0 +select t0.`id` `id`,0 `const`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 +select `id`,`val` from `auto_test_remote`.`tbl_a` select (t0.`val` + 1) `tbl_a.val+1` from `auto_test_remote`.`tbl_a` t0 select `id`,`val` from `auto_test_remote`.`tbl_a` order by `id` desc limit 1 for update -select (t0.`val` + 10) `val+10`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 group by t0.`val` order by t0.`val` +select `val` from `auto_test_remote`.`tbl_a` group by `val` select (t0.`val` + 1) `tbl_a.val+1` from `auto_test_remote`.`tbl_a` t0 limit 1 -select max(t0.`id`) `m`,t0.`val` `val` from `auto_test_remote`.`tbl_a` t0 group by t0.`val` order by t0.`val` +select max(`id`),min(`id`),`val` from `auto_test_remote`.`tbl_a` group by `val` select (t0.`val` + 1) `tbl_a.val+1` from `auto_test_remote`.`tbl_a` t0 limit 1 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT id, val FROM tbl_a ORDER BY id; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26345.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26345.result new file mode 100644 index 00000000000..f7d78521472 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26345.result @@ -0,0 +1,48 @@ +for master_1 +for child2 +for child3 + +MDEV-26345 SELECT MIN on Spider table returns more rows than expected + +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 int, PRIMARY KEY (a, b)); +create table t1 (a int, b int, PRIMARY KEY (a, b)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 VALUES (1,4), (1,2), (2,11); +SELECT MIN(b), a FROM t1 WHERE a=1; +MIN(b) a +2 1 +SELECT MAX(b), a FROM t1 WHERE a<3; +MAX(b) a +11 1 +drop table t1, t2; +create table t2 (a int, b int, c int, PRIMARY KEY (a, b)); +create table t1 (a int, b int, c int, PRIMARY KEY (a, b)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t2 VALUES (1,4,1), (1,2,2), (2,11,3); +SELECT MIN(b), a, c FROM t1 WHERE a=1; +MIN(b) a c +2 1 2 +drop table t1, t2; +create table t2 (a int, b int); +create table t1 ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 VALUES (1,1), (1,1), (2,2), (2,2); +select distinct count(a) from t1 group by b; +count(a) +2 +drop table t1, t2; +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values (1),(3),(5),(7),(9),(11),(13),(15); +select count(c) as d from t1 having d > 5; +d +8 +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29008.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29008.result index 66e33f42a7e..10bf1cc1d9c 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29008.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29008.result @@ -15,6 +15,10 @@ a INT, b INT ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO tbl_a VALUES (1,2),(3,4); +set @old_general_log=@@global.general_log; +set global general_log=1; +set @old_log_output=@@global.log_output; +set global log_output="TABLE"; connection master_1; CREATE DATABASE auto_test_local; USE auto_test_local; @@ -26,9 +30,20 @@ SELECT MIN(t2.a) AS f1, t1.b AS f2 FROM tbl_a AS t1 JOIN tbl_a AS t2 GROUP BY f2 f1 f2 1 2 1 4 +SELECT MIN(t2.a) AS f1, t1.b AS f2 FROM tbl_a AS t1 JOIN tbl_a AS t2 GROUP BY f2 ORDER BY MIN(t2.a), MAX(t2.a), f2; +f1 f2 +1 2 +1 4 connection master_1; DROP DATABASE IF EXISTS auto_test_local; connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %'; +argument +select min(t1.`a`) `f1`,t0.`b` `f2` from `auto_test_remote`.`tbl_a` t0 join `auto_test_remote`.`tbl_a` t1 group by `f2` order by `f1`,`f2` +select min(t1.`a`) `f1`,t0.`b` `f2` from `auto_test_remote`.`tbl_a` t0 join `auto_test_remote`.`tbl_a` t1 group by `f2` order by min(t1.`a`),max(t1.`a`),`f2` +SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %' +set global log_output=@old_log_output; +set global general_log=@old_general_log; DROP DATABASE IF EXISTS auto_test_remote; for master_1 for child2 diff --git a/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result b/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result index 52f8c98bf98..732446f9fb1 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result +++ b/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result @@ -44,7 +44,7 @@ connection child2_1; SET NAMES utf8; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`pkey` `pkey`,(left(t0.`txt_utf8` , 4)) `LEFT(``txt_utf8``, 4)` from `auto_test_remote`.`tbl_a` t0 order by `LEFT(``txt_utf8``, 4)` limit 3 +select t0.`pkey` `pkey`,(left(t0.`txt_utf8` , 4)) `LEFT(``txt_utf8``, 4)` from `auto_test_remote`.`tbl_a` t0 order by (left(`txt_utf8` , 4)) limit 3 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT pkey, txt_utf8 FROM tbl_a ORDER BY pkey; pkey txt_utf8 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26345.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26345.test new file mode 100644 index 00000000000..72069253e84 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26345.test @@ -0,0 +1,63 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings + +--echo +--echo MDEV-26345 SELECT MIN on Spider table returns more rows than expected +--echo + +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +# Case 1: implicit grouping: the const item is SELECTed, but its +# results discarded when storing to the temp table +create table t2 (a int, b int, PRIMARY KEY (a, b)); +create table t1 (a int, b int, PRIMARY KEY (a, b)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 VALUES (1,4), (1,2), (2,11); +SELECT MIN(b), a FROM t1 WHERE a=1; +SELECT MAX(b), a FROM t1 WHERE a<3; +drop table t1, t2; + +# Case 2: implicit grouping: the const item is SELECTed, but its +# results discarded when storing to the temp table +create table t2 (a int, b int, c int, PRIMARY KEY (a, b)); +create table t1 (a int, b int, c int, PRIMARY KEY (a, b)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t2 VALUES (1,4,1), (1,2,2), (2,11,3); +SELECT MIN(b), a, c FROM t1 WHERE a=1; +drop table t1, t2; + +# Case 3: auxiliary fields should not be SELECTed +create table t2 (a int, b int); +create table t1 ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 VALUES (1,1), (1,1), (2,2), (2,2); +# b is an auxiliary field item. If it was SELECTed, two rows would +# return instead of one. +select distinct count(a) from t1 group by b; +drop table t1, t2; + +# Case 4: having should still work, despite referring to auxiliary +# field items which are not SELECTed +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values (1),(3),(5),(7),(9),(11),(13),(15); +select count(c) as d from t1 having d > 5; +drop table t1, t2; + +drop server srv; + +--disable_warnings +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29008.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29008.test index 28d9a9244e3..f36855d8e71 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29008.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29008.test @@ -17,6 +17,11 @@ eval CREATE TABLE tbl_a ( ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; INSERT INTO tbl_a VALUES (1,2),(3,4); +set @old_general_log=@@global.general_log; +set global general_log=1; +set @old_log_output=@@global.log_output; +set global log_output="TABLE"; + --connection master_1 CREATE DATABASE auto_test_local; USE auto_test_local; @@ -25,11 +30,19 @@ eval CREATE TABLE tbl_a ( b INT ) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a", srv "s_2_1"'; +--disable_ps2_protocol SELECT MIN(t2.a) AS f1, t1.b AS f2 FROM tbl_a AS t1 JOIN tbl_a AS t2 GROUP BY f2 ORDER BY f1, f2; +SELECT MIN(t2.a) AS f1, t1.b AS f2 FROM tbl_a AS t1 JOIN tbl_a AS t2 GROUP BY f2 ORDER BY MIN(t2.a), MAX(t2.a), f2; +--enable_ps2_protocol --connection master_1 DROP DATABASE IF EXISTS auto_test_local; --connection child2_1 +--disable_ps2_protocol +SELECT argument FROM mysql.general_log WHERE argument LIKE 'select %'; +--enable_ps2_protocol +set global log_output=@old_log_output; +set global general_log=@old_general_log; DROP DATABASE IF EXISTS auto_test_remote; --disable_query_log diff --git a/storage/spider/mysql-test/spider/r/direct_join.result b/storage/spider/mysql-test/spider/r/direct_join.result index 5c0f4c808a0..b5511cb8c9c 100644 --- a/storage/spider/mysql-test/spider/r/direct_join.result +++ b/storage/spider/mysql-test/spider/r/direct_join.result @@ -76,7 +76,7 @@ a b c connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r_int` t2 where ((t0.`a` = t1.`a`) and (t2.`a` = t1.`a`)) order by t0.`b` desc limit 1,2 +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r_int` t2 where ((t0.`a` = t1.`a`) and (t2.`a` = t1.`a`)) order by t0.`b` desc limit 1,2 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_join_using.result b/storage/spider/mysql-test/spider/r/direct_join_using.result index 93df7b8cd3f..1a4708a739b 100644 --- a/storage/spider/mysql-test/spider/r/direct_join_using.result +++ b/storage/spider/mysql-test/spider/r/direct_join_using.result @@ -79,7 +79,7 @@ a b c connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r_int` t2 where ((t0.`a` = t1.`a`) and (t2.`a` = t1.`a`)) order by t0.`b` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r_int` t2 where ((t0.`a` = t1.`a`) and (t2.`a` = t1.`a`)) order by t0.`b` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_left_join.result b/storage/spider/mysql-test/spider/r/direct_left_join.result index b63f0661b2e..b2149436e03 100644 --- a/storage/spider/mysql-test/spider/r/direct_left_join.result +++ b/storage/spider/mysql-test/spider/r/direct_left_join.result @@ -79,7 +79,7 @@ a b c connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 left join `auto_test_remote`.`ta_r_3` t1 on (t1.`a` = t0.`a`) left join `auto_test_remote`.`ta_r_int` t2 on (t2.`a` = t0.`a`) where 1 order by t0.`b` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 left join `auto_test_remote`.`ta_r_3` t1 on (t1.`a` = t0.`a`) left join `auto_test_remote`.`ta_r_int` t2 on (t2.`a` = t0.`a`) where 1 order by t0.`b` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/direct_right_join.result b/storage/spider/mysql-test/spider/r/direct_right_join.result index b42e40031e3..5504c4b557a 100644 --- a/storage/spider/mysql-test/spider/r/direct_right_join.result +++ b/storage/spider/mysql-test/spider/r/direct_right_join.result @@ -79,7 +79,7 @@ a b c connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; argument -select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r_int` t2 left join (`auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t0.`a` = t2.`a`) and (t1.`a` = t2.`a`)) where 1 order by t0.`b` desc +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r_int` t2 left join (`auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t0.`a` = t2.`a`) and (t1.`a` = t2.`a`)) where 1 order by t0.`b` desc SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; a b date_format(c, '%Y-%m-%d %H:%i:%s') diff --git a/storage/spider/mysql-test/spider/r/timestamp.result b/storage/spider/mysql-test/spider/r/timestamp.result index 20e99dc02f8..c7a2a3ebe86 100644 --- a/storage/spider/mysql-test/spider/r/timestamp.result +++ b/storage/spider/mysql-test/spider/r/timestamp.result @@ -396,7 +396,7 @@ select t0.`col_d` `col_d`,t0.`col_t` `col_t` from `ts_test_remote`.`tbl_f` t0 select (timestamp(t0.`col_d` , t0.`col_t`)) `TIMESTAMP(col_d, col_t)` from `ts_test_remote`.`tbl_f` t0 select (timestamp('2018-06-25' , t0.`col_t`)) `TIMESTAMP('2018-06-25', col_t)` from `ts_test_remote`.`tbl_f` t0 select (timestamp(t0.`col_d` , '10:43:21')) `TIMESTAMP(col_d, '10:43:21')` from `ts_test_remote`.`tbl_f` t0 -select 1 from `ts_test_remote`.`tbl_f` t0 +select (timestamp('2018-06-25' , '10:43:21')) `TIMESTAMP('2018-06-25', '10:43:21')` from `ts_test_remote`.`tbl_f` t0 SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' SELECT col_d, col_t FROM tbl_f; col_d col_t diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 0d0f1bb2e08..72489a1777e 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -2827,6 +2827,7 @@ int spider_db_get_row_from_tmp_tbl_pos( DBUG_RETURN(0); } +/* Store one field result from a given row to a given table field. */ int spider_db_fetch_row( SPIDER_SHARE *share, Field *field, @@ -2851,6 +2852,10 @@ int spider_db_fetch_row( DBUG_RETURN(error_num); } +/* + Retrieve a result row and store the results from the row into the + given table +*/ int spider_db_fetch_table( ha_spider *spider, uchar *buf, @@ -2863,6 +2868,7 @@ int spider_db_fetch_table( SPIDER_RESULT *current = (SPIDER_RESULT*) result_list->current; SPIDER_DB_ROW *row; Field **field; + int n_aux= result_list->n_aux; DBUG_ENTER("spider_db_fetch_table"); if (result_list->quick_mode == 0) { @@ -2940,6 +2946,8 @@ int spider_db_fetch_table( *field; field++ ) { + if (n_aux-- > 0) + continue; if (( bitmap_is_set(table->read_set, (*field)->field_index) | bitmap_is_set(table->write_set, (*field)->field_index) @@ -3788,7 +3796,7 @@ int spider_db_store_result( } current->dbton_id = current->result->dbton_id; SPIDER_DB_ROW *row; - if (!(row = current->result->fetch_row())) + if (!(row = current->result->fetch_row(result_list->skips))) { error_num = current->result->get_errno(); DBUG_PRINT("info",("spider set finish_flg point 3")); diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index eb7875ac056..430cd8479be 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -801,6 +801,7 @@ public: SPIDER_DB_ROW *next_pos; spider_db_row(uint in_dbton_id) : dbton_id(in_dbton_id), next_pos(NULL) {} virtual ~spider_db_row() = default; + /* Store the current field result to a given field */ virtual int store_to_field( Field *field, CHARSET_INFO *access_charset @@ -813,6 +814,7 @@ public: uint dbton_id ) = 0; virtual void first() = 0; + /* Move to the next field result. */ virtual void next() = 0; virtual bool is_null() = 0; virtual int val_int() = 0; @@ -851,7 +853,7 @@ public: virtual bool has_result() = 0; virtual void free_result() = 0; virtual SPIDER_DB_ROW *current_row() = 0; - virtual SPIDER_DB_ROW *fetch_row() = 0; + virtual SPIDER_DB_ROW *fetch_row(MY_BITMAP *skips = NULL) = 0; virtual SPIDER_DB_ROW *fetch_row_from_result_buffer( spider_db_result_buffer *spider_res_buf ) = 0; @@ -1549,7 +1551,8 @@ public: uint alias_length, bool use_fields, spider_fields *fields, - ulong sql_type + ulong sql_type, + int n_aux=0 ) = 0; virtual int append_group_by_part( ORDER *order, @@ -1838,4 +1841,10 @@ typedef struct st_spider_result_list #endif SPIDER_RESULT *bgs_current; SPIDER_DB_ROW *tmp_pos_row_first; + /* + A bitmap marking fields to skip when storing results fetched from + the data node to a SPIDER_DB_ROW + */ + MY_BITMAP *skips; + int n_aux; } SPIDER_RESULT_LIST; diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 7e10b796f25..92885783daf 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -716,7 +716,13 @@ SPIDER_DB_ROW *spider_db_mbase_result::current_row() DBUG_RETURN((SPIDER_DB_ROW *) row.clone()); } -SPIDER_DB_ROW *spider_db_mbase_result::fetch_row() +/* + Fetch results from the data node and store them in a + SPIDER_DB_ROW + + @param skips A bitmap specifying which fields to skip storing +*/ +SPIDER_DB_ROW *spider_db_mbase_result::fetch_row(MY_BITMAP *skips) { DBUG_ENTER("spider_db_mbase_result::fetch_row"); DBUG_PRINT("info",("spider this=%p", this)); @@ -732,7 +738,22 @@ SPIDER_DB_ROW *spider_db_mbase_result::fetch_row() DBUG_RETURN(NULL); } row.lengths = mysql_fetch_lengths(db_result); - row.field_count = mysql_num_fields(db_result); + if (skips != NULL) + { + uint i= 0; + for (uint j= 0; j < mysql_num_fields(db_result); j++) + { + if (!bitmap_is_set(skips, j)) + { + row.row[i]= row.row[j]; + row.lengths[i]= row.lengths[j]; + i++; + } + } + row.field_count= i; + } + else + row.field_count = mysql_num_fields(db_result); row.row[row.field_count] = NULL; row.row_first = row.row; row.lengths_first = row.lengths; @@ -13944,7 +13965,8 @@ int spider_mbase_handler::append_list_item_select_part( uint alias_length, bool use_fields, spider_fields *fields, - ulong sql_type + ulong sql_type, + int n_aux ) { int error_num; spider_string *str; @@ -13959,7 +13981,7 @@ int spider_mbase_handler::append_list_item_select_part( DBUG_RETURN(0); } error_num = append_list_item_select(select, str, alias, alias_length, - use_fields, fields); + use_fields, fields, n_aux); DBUG_RETURN(error_num); } @@ -13969,38 +13991,29 @@ int spider_mbase_handler::append_list_item_select( const char *alias, uint alias_length, bool use_fields, - spider_fields *fields + spider_fields *fields, + int n_aux ) { int error_num; uint32 length, begin; List_iterator_fast it(*select); Item *item; - Field *field; const char *item_name; DBUG_ENTER("spider_mbase_handler::append_list_item_select"); DBUG_PRINT("info",("spider this=%p", this)); begin = str->length(); while ((item = it++)) { - if (item->const_item()) - { - DBUG_PRINT("info",("spider const item")); + fields->get_next_field_ptr(); + if (n_aux-- > 0) continue; - } if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } - field = *(fields->get_next_field_ptr()); - if (field) - { - item_name = SPIDER_field_name_str(field); - length = SPIDER_field_name_length(field); - } else { - item_name = SPIDER_item_name_str(item); - length = SPIDER_item_name_length(item); - } + item_name = SPIDER_item_name_str(item); + length = SPIDER_item_name_length(item); if (str->reserve( SPIDER_SQL_COMMA_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_SPACE_LEN + length @@ -14071,7 +14084,7 @@ int spider_mbase_handler::append_group_by( str->q_append(SPIDER_SQL_GROUP_STR, SPIDER_SQL_GROUP_LEN); for (; order; order = order->next) { - if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, + if ((error_num = spider_db_print_item_type(order->item_ptr, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); @@ -14128,7 +14141,7 @@ int spider_mbase_handler::append_order_by( str->q_append(SPIDER_SQL_ORDER_STR, SPIDER_SQL_ORDER_LEN); for (; order; order = order->next) { - if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, + if ((error_num = spider_db_print_item_type(order->item_ptr, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 028a69e843b..ac00217ff4c 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -294,7 +294,7 @@ public: bool has_result() override; void free_result() override; SPIDER_DB_ROW *current_row() override; - SPIDER_DB_ROW *fetch_row() override; + SPIDER_DB_ROW *fetch_row(MY_BITMAP *) override; SPIDER_DB_ROW *fetch_row_from_result_buffer( spider_db_result_buffer *spider_res_buf ) override; @@ -1493,7 +1493,8 @@ public: uint alias_length, bool use_fields, spider_fields *fields, - ulong sql_type + ulong sql_type, + int n_aux=0 ) override; int append_list_item_select( List *select, @@ -1501,7 +1502,8 @@ public: const char *alias, uint alias_length, bool use_fields, - spider_fields *fields + spider_fields *fields, + int n_aux ); int append_group_by_part( ORDER *order, diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index 2e4eb003371..f5889edc59e 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -978,13 +978,16 @@ int spider_fields::ping_table_mon_from_table( spider_group_by_handler::spider_group_by_handler( THD *thd_arg, Query *query_arg, - spider_fields *fields_arg + spider_fields *fields_arg, + const MY_BITMAP &skips1 ) : group_by_handler(thd_arg, spider_hton_ptr), query(*query_arg), fields(fields_arg) { DBUG_ENTER("spider_group_by_handler::spider_group_by_handler"); spider = fields->get_first_table_holder()->spider; trx = spider->wide_handler->trx; + my_bitmap_init(&skips, NULL, skips1.n_bits, TRUE); + bitmap_copy(&skips, &skips1); DBUG_VOID_RETURN; } @@ -993,11 +996,18 @@ spider_group_by_handler::~spider_group_by_handler() DBUG_ENTER("spider_group_by_handler::~spider_group_by_handler"); spider_free(spider_current_trx, fields->get_first_table_holder(), MYF(0)); delete fields; + my_bitmap_free(&skips); + /* + The `skips' bitmap may have been copied to the result_list field + of the same name + */ + spider->result_list.skips= NULL; + spider->result_list.n_aux= 0; DBUG_VOID_RETURN; } static int spider_prepare_init_scan( - const Query& query, spider_fields *fields, ha_spider *spider, + const Query& query, MY_BITMAP *skips, spider_fields *fields, ha_spider *spider, SPIDER_TRX *trx, longlong& offset_limit, THD *thd) { int error_num, link_idx; @@ -1072,6 +1082,8 @@ static int spider_prepare_init_scan( result_list->limit_num = result_list->internal_limit >= result_list->split_read ? result_list->split_read : result_list->internal_limit; + result_list->skips= skips; + result_list->n_aux= query.n_aux; if (select_lex->explicit_limit) { @@ -1101,7 +1113,8 @@ static int spider_make_query(const Query& query, spider_fields* fields, ha_spide DBUG_RETURN(error_num); fields->set_field_ptr(table->field); if ((error_num = dbton_hdl->append_list_item_select_part( - query.select, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL))) + query.select, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL, + query.n_aux))) DBUG_RETURN(error_num); if ((error_num = dbton_hdl->append_from_and_tables_part( fields, SPIDER_SQL_TYPE_SELECT_SQL))) @@ -1276,7 +1289,7 @@ int spider_group_by_handler::init_scan() } if ((error_num = spider_prepare_init_scan( - query, fields, spider, trx, offset_limit, thd))) + query, &skips, fields, spider, trx, offset_limit, thd))) DBUG_RETURN(error_num); if ((error_num = spider_make_query(query, fields, spider, table))) @@ -1397,6 +1410,7 @@ group_by_handler *spider_create_group_by_handler( SPIDER_TABLE_HOLDER *table_holder; uint table_idx, dbton_id, table_count= 0; long tgt_link_status; + MY_BITMAP skips; DBUG_ENTER("spider_create_group_by_handler"); switch (thd_sql_command(thd)) @@ -1543,13 +1557,30 @@ group_by_handler *spider_create_group_by_handler( fields_arg->set_table_holder(table_holder, table_count); keep_going = TRUE; it.init(*query->select); + my_bitmap_init(&skips, NULL, query->select->elements, TRUE); + int i= -1, n_aux= query->n_aux; while ((item = it++)) { + i++; + n_aux--; DBUG_PRINT("info",("spider select item=%p", item)); if (item->const_item()) { - DBUG_PRINT("info",("spider const item")); - continue; + /* + Do not handle the complex case where there's a const item + in the auxiliary fields. It is too unlikely (if at all) to + happen to be covered by the GBH. + + TODO: find an example covering this case or determine it + never happens and remove this consideration. + */ + if (n_aux >= 0) + { + spider_clear_bit(dbton_bitmap, roop_count); + keep_going= FALSE; + break; + } + bitmap_set_bit(&skips, i); } if (spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0, roop_count, TRUE, fields_arg)) @@ -1823,11 +1854,12 @@ group_by_handler *spider_create_group_by_handler( fields->set_first_link_idx(); - if (!(group_by_handler = new spider_group_by_handler(thd, query, fields))) + if (!(group_by_handler = new spider_group_by_handler(thd, query, fields, skips))) { DBUG_PRINT("info",("spider can't create group_by_handler")); goto skip_free_fields; } + my_bitmap_free(&skips); query->distinct = FALSE; query->where = NULL; query->group_by = NULL; @@ -1839,5 +1871,6 @@ skip_free_fields: delete fields; skip_free_table_holder: spider_free(spider_current_trx, table_holder, MYF(0)); + my_bitmap_free(&skips); DBUG_RETURN(NULL); } diff --git a/storage/spider/spd_group_by_handler.h b/storage/spider/spd_group_by_handler.h index db100de92f2..0583229d4d7 100644 --- a/storage/spider/spd_group_by_handler.h +++ b/storage/spider/spd_group_by_handler.h @@ -23,12 +23,20 @@ class spider_group_by_handler: public group_by_handler bool first; longlong offset_limit; int store_error; + /* + Bitmap marking constant items among the select items. They are + SELECTed in the query executed at the data node, but not stored in + SPIDER_DB_ROW, because the temp table do not contain the + corresponding fields. + */ + MY_BITMAP skips; public: spider_group_by_handler( THD *thd_arg, Query *query_arg, - spider_fields *fields_arg + spider_fields *fields_arg, + const MY_BITMAP &skips1 ); ~spider_group_by_handler(); int init_scan() override;