Commit bbc9e579 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-4978 - Server cursor is broken with blobs in the select list,

            ORDER BY does not work

Use "dynamic" row format (instead of "block") for MARIA internal
temporary tables created for cursors.

With "block" row format MARIA may shuffle rows, with "dynamic" row
format records are inserted sequentially (there are no gaps in data
file while we fill temporary tables).

This is needed to preserve row order when scanning materialized cursors.
parent 078388f3
......@@ -7977,4 +7977,43 @@ Warning 1329 No data - zero rows fetched, selected, or processed
drop procedure p1;
drop procedure p2;
drop table t1;
#
# MDEV-4978 - Server cursor is broken with blobs in the select list,
# ORDER BY does not work
#
CREATE TABLE t1(a INT, b BLOB);
INSERT INTO t1 VALUES(1,REPEAT('a',4835)),(2,'b'),(3,'c'),(4,'d'),(5,REPEAT('e',805)),(6,'f');
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v1 INT;
DECLARE v2 BLOB;
DECLARE c1 CURSOR FOR SELECT * FROM t1 ORDER BY a;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
OPEN c1;
REPEAT
FETCH c1 INTO v1, v2;
IF NOT done THEN
SELECT v1;
END IF;
UNTIL done END REPEAT;
CLOSE c1;
END|
CALL p1;
v1
1
v1
2
v1
3
v1
4
v1
5
v1
6
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
DROP PROCEDURE p1;
DROP TABLE t1;
# End of 5.5 test
......@@ -9271,4 +9271,35 @@ drop procedure p2;
drop table t1;
--echo #
--echo # MDEV-4978 - Server cursor is broken with blobs in the select list,
--echo # ORDER BY does not work
--echo #
CREATE TABLE t1(a INT, b BLOB);
INSERT INTO t1 VALUES(1,REPEAT('a',4835)),(2,'b'),(3,'c'),(4,'d'),(5,REPEAT('e',805)),(6,'f');
DELIMITER |;
CREATE PROCEDURE p1()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v1 INT;
DECLARE v2 BLOB;
DECLARE c1 CURSOR FOR SELECT * FROM t1 ORDER BY a;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
OPEN c1;
REPEAT
FETCH c1 INTO v1, v2;
IF NOT done THEN
SELECT v1;
END IF;
UNTIL done END REPEAT;
CLOSE c1;
END|
DELIMITER ;|
CALL p1;
DROP PROCEDURE p1;
DROP TABLE t1;
--echo # End of 5.5 test
......@@ -3496,7 +3496,8 @@ select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long,
bool create_table)
bool create_table,
bool keep_row_order)
{
DBUG_ASSERT(table == 0);
tmp_table_param.field_count= column_types->elements;
......@@ -3504,7 +3505,8 @@ create_result_table(THD *thd_arg, List<Item> *column_types,
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
options, HA_POS_ERROR, (char*) table_alias)))
options, HA_POS_ERROR, (char*) table_alias,
keep_row_order)))
return TRUE;
col_stat= (Column_statistics*) table->in_use->alloc(table->s->fields *
......
......@@ -3580,7 +3580,8 @@ public:
bool is_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long,
bool create_table);
bool create_table,
bool keep_row_order= FALSE);
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
};
......@@ -3650,7 +3651,8 @@ public:
bool is_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long,
bool create_table);
bool create_table,
bool keep_row_order= FALSE);
bool init_result_table(ulonglong select_options);
int send_data(List<Item> &items);
void cleanup();
......
......@@ -389,7 +389,7 @@ bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
if (create_result_table(unit->thd, unit->get_unit_column_types(),
FALSE,
thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS,
"", FALSE, TRUE))
"", FALSE, TRUE, TRUE))
return TRUE;
materialized_cursor= new (&table->mem_root)
......
......@@ -14572,7 +14572,8 @@ TABLE *
create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit,
const char *table_alias, bool do_not_open)
const char *table_alias, bool do_not_open,
bool keep_row_order)
{
MEM_ROOT *mem_root_save, own_root;
TABLE *table;
......@@ -15375,6 +15376,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
share->db_record_offset= 1;
table->used_for_duplicate_elimination= (param->sum_func_count == 0 &&
(table->group || table->distinct));
table->keep_row_order= keep_row_order;
if (!do_not_open)
{
......@@ -15712,7 +15714,8 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
table->no_rows ? NO_RECORD :
(share->reclength < 64 &&
!share->blob_fields ? STATIC_RECORD :
table->used_for_duplicate_elimination ?
table->used_for_duplicate_elimination ||
table->keep_row_order ?
DYNAMIC_RECORD : BLOCK_RECORD),
share->keys, &keydef,
(uint) (*recinfo-start_recinfo),
......
......@@ -1821,7 +1821,8 @@ void push_index_cond(JOIN_TAB *tab, uint keyno);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit,
const char* alias, bool do_not_open=FALSE);
const char* alias, bool do_not_open=FALSE,
bool keep_row_order= FALSE);
void free_tmp_table(THD *thd, TABLE *entry);
bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
ENGINE_COLUMNDEF *start_recinfo,
......
......@@ -129,6 +129,7 @@ bool select_union::flush()
table_alias name of the temporary table
bit_fields_as_long convert bit fields to ulonglong
create_table whether to physically create result table
keep_row_order keep rows in order as they were inserted
DESCRIPTION
Create a temporary table that is used to store the result of a UNION,
......@@ -143,7 +144,8 @@ bool
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long, bool create_table)
bool bit_fields_as_long, bool create_table,
bool keep_row_order)
{
DBUG_ASSERT(table == 0);
tmp_table_param.init();
......@@ -153,7 +155,7 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
options, HA_POS_ERROR, alias,
!create_table)))
!create_table, keep_row_order)))
return TRUE;
table->keys_in_use_for_query.clear_all();
......
......@@ -1149,6 +1149,10 @@ public:
*/
bool force_index_group;
bool distinct,const_table,no_rows, used_for_duplicate_elimination;
/**
Forces DYNAMIC Aria row format for internal temporary tables.
*/
bool keep_row_order;
/**
If set, the optimizer has found that row retrieval should access index
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment