[MDEV-18202]  SQL_CALC_FOUND_ROWS do not work with UNION ALL Created: 2019-01-10  Updated: 2023-11-27

Status: Stalled
Project: MariaDB Server
Component/s: OTHER
Affects Version/s: 10.1, 10.2, 10.3, 10.4
Fix Version/s: 10.4

Type: Bug Priority: Major
Reporter: Oleksandr Byelkin Assignee: Oleksandr Byelkin
Resolution: Unresolved Votes: 0
Labels: None


 Description   

SELECT SQL_CALC_FOUND_ROWS 'foo' UNION ALL SELECT 'bar';
SELECT SQL_CALC_FOUND_ROWS 'foo' UNION ALL SELECT 'bar' LIMIT 0;
SELECT FOUND_ROWS();

SELECT SQL_CALC_FOUND_ROWS 'foo' UNION ALL SELECT 'bar';
foo
foo
bar
SELECT SQL_CALC_FOUND_ROWS 'foo' UNION ALL SELECT 'bar' LIMIT 0;
foo
SELECT FOUND_ROWS();
FOUND_ROWS()
0



 Comments   
Comment by Oleksandr Byelkin [ 2019-01-10 ]

Do not work with real tables.

Without ALL and SQL_CALC_FOUND_ROWS but with LIMIT it also return incorrect found_rows() (2 instead of 0 independently of real or not tables)

Comment by Rucha Deodhar [ 2020-05-28 ]

Works fine with real tables, gives wrong output when real tables are not used in the query:

|MariaDB [d1]> SELECT SQL_CALC_FOUND_ROWS id1 FROM t1 UNION ALL SELECT  id2 FROM t2;
+------+
| id1  |
+------+
|    1 |
|    2 |
|    3 |
|    3 |
|    4 |
|    5 |
+------+
6 rows in set (0.001 sec)
 
MariaDB [d1]> SELECT SQL_CALC_FOUND_ROWS id1 FROM t1 UNION ALL SELECT  id2 FROM t2 LIMIT 0;
Empty set (0.001 sec)
 
MariaDB [d1]> select FOUND_ROWS();
+--------------+
| FOUND_ROWS() |
+--------------+
|            6 |
+--------------+
1 row in set (0.001 sec)
 
MariaDB [d1]> SELECT SQL_CALC_FOUND_ROWS 'foo' UNION ALL SELECT 'bar' LIMIT 0;
Empty set (0.001 sec)
 
MariaDB [d1]> select FOUND_ROWS();
+--------------+
| FOUND_ROWS() |
+--------------+
|            0 |
+--------------+
1 row in set (0.001 sec)

Comment by Rucha Deodhar [ 2020-06-08 ]

JOIN::exec_inner() has a branch which checks for tableless queries. When the limit is 0, m_sent_row_count (value returned by thd->get_sent_row_count()) is never incremented and remains 0 (because do_send_record is true and procedure is false, so result->send_data() is called.
result->send_data() calls send_data() method of select_union_direct which calls send_data method of select_send where m_sent_row_count is incremented if limit is not 0. Since limit is 0, we never really reach here).
So send_records remains 0. send_records gets the value of thd->get_sent_row_count(), which is always 0.

Comment by Rucha Deodhar [ 2020-06-11 ]

https://github.com/MariaDB/server/commit/393028ec4dd5f3222a18db3c833b77f917f48da1

select_options (here used in conjunction with OPTION_FOUND_ROWS) is not set correctly to check if the SELECT in union of SELECTs has SQL_CALC_FOUND_ROWS. As a result, (select_options & OPTION_FOUND_ROWS) would give out 0 and send_records gets assigned 0 (number of rows sent to client in the query. In case of LIMIT 0, no rows were sent to client, so send_records gets assigned 0).

thd->limit_found_rows(the variable from where FOUND_ROWS() gets its value from) gets its value from send_records, so it also gets assigned 0.

After setting select_options correctly, send_record gave out 1 (in case of tablesless SELECT, 1 row is sent to client). And even if limit_found_rows is incremented in select_union_direct::send_eof() and the correct value of rows gets assigned to thd->limit_found_rows when current_select==last_select_lex, thd->limit_found_rows gets assigned 1 again because thd->limit_found_rows=send_records executes after send_eof (And send_records has value 1 here) for every select in union of selects.

Comment by Oleksandr Byelkin [ 2020-06-18 ]

https://github.com/MariaDB/server/commit/d348afe77c1c3be0da899d07a74c14d2932dd0ef

Generated at Thu Feb 08 08:42:16 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.