diff options
-rw-r--r-- | mysql-test/r/sp.result | 39 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 31 | ||||
-rw-r--r-- | sql/sql_class.cc | 6 | ||||
-rw-r--r-- | sql/sql_class.h | 6 | ||||
-rw-r--r-- | sql/sql_cursor.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 7 | ||||
-rw-r--r-- | sql/sql_select.h | 3 | ||||
-rw-r--r-- | sql/sql_union.cc | 6 | ||||
-rw-r--r-- | sql/table.h | 4 |
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 |