summaryrefslogtreecommitdiff
path: root/mysql-test
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2016-11-21 10:33:06 -0800
committerIgor Babaev <igor@askmonty.org>2016-11-21 10:33:39 -0800
commit665045f985787d77318a17ccddd67ec3ff92f7bc (patch)
tree9c5680ffaae3c4a6d35abac1418c0f99105e9eb1 /mysql-test
parent022aeda4c01a1be47abdfe90a59df2dc0b72828d (diff)
downloadmariadb-git-665045f985787d77318a17ccddd67ec3ff92f7bc.tar.gz
Fixed bug mdev-11081.
The idea of this fix was taken from the patch by Roy Lyseng for mysql-5.6 bug iBug#14740889: "Wrong result for aggregate functions when executing query through cursor". Here's Roy's comment for his patch: " The problem was that a grouped query did not behave properly when executed using a cursor. On further inspection, the query used one intermediate temporary table for the grouping. Then, Select_materialize::send_result_set_metadata created a temporary table for storing the query result. Notice that get_unit_column_types() is used to retrieve column meta-data for the query. The items contained in this list are later modified so that their result_field points to the row buffer of the materialized temporary table for the cursor. But prior to this, these result_field objects have been prepared for use in the grouping operation, by JOIN::make_tmp_tables_info(), hence the grouping operation operates on wrong column buffers. The problem is solved by using the list JOIN::fields when copying data to the materialized table. This list is set by JOIN::make_tmp_tables_info() and points to the columns of the last intermediate temporary table of the executed query. For a UNION, it points to the temporary table that is the result of the UNION query. Notice that we have to assign a value to ::fields early in JOIN::optimize() in case the optimization shortcuts due to a const plan detection. A more optimal solution might be to avoid creating the final temporary table when the query result is already stored in a temporary table. " The patch does not contain a test case, but the description of the problem corresponds exactly what could be observed in the test case for mdev-11081.
Diffstat (limited to 'mysql-test')
-rw-r--r--mysql-test/r/sp.result39
-rw-r--r--mysql-test/t/sp.test38
2 files changed, 77 insertions, 0 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 130e789d3eb..aca9458f124 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -8001,3 +8001,42 @@ return 1;
end |
ERROR 0A000: Not allowed to return a result set from a function
drop table t1,t2;
+#
+# MDEV-11081: CURSOR for query with GROUP BY
+#
+CREATE TABLE t1 (name VARCHAR(10), value INT);
+INSERT INTO t1 VALUES ('b',1);
+INSERT INTO t1 VALUES ('b',1);
+INSERT INTO t1 VALUES ('c',1);
+INSERT INTO t1 VALUES ('a',1);
+INSERT INTO t1 VALUES ('a',1);
+INSERT INTO t1 VALUES ('a',1);
+CREATE PROCEDURE p1 ()
+BEGIN
+DECLARE done INT DEFAULT FALSE;
+DECLARE v_name VARCHAR(10);
+DECLARE v_total INT;
+DECLARE c CURSOR FOR
+SELECT name, SUM(value) AS total FROM t1 GROUP BY name;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+OPEN c;
+read_loop:
+LOOP
+FETCH c INTO v_name, v_total;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT v_name, v_total;
+END LOOP;
+CLOSE c;
+END;
+|
+CALL p1();
+v_name v_total
+a 3
+v_name v_total
+b 2
+v_name v_total
+c 1
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index c80e1eaaa3e..aaab59bcb89 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -9446,3 +9446,41 @@ end |
--delimiter ;
drop table t1,t2;
+
+--echo #
+--echo # MDEV-11081: CURSOR for query with GROUP BY
+--echo #
+
+CREATE TABLE t1 (name VARCHAR(10), value INT);
+INSERT INTO t1 VALUES ('b',1);
+INSERT INTO t1 VALUES ('b',1);
+INSERT INTO t1 VALUES ('c',1);
+INSERT INTO t1 VALUES ('a',1);
+INSERT INTO t1 VALUES ('a',1);
+INSERT INTO t1 VALUES ('a',1);
+DELIMITER |;
+CREATE PROCEDURE p1 ()
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE v_name VARCHAR(10);
+ DECLARE v_total INT;
+ DECLARE c CURSOR FOR
+ SELECT name, SUM(value) AS total FROM t1 GROUP BY name;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+ OPEN c;
+read_loop:
+ LOOP
+ FETCH c INTO v_name, v_total;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT v_name, v_total;
+ END LOOP;
+ CLOSE c;
+END;
+|
+DELIMITER ;|
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+