summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2016-12-20 10:25:25 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2016-12-20 11:25:47 +0100
commitaaff3d6c35f51dde60907f3c0fc4b2a40bc63c38 (patch)
treedbdfd49a88cfeb441626fddc929d2951a17e625f
parentf23b41b9b8a30e0e54a1ec7a8923057b0e57e0f5 (diff)
downloadmariadb-git-aaff3d6c35f51dde60907f3c0fc4b2a40bc63c38.tar.gz
MDEV-10172: UNION query returns incorrect rows outside conditional evaluation
count duplicate of UNION SELECT separately to awoid influence on lokal LIMIT clause.
-rw-r--r--mysql-test/r/union.result33
-rw-r--r--mysql-test/t/union.test22
-rw-r--r--sql/sql_select.cc13
-rw-r--r--sql/sql_select.h5
4 files changed, 61 insertions, 12 deletions
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 40f5a77e3d0..5a6cd8907e9 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -362,7 +362,7 @@ a
2
select found_rows();
found_rows()
-6
+5
SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 100;
a
1
@@ -1169,12 +1169,9 @@ a b
select * from ((select * from t1 limit 1) union (select * from t1 limit 1)) a;
a b
1 a
-2 b
select * from ((select * from t1 limit 1) union (select * from t1 limit 1) union (select * from t1 limit 1)) a;
a b
1 a
-2 b
-3 c
select * from ((((select * from t1))) union (select * from t1) union (select * from t1)) a;
a b
1 a
@@ -1553,7 +1550,6 @@ NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
Note 1003 select NULL AS `a` from `test`.`t1` union select NULL AS `a` from `test`.`t1` order by `a`
DROP TABLE t1;
-End of 5.0 tests
#
# Bug#32858: Error: "Incorrect usage of UNION and INTO" does not take
# subselects into account
@@ -1659,6 +1655,14 @@ a
4
5
6
+(select a from t1 where false) UNION (select a from t1) limit 8;
+a
+10
+2
+3
+4
+5
+6
7
8
drop table t1;
@@ -1955,3 +1959,22 @@ cccc
bbbb
dddd
drop table t1;
+#
+# MDEV-10172: UNION query returns incorrect rows outside
+# conditional evaluation
+#
+create table t1 (d datetime not null primary key);
+insert into t1(d) values ('2016-06-01'),('2016-06-02'),('2016-06-03'),('2016-06-04');
+select * from
+(
+select * from t1 where d between '2016-06-02' and '2016-06-05'
+ union
+(select * from t1 where d < '2016-06-05' order by d desc limit 1)
+) onlyJun2toJun4
+order by d;
+d
+2016-06-02 00:00:00
+2016-06-03 00:00:00
+2016-06-04 00:00:00
+drop table t1;
+End of 5.0 tests
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 9204ddd22e5..f4dc6a5d449 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -1022,7 +1022,6 @@ ORDER BY a;
DROP TABLE t1;
---echo End of 5.0 tests
-- echo #
-- echo # Bug#32858: Error: "Incorrect usage of UNION and INTO" does not take
-- echo # subselects into account
@@ -1126,6 +1125,8 @@ create table t1 (a int);
insert into t1 values (10),(10),(10),(2),(3),(4),(5),(6),(7),(8),(9),(1),(10);
--sorted_result
select a from t1 where false UNION select a from t1 limit 8;
+--sorted_result
+(select a from t1 where false) UNION (select a from t1) limit 8;
drop table t1;
--echo #
@@ -1350,3 +1351,22 @@ UNION
;
drop table t1;
+
+
+--echo #
+--echo # MDEV-10172: UNION query returns incorrect rows outside
+--echo # conditional evaluation
+--echo #
+
+create table t1 (d datetime not null primary key);
+insert into t1(d) values ('2016-06-01'),('2016-06-02'),('2016-06-03'),('2016-06-04');
+select * from
+(
+ select * from t1 where d between '2016-06-02' and '2016-06-05'
+ union
+ (select * from t1 where d < '2016-06-05' order by d desc limit 1)
+) onlyJun2toJun4
+order by d;
+drop table t1;
+
+--echo End of 5.0 tests
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 8c994964d59..839665f3a9f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2871,7 +2871,7 @@ JOIN::exec()
*curr_fields_list),
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
error= do_select(curr_join, curr_fields_list, NULL, procedure);
- thd->limit_found_rows= curr_join->send_records;
+ thd->limit_found_rows= curr_join->send_records - curr_join->duplicate_rows;
/* Accumulate the counts from all join iterations of all join parts. */
thd->examined_row_count+= curr_join->examined_rows;
@@ -16578,7 +16578,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
join->join_tab[join->top_join_tab_count - 1].next_select= end_select;
join_tab=join->join_tab+join->const_tables;
}
- join->send_records=0;
+ join->duplicate_rows= join->send_records=0;
if (join->table_count == join->const_tables)
{
/*
@@ -18089,7 +18089,12 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
int error;
/* result < 0 if row was not accepted and should not be counted */
if ((error= join->result->send_data(*join->fields)))
- DBUG_RETURN(error < 0 ? NESTED_LOOP_OK : NESTED_LOOP_ERROR);
+ {
+ if (error > 0)
+ DBUG_RETURN(NESTED_LOOP_ERROR);
+ // error < 0 => duplicate row
+ join->duplicate_rows++;
+ }
}
if (++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
@@ -18205,7 +18210,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (error < 0)
{
/* Duplicate row, don't count */
- join->send_records--;
+ join->duplicate_rows++;
error= 0;
}
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 4650bc24c68..0623672840e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1018,7 +1018,8 @@ public:
table_map outer_join;
/* Bitmap of tables used in the select list items */
table_map select_list_used_tables;
- ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
+ ha_rows send_records, found_records, examined_rows,
+ row_limit, select_limit, duplicate_rows;
/**
Used to fetch no more than given amount of rows per one
fetch operation of server side cursor.
@@ -1272,7 +1273,7 @@ public:
sort_and_group= 0;
first_record= 0;
do_send_rows= 1;
- send_records= 0;
+ duplicate_rows= send_records= 0;
found_records= 0;
fetch_limit= HA_POS_ERROR;
examined_rows= 0;