From 21175bb31610cdfe7f25b981edc760e46aa08c43 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 2 Oct 2015 18:40:38 +0200 Subject: [PATCH] Don't use flags in the group_by_handler class instead pass the whole query down and let the engine return unsupported parts back --- sql/group_by_handler.h | 46 +++++++++++++++++++++++++----------- sql/handler.h | 6 ++--- sql/sql_select.cc | 27 +++++++-------------- storage/sequence/sequence.cc | 14 +++++------ 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/sql/group_by_handler.h b/sql/group_by_handler.h index 534acc27ee2..993e94819a2 100644 --- a/sql/group_by_handler.h +++ b/sql/group_by_handler.h @@ -30,13 +30,44 @@ SELECT a, (select sum(*) from t2 where t1.a=t2.a) from t2; */ +/** + The structure describing various parts of the query + + The engine is supposed to take out parts that it can do internally. + For example, if the engine can return results sorted according to + the specified order_by clause, it sets Query::order_by=NULL before + returning. + + At the moment the engine must take group_by (or return an error), and + optionally can take distinct, where, order_by, and having. + + The engine should not modify the select list. It is the extended SELECT + clause (extended, because it has more items than the original + user-specified SELECT clause) and it contains all aggregate functions, + used in the query. +*/ +struct Query +{ + List *select; + bool distinct; + TABLE_LIST *from; + Item *where; + ORDER *group_by; + ORDER *order_by; + Item *having; + // LIMIT +}; + class group_by_handler { public: THD *thd; handlerton *ht; - /* Temporary table where all results should be stored in record[0] */ + /* + Temporary table where all results should be stored in record[0] + The table has a field for every item from the Query::select list. + */ TABLE *table; group_by_handler(THD *thd_arg, handlerton *ht_arg) @@ -67,19 +98,6 @@ public: return init(having_arg, order_by_arg); } - /* - Bits of things the storage engine can do for this query. - Should be initialized on object creation. - Result data is sorted by the storage engine according to order_by (if it - exists) else according to the group_by. If this is not specified, - MariaDB will store the result set into the temporary table and sort the - result. - */ - #define GROUP_BY_ORDER_BY 1 - /* The storage engine can handle DISTINCT */ - #define GROUP_BY_DISTINCT 2 - virtual uint flags() { return 0; } - /* Functions to scan data. All these returns 0 if ok, error code in case of error diff --git a/sql/handler.h b/sql/handler.h index fb5ce226a74..cfb6836f6d4 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -950,6 +950,7 @@ struct handler_iterator { class handler; class group_by_handler; +struct Query; typedef class st_select_lex SELECT_LEX; typedef struct st_order ORDER; @@ -1267,10 +1268,7 @@ struct handlerton The server guaranteeds that all tables in the list belong to this storage engine. */ - group_by_handler *(*create_group_by)(THD *thd, List *fields, - TABLE_LIST *table_list, ORDER *group_by, - ORDER *order_by, Item *where, - Item *having); + group_by_handler *(*create_group_by)(THD *thd, Query *query); /********************************************************************* Table discovery API. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index dcd8bd839b2..af8571fb714 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1916,31 +1916,26 @@ JOIN::optimize_inner() if (ht && ht->create_group_by) { /* Check if the storage engine can intercept the query */ - group_by_handler *gbh= ht->create_group_by(thd, &all_fields, - tables_list, group_list, order, conds, having); + Query query= {&all_fields, select_distinct, tables_list, conds, + group_list, order ? order : group_list, having}; + group_by_handler *gbh= ht->create_group_by(thd, &query); if (gbh) { pushdown_query= new (thd->mem_root) Pushdown_query(select_lex, gbh); - uint handler_flags= gbh->flags(); int err; /* We must store rows in the tmp table if we need to do an ORDER BY or DISTINCT and the storage handler can't handle it. */ - need_tmp= ((!(handler_flags & GROUP_BY_ORDER_BY) && - (order || group_list)) || - (!(handler_flags & GROUP_BY_DISTINCT) && select_distinct)); + need_tmp= query.order_by || query.group_by || query.distinct; tmp_table_param.hidden_field_count= (all_fields.elements - fields_list.elements); if (!(exec_tmp_table1= create_tmp_table(thd, &tmp_table_param, all_fields, 0, - handler_flags & GROUP_BY_DISTINCT ? - 0 : select_distinct, 1, + query.distinct, 1, select_options, HA_POS_ERROR, "", - !need_tmp, - (!order || - (handler_flags & GROUP_BY_ORDER_BY))))) + !need_tmp, query.order_by || query.group_by))) DBUG_RETURN(1); /* @@ -1965,16 +1960,11 @@ JOIN::optimize_inner() } pushdown_query->store_data_in_temp_table= need_tmp; pushdown_query->having= having; - /* - If no ORDER BY clause was specified explicitly, we should sort things - according to the group_by - */ - if (!order) - order= group_list; /* Group by and having is calculated by the group_by handler. Reset the group by and having */ + DBUG_ASSERT(query.group_by == NULL); group= 0; group_list= 0; having= tmp_having= 0; /* @@ -1982,8 +1972,7 @@ JOIN::optimize_inner() over all fields in the temporary table */ select_distinct= 0; - if (handler_flags & GROUP_BY_ORDER_BY) - order= 0; + order= query.order_by; tmp_table_param.field_count+= tmp_table_param.sum_func_count; tmp_table_param.sum_func_count= 0; diff --git a/storage/sequence/sequence.cc b/storage/sequence/sequence.cc index d0d46495acf..36ccebfa86f 100644 --- a/storage/sequence/sequence.cc +++ b/storage/sequence/sequence.cc @@ -375,19 +375,17 @@ public: }; static group_by_handler * -create_group_by_handler(THD *thd, List *fields, TABLE_LIST *table_list, - ORDER *group_by, ORDER *order_by, Item *where, - Item *having) +create_group_by_handler(THD *thd, Query *query) { ha_seq_group_by_handler *handler; Item *item; - List_iterator_fast it(*fields); + List_iterator_fast it(*query->select); /* check that only one table is used in FROM clause and no sub queries */ - if (table_list->next_local != 0) + if (query->from->next_local != 0) return 0; /* check that there is no where clause and no group_by */ - if (where != 0 || group_by != 0) + if (query->where != 0 || query->group_by != 0) return 0; /* @@ -417,7 +415,7 @@ create_group_by_handler(THD *thd, List *fields, TABLE_LIST *table_list, Check that we are using the sequence table (the only table in the FROM clause) and not an outer table. */ - if (field->table != table_list->table) + if (field->table != query->from->table) return 0; /* Check that we are using a SUM() on the primary key */ if (strcmp(field->field_name, "seq")) @@ -425,7 +423,7 @@ create_group_by_handler(THD *thd, List *fields, TABLE_LIST *table_list, } /* Create handler and return it */ - handler= new ha_seq_group_by_handler(thd, fields, table_list); + handler= new ha_seq_group_by_handler(thd, query->select, query->from); return handler; }