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.
This commit is contained in:
Yuchen Pei 2024-10-15 15:36:12 +11:00
parent e6daff40e4
commit 77ed235d50
No known key found for this signature in database
GPG key ID: 3DD1B35105743563
22 changed files with 286 additions and 109 deletions

View file

@ -53,6 +53,8 @@ class Select_limit_counters;
struct Query
{
List<Item> *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;

View file

@ -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};

View file

@ -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<Item> all_fields;

View file

@ -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;
}

View file

@ -910,6 +910,8 @@ public:
int append_lock_tables_list();
int lock_tables();
int dml_init();
private:
void init_fields();
};

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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')

View file

@ -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')

View file

@ -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')

View file

@ -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

View file

@ -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"));

View file

@ -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;

View file

@ -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<Item> 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);

View file

@ -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<Item> *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,

View file

@ -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);
}

View file

@ -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;