Skip to content

Commit

Permalink
Don't use flags in the group_by_handler class
Browse files Browse the repository at this point in the history
instead pass the whole query down and let the engine return
unsupported parts back
  • Loading branch information
vuvova committed Oct 5, 2015
1 parent 8dff1aa commit 21175bb
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 45 deletions.
46 changes: 32 additions & 14 deletions sql/group_by_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Item> *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)
Expand Down Expand Up @@ -67,19 +98,6 @@ class group_by_handler
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
Expand Down
6 changes: 2 additions & 4 deletions sql/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<Item> *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.
Expand Down
27 changes: 8 additions & 19 deletions sql/sql_select.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
Expand All @@ -1965,25 +1960,19 @@ 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;
/*
Select distinct is handled by handler or by creating an unique index
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;

Expand Down
14 changes: 6 additions & 8 deletions storage/sequence/sequence.cc
Original file line number Diff line number Diff line change
Expand Up @@ -375,19 +375,17 @@ class ha_seq_group_by_handler: public group_by_handler
};

static group_by_handler *
create_group_by_handler(THD *thd, List<Item> *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<Item> it(*fields);
List_iterator_fast<Item> 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;

/*
Expand Down Expand Up @@ -417,15 +415,15 @@ create_group_by_handler(THD *thd, List<Item> *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"))
return 0;
}

/* 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;
}

Expand Down

0 comments on commit 21175bb

Please sign in to comment.