summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp.result39
-rw-r--r--mysql-test/t/sp.test31
-rw-r--r--sql/sql_class.cc6
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_cursor.cc2
-rw-r--r--sql/sql_select.cc7
-rw-r--r--sql/sql_select.h3
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/table.h4
9 files changed, 94 insertions, 10 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index a0f21b434d1..962b834e4ac 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -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
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 3590dc66187..ecb12408654 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.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
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 8b0006431a2..be1e24c61c1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -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 *
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 9b6cbcc2e8a..dab57a680f3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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();
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 3758bf27819..230a8b2c802 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -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)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1ce88b3c48c..8e3976ba3ca 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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),
diff --git a/sql/sql_select.h b/sql/sql_select.h
index eb50f65a0cc..179d1ccf8c6 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -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,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 1551a8ff6d6..8a5ec26ba80 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -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();
diff --git a/sql/table.h b/sql/table.h
index 7a946d63bcc..0e41c10447a 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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