mirror of
https://github.com/MariaDB/server.git
synced 2026-05-11 09:30:23 +02:00
Don't use flags in the group_by_handler class
instead pass the whole query down and let the engine return unsupported parts back
This commit is contained in:
parent
8dff1aa5dc
commit
21175bb316
4 changed files with 48 additions and 45 deletions
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -375,19 +375,17 @@ public:
|
|||
};
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
|
|
@ -417,7 +415,7 @@ 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"))
|
||||
|
|
@ -425,7 +423,7 @@ create_group_by_handler(THD *thd, List<Item> *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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue