diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 759404bbaaf..bbb7434825b 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -14001,6 +14001,7 @@ void ha_spider::sync_from_clone_source_base( dbton_hdl = dbton_handler[dbton_id]; dbton_hdl2 = spider->dbton_handler[dbton_id]; dbton_hdl->first_link_idx = dbton_hdl2->first_link_idx; + dbton_hdl->strict_group_by = dbton_hdl2->strict_group_by; } DBUG_VOID_RETURN; } @@ -14016,6 +14017,7 @@ void ha_spider::set_first_link_idx() dbton_id = share->use_dbton_ids[roop_count2]; dbton_hdl = dbton_handler[dbton_id]; dbton_hdl->first_link_idx = -1; + dbton_hdl->strict_group_by = FALSE; } for ( roop_count = spider_conn_link_idx_next(share->link_statuses, @@ -14034,6 +14036,10 @@ void ha_spider::set_first_link_idx() { dbton_hdl->first_link_idx = roop_count; } + if (share->strict_group_bys[all_link_idx]) + { + dbton_hdl->strict_group_by = TRUE; + } } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) dbton_id = share->hs_dbton_ids[all_link_idx]; @@ -14044,6 +14050,10 @@ void ha_spider::set_first_link_idx() { dbton_hdl->first_link_idx = roop_count; } + if (share->strict_group_bys[all_link_idx]) + { + dbton_hdl->strict_group_by = TRUE; + } } #endif } diff --git a/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_deinit.inc new file mode 100644 index 00000000000..2b0f9cbb701 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_deinit.inc @@ -0,0 +1,18 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--connection child2_1 +set global sql_mode= @old_sql_mode; +--connection master_1 +set session spider_sync_sql_mode= @old_spider_sync_sql_mode; +--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/include/strict_group_by_init.inc b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_init.inc new file mode 100644 index 00000000000..15c2a9eed7c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/strict_group_by_init.inc @@ -0,0 +1,60 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +if (!$HAVE_PARTITION) +{ + --source strict_group_by_deinit.inc + --enable_result_log + --enable_query_log + --enable_warnings + skip Test requires partitioning; +} +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a"' + PARTITION BY KEY(pkey) ( + PARTITION pt1 COMMENT='srv "s_2_1"', + PARTITION pt2 COMMENT='srv "s_2_2"' + ); +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey, skey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey, skey FROM tbl_a ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_sync_sql_mode= @@spider_sync_sql_mode; +set session spider_sync_sql_mode= FALSE; +--connection child2_1 +set @old_sql_mode= @@sql_mode; +set global sql_mode= 'ONLY_FULL_GROUP_BY'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/strict_group_by.result b/storage/spider/mysql-test/spider/bugfix/r/strict_group_by.result new file mode 100644 index 00000000000..f2287dea65a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/strict_group_by.result @@ -0,0 +1,124 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_sync_sql_mode= @@spider_sync_sql_mode; +set session spider_sync_sql_mode= FALSE; +connection child2_1; +set @old_sql_mode= @@sql_mode; +set global sql_mode= 'ONLY_FULL_GROUP_BY'; + +this test is for MDEV-18988 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +skey int NOT NULL, +PRIMARY KEY (pkey), +KEY idx1 (skey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19); +INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +FLUSH TABLES; +SELECT count(pkey) cnt, skey FROM tbl_a; +cnt skey +30 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select count(`pkey`),min(`pkey`),min(`skey`) from `auto_test_remote`.`tbl_a` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey, skey FROM tbl_a ORDER BY pkey; +pkey skey +1 1 +3 3 +5 5 +7 7 +9 9 +11 11 +13 13 +15 15 +17 17 +19 19 +21 6 +23 8 +25 10 +27 12 +29 14 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select count(`pkey`),min(`pkey`),min(`skey`) from `auto_test_remote2`.`tbl_a` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey, skey FROM tbl_a ORDER BY pkey; +pkey skey +0 0 +2 2 +4 4 +6 6 +8 8 +10 10 +12 12 +14 14 +16 16 +18 18 +20 5 +22 7 +24 9 +26 11 +28 13 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection child2_1; +set global sql_mode= @old_sql_mode; +connection master_1; +set session spider_sync_sql_mode= @old_spider_sync_sql_mode; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.cnf b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.cnf new file mode 100644 index 00000000000..e0ffb99c38e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_2_2.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.test b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.test new file mode 100644 index 00000000000..8b8da46d56c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/strict_group_by.test @@ -0,0 +1,98 @@ +--source ../include/strict_group_by_init.inc +--echo +--echo this test is for MDEV-18988 +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +--connection child2_2 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +--disable_query_log +echo CHILD2_2_CREATE_TABLES; +eval $CHILD2_2_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + skey int NOT NULL, + PRIMARY KEY (pkey), + KEY idx1 (skey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9); +INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19); +INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14); + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +FLUSH TABLES; +SELECT count(pkey) cnt, skey FROM tbl_a; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--connection child2_2 +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/strict_group_by_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 07f7c84c1ad..828aabb5ec5 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -218,6 +218,8 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_CONNECTION_LEN (sizeof(SPIDER_SQL_CONNECTION_STR) - 1) #define SPIDER_SQL_LCL_NAME_QUOTE_STR "`" #define SPIDER_SQL_LCL_NAME_QUOTE_LEN (sizeof(SPIDER_SQL_LCL_NAME_QUOTE_STR) - 1) +#define SPIDER_SQL_MIN_STR "min" +#define SPIDER_SQL_MIN_LEN (sizeof(SPIDER_SQL_MIN_STR) - 1) #define SPIDER_SQL_LOP_CHK_PRM_PRF_STR "spider_lc_" #define SPIDER_SQL_LOP_CHK_PRM_PRF_LEN (sizeof(SPIDER_SQL_LOP_CHK_PRM_PRF_STR) - 1) @@ -1352,6 +1354,7 @@ public: #ifdef SPIDER_HAS_GROUP_BY_HANDLER SPIDER_LINK_IDX_CHAIN *link_idx_chain; #endif + bool strict_group_by; spider_db_handler(ha_spider *spider, spider_db_share *db_share) : dbton_id(db_share->dbton_id), spider(spider), db_share(db_share), first_link_idx(-1) {} diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 9c37d9058b6..faacd4a970f 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -9804,10 +9804,58 @@ int spider_mbase_handler::append_table_select_part( int spider_mbase_handler::append_table_select( spider_string *str ) { +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_table_select"); - table_name_pos = str->length() + mysql_share->table_select_pos; - if (str->append(*(mysql_share->table_select))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } + if (select_lex) + { + TABLE *table = spider->get_table(); + Field **field; + int field_length; + for (field = table->field; *field; field++) + { + field_length = + mysql_share->column_name_str[(*field)->field_index].length(); + if (!spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { + if (str->reserve(field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, (*field)->field_index); + } + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + } else { +#endif + table_name_pos = str->length() + mysql_share->table_select_pos; + if (str->append(*(mysql_share->table_select))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif DBUG_RETURN(0); } @@ -9835,10 +9883,63 @@ int spider_mbase_handler::append_key_select( spider_string *str, uint idx ) { +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_key_select"); - table_name_pos = str->length() + mysql_share->key_select_pos[idx]; - if (str->append(mysql_share->key_select[idx])) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } + if (select_lex) + { + TABLE *table = spider->get_table(); + KEY *key_info = &table->key_info[idx]; + KEY_PART_INFO *key_part; + Field *field; + uint part_num; + int field_length; + for (key_part = key_info->key_part, part_num = 0; + part_num < spider_user_defined_key_parts(key_info); + key_part++, part_num++) + { + field = key_part->field; + field_length = mysql_share->column_name_str[field->field_index].length(); + if (!spider_db_check_select_colum_in_group(select_lex, field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + mysql_share->append_column_name(str, field->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { + if (str->reserve(field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, field->field_index); + } + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + } else { +#endif + table_name_pos = str->length() + mysql_share->key_select_pos[idx]; + if (str->append(mysql_share->key_select[idx])) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif DBUG_RETURN(0); } @@ -9869,7 +9970,23 @@ int spider_mbase_handler::append_minimum_select( Field **field; int field_length; bool appended = FALSE; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_minimum_select"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif minimum_select_bitmap_create(); for (field = table->field; *field; field++) { @@ -9880,10 +9997,27 @@ int spider_mbase_handler::append_minimum_select( */ field_length = mysql_share->column_name_str[(*field)->field_index].length(); - if (str->reserve(field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); appended = TRUE; } @@ -9906,16 +10040,50 @@ int spider_mbase_handler::append_table_select_with_alias( TABLE *table = spider->get_table(); Field **field; int field_length; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_table_select_with_alias"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif for (field = table->field; *field; field++) { field_length = mysql_share->column_name_str[(*field)->field_index].length(); - if (str->reserve(alias_length + field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(alias, alias_length); - mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + alias_length + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(alias_length + field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } str->length(str->length() - SPIDER_SQL_COMMA_LEN); @@ -9932,17 +10100,51 @@ int spider_mbase_handler::append_key_select_with_alias( Field *field; uint part_num; int field_length; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_key_select_with_alias"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif for (key_part = key_info->key_part, part_num = 0; part_num < spider_user_defined_key_parts(key_info); key_part++, part_num++) { field = key_part->field; field_length = mysql_share->column_name_str[field->field_index].length(); - if (str->reserve(alias_length + field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(alias, alias_length); - mysql_share->append_column_name(str, field->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + alias_length + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, field->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(alias_length + field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, field->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } str->length(str->length() - SPIDER_SQL_COMMA_LEN); @@ -9958,7 +10160,23 @@ int spider_mbase_handler::append_minimum_select_with_alias( Field **field; int field_length; bool appended = FALSE; +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + st_select_lex *select_lex = NULL; + bool sgb = (spider->result_list.direct_aggregate && + spider_param_strict_group_by(current_thd, (strict_group_by ? 1 : 0)) == 1); +#endif DBUG_ENTER("spider_mbase_handler::append_minimum_select_with_alias"); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (sgb) + { + select_lex = spider_get_select_lex(spider); + JOIN *join = select_lex->join; + if (!(*join->sum_funcs) && !select_lex->group_list.elements) + { + select_lex = NULL; + } + } +#endif minimum_select_bitmap_create(); for (field = table->field; *field; field++) { @@ -9969,11 +10187,29 @@ int spider_mbase_handler::append_minimum_select_with_alias( */ field_length = mysql_share->column_name_str[(*field)->field_index].length(); - if (str->reserve(alias_length + field_length + - /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(alias, alias_length); - mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + if (select_lex && + !spider_db_check_select_colum_in_group(select_lex, *field)) + { + if (str->reserve(SPIDER_SQL_MIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN + + alias_length + field_length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_MIN_STR, SPIDER_SQL_MIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN); + } else { +#endif + if (str->reserve(alias_length + field_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(alias, alias_length); + mysql_share->append_column_name(str, (*field)->field_index); +#ifdef HANDLER_HAS_DIRECT_AGGREGATE + } +#endif str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); appended = TRUE; } diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 7dbfe12d03d..0fe1a45dd27 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -258,7 +258,7 @@ const char SPIDER_empty_string = ""; #define SPIDER_TMP_SHARE_CHAR_PTR_COUNT 21 #define SPIDER_TMP_SHARE_UINT_COUNT SPIDER_TMP_SHARE_CHAR_PTR_COUNT -#define SPIDER_TMP_SHARE_LONG_COUNT 19 +#define SPIDER_TMP_SHARE_LONG_COUNT 20 #define SPIDER_TMP_SHARE_LONGLONG_COUNT 3 #define SPIDER_MEM_CALC_LIST_NUM 314 @@ -1164,6 +1164,7 @@ typedef struct st_spider_share long *net_write_timeouts; long *access_balances; long *bka_table_name_types; + long *strict_group_bys; uint *server_names_lengths; uint *tgt_table_names_lengths; @@ -1277,6 +1278,7 @@ typedef struct st_spider_share uint net_write_timeouts_length; uint access_balances_length; uint bka_table_name_types_length; + uint strict_group_bys_length; /* for dbton */ uchar dbton_bitmap[spider_bitmap_size(SPIDER_DBTON_SIZE)]; diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index 90f68450f67..14c2b60fb26 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -3450,6 +3450,32 @@ bool spider_param_sync_sql_mode( DBUG_RETURN(THDVAR(thd, sync_sql_mode)); } +/* + -1 : use table parameter + 0 : do not strict + 1 : do strict + */ +static MYSQL_THDVAR_INT( + strict_group_by, /* name */ + PLUGIN_VAR_RQCMDARG, /* opt */ + "Use columns in select clause strictly for group by clause", + NULL, /* check */ + NULL, /* update */ + -1, /* def */ + -1, /* min */ + 1, /* max */ + 0 /* blk */ +); + +int spider_param_strict_group_by( + THD *thd, + int strict_group_by +) { + DBUG_ENTER("spider_param_strict_group_by"); + DBUG_RETURN(THDVAR(thd, strict_group_by) == -1 ? + strict_group_by : THDVAR(thd, strict_group_by)); +} + static struct st_mysql_storage_engine spider_storage_engine = { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -3604,6 +3630,7 @@ static struct st_mysql_sys_var* spider_system_variables[] = { MYSQL_SYSVAR(remote_wait_timeout), MYSQL_SYSVAR(wait_timeout), MYSQL_SYSVAR(sync_sql_mode), + MYSQL_SYSVAR(strict_group_by), NULL }; diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h index f3b103eec99..c3a79cec065 100644 --- a/storage/spider/spd_param.h +++ b/storage/spider/spd_param.h @@ -436,3 +436,7 @@ int spider_param_wait_timeout( bool spider_param_sync_sql_mode( THD *thd ); +int spider_param_strict_group_by( + THD *thd, + int strict_group_by +); diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 27003f4a58b..752897bd000 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -913,6 +913,8 @@ int spider_free_share_alloc( spider_free(spider_current_trx, share->access_balances, MYF(0)); if (share->bka_table_name_types) spider_free(spider_current_trx, share->bka_table_name_types, MYF(0)); + if (share->strict_group_bys) + spider_free(spider_current_trx, share->strict_group_bys, MYF(0)); #ifndef WITHOUT_SPIDER_BG_SEARCH if (share->monitoring_bg_interval) spider_free(spider_current_trx, share->monitoring_bg_interval, MYF(0)); @@ -2390,6 +2392,7 @@ int spider_parse_connect_info( SPIDER_PARAM_STR_LIST("scp", tgt_ssl_capaths); SPIDER_PARAM_STR_LIST("scr", tgt_ssl_certs); SPIDER_PARAM_INT_WITH_MAX("sdc", skip_default_condition, 0, 1); + SPIDER_PARAM_LONG_LIST_WITH_MAX("sgb", strict_group_bys, 0, 1); SPIDER_PARAM_DOUBLE("siv", sts_interval, 0); SPIDER_PARAM_STR_LIST("sky", tgt_ssl_keys); SPIDER_PARAM_STR_LIST("sli", static_link_ids); @@ -2561,6 +2564,8 @@ int spider_parse_connect_info( #endif SPIDER_PARAM_LONG_LIST_WITH_MAX("connect_timeout", connect_timeouts, 0, 2147483647); + SPIDER_PARAM_LONG_LIST_WITH_MAX("strict_group_by", + strict_group_bys, 0, 1); SPIDER_PARAM_INT_WITH_MAX("error_read_mode", error_read_mode, 0, 1); error_num = connect_string_parse.print_param_error(); goto error; @@ -2796,6 +2801,8 @@ int spider_parse_connect_info( share->all_link_count = share->access_balances_length; if (share->all_link_count < share->bka_table_name_types_length) share->all_link_count = share->bka_table_name_types_length; + if (share->all_link_count < share->strict_group_bys_length) + share->all_link_count = share->strict_group_bys_length; if ((error_num = spider_increase_string_list( &share->server_names, &share->server_names_lengths, @@ -3059,6 +3066,11 @@ int spider_parse_connect_info( &share->bka_table_name_types_length, share->all_link_count))) goto error; + if ((error_num = spider_increase_long_list( + &share->strict_group_bys, + &share->strict_group_bys_length, + share->all_link_count))) + goto error; /* copy for tables start */ share_alter = &share->alter_table; @@ -3922,6 +3934,8 @@ int spider_set_connect_info_default( share->access_balances[roop_count] = 100; if (share->bka_table_name_types[roop_count] == -1) share->bka_table_name_types[roop_count] = 0; + if (share->strict_group_bys[roop_count] == -1) + share->strict_group_bys[roop_count] = 1; } #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -8557,6 +8571,7 @@ void spider_set_tmp_share_pointer( tmp_long[15] = -1; tmp_share->access_balances = &tmp_long[17]; tmp_share->bka_table_name_types = &tmp_long[18]; + tmp_share->strict_group_bys = &tmp_long[19]; tmp_share->monitoring_limit = &tmp_longlong[0]; tmp_share->monitoring_sid = &tmp_longlong[1]; #ifndef WITHOUT_SPIDER_BG_SEARCH @@ -8634,6 +8649,7 @@ void spider_set_tmp_share_pointer( tmp_share->net_write_timeouts_length = 1; tmp_share->access_balances_length = 1; tmp_share->bka_table_name_types_length = 1; + tmp_share->strict_group_bys_length = 1; #ifndef WITHOUT_SPIDER_BG_SEARCH tmp_share->monitoring_bg_flag[0] = -1;