1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

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.
This commit is contained in:
Sergey Vojtovich
2013-09-06 15:59:19 +04:00
parent 078388f39c
commit bbc9e57981
9 changed files with 94 additions and 10 deletions

View File

@@ -7977,4 +7977,43 @@ Warning 1329 No data - zero rows fetched, selected, or processed
drop procedure p1; drop procedure p1;
drop procedure p2; drop procedure p2;
drop table t1; 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 # End of 5.5 test

View File

@@ -9271,4 +9271,35 @@ drop procedure p2;
drop table t1; 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 --echo # End of 5.5 test

View File

@@ -3496,7 +3496,8 @@ select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types, create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options, bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long, const char *table_alias, bool bit_fields_as_long,
bool create_table) bool create_table,
bool keep_row_order)
{ {
DBUG_ASSERT(table == 0); DBUG_ASSERT(table == 0);
tmp_table_param.field_count= column_types->elements; 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, if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1, (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; return TRUE;
col_stat= (Column_statistics*) table->in_use->alloc(table->s->fields * col_stat= (Column_statistics*) table->in_use->alloc(table->s->fields *

View File

@@ -3580,7 +3580,8 @@ public:
bool is_distinct, ulonglong options, bool is_distinct, ulonglong options,
const char *alias, const char *alias,
bool bit_fields_as_long, 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; } TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
}; };
@@ -3650,7 +3651,8 @@ public:
bool is_distinct, ulonglong options, bool is_distinct, ulonglong options,
const char *alias, const char *alias,
bool bit_fields_as_long, bool bit_fields_as_long,
bool create_table); bool create_table,
bool keep_row_order= FALSE);
bool init_result_table(ulonglong select_options); bool init_result_table(ulonglong select_options);
int send_data(List<Item> &items); int send_data(List<Item> &items);
void cleanup(); void cleanup();

View File

@@ -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(), if (create_result_table(unit->thd, unit->get_unit_column_types(),
FALSE, FALSE,
thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS, thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS,
"", FALSE, TRUE)) "", FALSE, TRUE, TRUE))
return TRUE; return TRUE;
materialized_cursor= new (&table->mem_root) materialized_cursor= new (&table->mem_root)

View File

@@ -14572,7 +14572,8 @@ TABLE *
create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields, ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit, 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; MEM_ROOT *mem_root_save, own_root;
TABLE *table; TABLE *table;
@@ -15375,6 +15376,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
share->db_record_offset= 1; share->db_record_offset= 1;
table->used_for_duplicate_elimination= (param->sum_func_count == 0 && table->used_for_duplicate_elimination= (param->sum_func_count == 0 &&
(table->group || table->distinct)); (table->group || table->distinct));
table->keep_row_order= keep_row_order;
if (!do_not_open) if (!do_not_open)
{ {
@@ -15712,7 +15714,8 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
table->no_rows ? NO_RECORD : table->no_rows ? NO_RECORD :
(share->reclength < 64 && (share->reclength < 64 &&
!share->blob_fields ? STATIC_RECORD : !share->blob_fields ? STATIC_RECORD :
table->used_for_duplicate_elimination ? table->used_for_duplicate_elimination ||
table->keep_row_order ?
DYNAMIC_RECORD : BLOCK_RECORD), DYNAMIC_RECORD : BLOCK_RECORD),
share->keys, &keydef, share->keys, &keydef,
(uint) (*recinfo-start_recinfo), (uint) (*recinfo-start_recinfo),

View File

@@ -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, TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields, ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit, 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); void free_tmp_table(THD *thd, TABLE *entry);
bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
ENGINE_COLUMNDEF *start_recinfo, ENGINE_COLUMNDEF *start_recinfo,

View File

@@ -129,6 +129,7 @@ bool select_union::flush()
table_alias name of the temporary table table_alias name of the temporary table
bit_fields_as_long convert bit fields to ulonglong bit_fields_as_long convert bit fields to ulonglong
create_table whether to physically create result table create_table whether to physically create result table
keep_row_order keep rows in order as they were inserted
DESCRIPTION DESCRIPTION
Create a temporary table that is used to store the result of a UNION, 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, select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options, bool is_union_distinct, ulonglong options,
const char *alias, 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); DBUG_ASSERT(table == 0);
tmp_table_param.init(); 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, if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1, (ORDER*) 0, is_union_distinct, 1,
options, HA_POS_ERROR, alias, options, HA_POS_ERROR, alias,
!create_table))) !create_table, keep_row_order)))
return TRUE; return TRUE;
table->keys_in_use_for_query.clear_all(); table->keys_in_use_for_query.clear_all();

View File

@@ -1149,6 +1149,10 @@ public:
*/ */
bool force_index_group; bool force_index_group;
bool distinct,const_table,no_rows, used_for_duplicate_elimination; 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 If set, the optimizer has found that row retrieval should access index