1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-16327: Server doesn't account for engines that supports OFFSET on their own.

Engine get LIMIT/OFFSET info an can it use/reset.
This commit is contained in:
Oleksandr Byelkin
2019-10-11 13:08:53 +02:00
parent a6de640804
commit ebeb4f93e8
6 changed files with 71 additions and 7 deletions

View File

@ -14,6 +14,10 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef GROUP_BY_HANDLER_INCLUDED
#define GROUP_BY_HANDLER_INCLUDED
class Select_limit_counters;
/* /*
This file implements the group_by_handler interface. This interface This file implements the group_by_handler interface. This interface
can be used by storage handlers that can intercept summary or GROUP can be used by storage handlers that can intercept summary or GROUP
@ -56,7 +60,7 @@ struct Query
ORDER *order_by; ORDER *order_by;
Item *having; Item *having;
// LIMIT // LIMIT
//ha_rows select_limit_cnt, offset_limit_cnt; Select_limit_counters *limit;
}; };
class group_by_handler class group_by_handler
@ -101,3 +105,4 @@ public:
virtual void print_error(int error, myf errflag); virtual void print_error(int error, myf errflag);
}; };
#endif //GROUP_BY_HANDLER_INCLUDED

View File

@ -28,6 +28,10 @@ class Select_limit_counters
Select_limit_counters(): Select_limit_counters():
select_limit_cnt(0), offset_limit_cnt(0) select_limit_cnt(0), offset_limit_cnt(0)
{}; {};
Select_limit_counters(Select_limit_counters &orig):
select_limit_cnt(orig.select_limit_cnt),
offset_limit_cnt(orig.offset_limit_cnt)
{};
void set_limit(ha_rows limit, ha_rows offset) void set_limit(ha_rows limit, ha_rows offset)
{ {
@ -48,6 +52,8 @@ class Select_limit_counters
bool is_unlimited() bool is_unlimited()
{ return select_limit_cnt == HA_POS_ERROR; } { return select_limit_cnt == HA_POS_ERROR; }
bool is_unrestricted()
{ return select_limit_cnt == HA_POS_ERROR && offset_limit_cnt == 0; }
void set_unlimited() void set_unlimited()
{ select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; } { select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; }

View File

@ -3146,7 +3146,8 @@ bool JOIN::make_aggr_tables_info()
{ {
/* Check if the storage engine can intercept the query */ /* Check if the storage engine can intercept the query */
Query query= {&all_fields, select_distinct, tables_list, conds, Query query= {&all_fields, select_distinct, tables_list, conds,
group_list, order ? order : group_list, having}; group_list, order ? order : group_list, having,
&select_lex->master_unit()->lim};
group_by_handler *gbh= ht->create_group_by(thd, &query); group_by_handler *gbh= ht->create_group_by(thd, &query);
if (gbh) if (gbh)

View File

@ -103,3 +103,33 @@ count(NULL)
select count(NULL) from seq_1_to_3 limit 0; select count(NULL) from seq_1_to_3 limit 0;
count(NULL) count(NULL)
# End of 10.3 tests # End of 10.3 tests
#
# MDEV-16327: Server doesn't account for engines that supports
# OFFSET on their own.
#
select count(NULL) from seq_1_to_3 limit 1;
count(NULL)
0
explain format=json select count(NULL) from seq_1_to_3 limit 1;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"message": "Storage engine handles GROUP BY"
}
}
}
select count(NULL) from seq_1_to_3 limit 1 offset 1;
count(NULL)
explain format=json select count(NULL) from seq_1_to_3 limit 1 offset 1;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"message": "Storage engine handles GROUP BY"
}
}
}
# End of 10.5 tests

View File

@ -56,3 +56,15 @@ select count(NULL) from seq_1_to_3;
select count(NULL) from seq_1_to_3 limit 0; select count(NULL) from seq_1_to_3 limit 0;
--echo # End of 10.3 tests --echo # End of 10.3 tests
--echo #
--echo # MDEV-16327: Server doesn't account for engines that supports
--echo # OFFSET on their own.
--echo #
select count(NULL) from seq_1_to_3 limit 1;
explain format=json select count(NULL) from seq_1_to_3 limit 1;
select count(NULL) from seq_1_to_3 limit 1 offset 1;
explain format=json select count(NULL) from seq_1_to_3 limit 1 offset 1;
--echo # End of 10.5 tests

View File

@ -28,6 +28,7 @@
#include <handler.h> #include <handler.h>
#include <table.h> #include <table.h>
#include <field.h> #include <field.h>
#include <sql_limit.h>
static handlerton *sequence_hton; static handlerton *sequence_hton;
@ -361,15 +362,21 @@ static int dummy_savepoint(handlerton *, THD *, void *) { return 0; }
class ha_seq_group_by_handler: public group_by_handler class ha_seq_group_by_handler: public group_by_handler
{ {
Select_limit_counters limit;
List<Item> *fields; List<Item> *fields;
TABLE_LIST *table_list; TABLE_LIST *table_list;
bool first_row; bool first_row;
public: public:
ha_seq_group_by_handler(THD *thd_arg, List<Item> *fields_arg, ha_seq_group_by_handler(THD *thd_arg, List<Item> *fields_arg,
TABLE_LIST *table_list_arg) TABLE_LIST *table_list_arg,
: group_by_handler(thd_arg, sequence_hton), fields(fields_arg), Select_limit_counters *orig_lim)
table_list(table_list_arg) {} : group_by_handler(thd_arg, sequence_hton), limit(orig_lim[0]),
fields(fields_arg), table_list(table_list_arg)
{
// Reset limit because we are handling it now
orig_lim->set_unlimited();
}
~ha_seq_group_by_handler() {} ~ha_seq_group_by_handler() {}
int init_scan() { first_row= 1 ; return 0; } int init_scan() { first_row= 1 ; return 0; }
int next_row(); int next_row();
@ -425,7 +432,8 @@ create_group_by_handler(THD *thd, Query *query)
} }
/* Create handler and return it */ /* Create handler and return it */
handler= new ha_seq_group_by_handler(thd, query->select, query->from); handler= new ha_seq_group_by_handler(thd, query->select, query->from,
query->limit);
return handler; return handler;
} }
@ -440,7 +448,9 @@ int ha_seq_group_by_handler::next_row()
Check if this is the first call to the function. If not, we have already Check if this is the first call to the function. If not, we have already
returned all data. returned all data.
*/ */
if (!first_row) if (!first_row ||
limit.get_offset_limit() > 0 ||
limit.get_select_limit() == 0)
DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_RETURN(HA_ERR_END_OF_FILE);
first_row= 0; first_row= 0;