Skip to content

Commit b49f1af

Browse files
kahatlendahlerlend
authored andcommitted
Bug#36578613: Hypergraph result difference when querying I_S.TABLES
Some query plans combining hash joins and sorting caused wrong results with the hypergraph optimizer. The problem occurred when two SORT paths were stacked on top of each other without any materialization step in between, and the sorting required row IDs, and the input to the lower SORT path came from a hash join. The cause of the problem is that the sorting iterators are not updating the row ID in handler::ref when they have positioned the handler on the row to return. This makes the next sort see the same row ID for every row, and it therefore returns the same row multiple times instead of sorting them. Fixed by making FindTablesToGetRowidFor() take into account that row IDs are not preserved through SORT the same way as they are through HASH_JOIN, so that any SORT or HASH_JOIN above a SORT will fetch row IDs afresh from the handler. Change-Id: I15d83fbfc748d7cf26bcaecb2f826e485b193c39
1 parent ea848d4 commit b49f1af

File tree

11 files changed

+89
-11
lines changed

11 files changed

+89
-11
lines changed

mysql-test/include/keyring_tests/mats/table_encrypt_2.inc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ CREATE TABLE not_encrypted2 (col1 INT) ENCRYPTION='N';
119119
CREATE TABLE encrypted1 (col1 INT) ENCRYPTION='y';
120120
CREATE TABLE encrypted2 (col1 INT) ENCRYPTION='Y';
121121

122-
--skip_if_hypergraph # See Bug#36578613.
123122
SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS
124123
FROM INFORMATION_SCHEMA.TABLES
125124
WHERE TABLE_NAME like '%encrypted%'

mysql-test/r/hypergraph_bugs.result

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,3 +1739,32 @@ SELECT NULL FROM t AS t1, t AS t2 STRAIGHT_JOIN t AS t3 ON t2.x = t3.x
17391739
) OR x = 1;
17401740
1
17411741
DROP TABLE t;
1742+
#
1743+
# Bug#36578613: Hypergraph result difference when querying I_S.TABLES
1744+
#
1745+
CREATE TABLE t(x INT, y LONGTEXT);
1746+
INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f');
1747+
ANALYZE TABLE t;
1748+
Table Op Msg_type Msg_text
1749+
test.t analyze status OK
1750+
EXPLAIN FORMAT=JSON INTO @explain SELECT DISTINCT t1.x, t1.y
1751+
FROM t AS t1, t AS t2 WHERE t1.x = t2.x
1752+
ORDER BY -t1.x;
1753+
SELECT
1754+
JSON_EXTRACT(@explain, '$.access_type') AS sort_for_order_by,
1755+
JSON_EXTRACT(@explain, '$.inputs[0].access_type') AS sort_for_distinct,
1756+
JSON_EXTRACT(@explain, '$.inputs[0].inputs[0].join_algorithm') AS hash_join;
1757+
sort_for_order_by "sort"
1758+
sort_for_distinct "sort"
1759+
hash_join "hash"
1760+
SELECT DISTINCT t1.x, t1.y
1761+
FROM t AS t1, t AS t2 WHERE t1.x = t2.x
1762+
ORDER BY -t1.x;
1763+
x y
1764+
6 f
1765+
5 e
1766+
4 d
1767+
3 c
1768+
2 b
1769+
1 a
1770+
DROP TABLE t;

mysql-test/suite/innodb/t/row_format.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
--echo # Bug#31479542 : MYSQL 8 ORPHANED TABLE DUE TO UNCHECKED NON-EXISTENT ROW FORMAT CHECK.
44
--echo #
55

6-
--source include/not_hypergraph.inc # Fails, see Bug#36578613
76
--source include/have_innodb_16k.inc
87
--source include/not_valgrind.inc
98

mysql-test/suite/innodb/t/table_encrypt_2.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ CREATE TABLE not_encrypted2 (col1 INT) ENCRYPTION='N';
127127
CREATE TABLE encrypted1 (col1 INT) ENCRYPTION='y';
128128
CREATE TABLE encrypted2 (col1 INT) ENCRYPTION='Y';
129129

130-
--skip_if_hypergraph # Bug#36578613
131130
SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS
132131
FROM INFORMATION_SCHEMA.TABLES
133132
WHERE TABLE_NAME like '%encrypted%'

mysql-test/suite/perfschema/t/table_component_lifecycle.test

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ select * from performance_schema.pfs_example_continent;
2626

2727
INSTALL COMPONENT "file://component_pfs_example_component_population";
2828

29-
--skip_if_hypergraph # Bug#36578613, see comment.
3029
select TABLE_SCHEMA, TABLE_NAME, ENGINE, VERSION, TABLE_COMMENT
3130
from INFORMATION_SCHEMA.tables
3231
where TABLE_NAME like "pfs_example_%"
@@ -80,7 +79,6 @@ select * from performance_schema.pfs_example_continent;
8079

8180
INSTALL COMPONENT "file://component_pfs_example_component_population";
8281

83-
--skip_if_hypergraph # Bug#36578613, see comment.
8482
select TABLE_SCHEMA, TABLE_NAME, ENGINE, VERSION, TABLE_COMMENT
8583
from INFORMATION_SCHEMA.tables
8684
where TABLE_NAME like "pfs_example_%"
@@ -98,7 +96,6 @@ select * from performance_schema.pfs_example_continent;
9896

9997
--source include/restart_mysqld.inc
10098

101-
--skip_if_hypergraph # Bug#36578613, see comment.
10299
select TABLE_SCHEMA, TABLE_NAME, ENGINE, VERSION, TABLE_COMMENT
103100
from INFORMATION_SCHEMA.tables
104101
where TABLE_NAME like "pfs_example_%"

mysql-test/suite/perfschema/t/table_plugin_in_use.test

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
#
77
################################################################################
88

9-
--source include/not_hypergraph.inc # Appears susceptible to Bug#36578613.
10-
119
connect(con1, localhost, root,,);
1210

1311
connect(con2, localhost, root,,);

mysql-test/suite/perfschema/t/table_plugin_lifecycle.test

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#
55
################################################################################
66

7-
--source include/not_hypergraph.inc # Appears susceptible to Bug#36578613.
8-
97
--echo #################
108
--echo # INITIAL STATE #
119
--echo #################

mysql-test/t/hypergraph_bugs.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,4 +1444,33 @@ FROM t WHERE x IN (
14441444
) OR x = 1;
14451445
DROP TABLE t;
14461446

1447+
--echo #
1448+
--echo # Bug#36578613: Hypergraph result difference when querying I_S.TABLES
1449+
--echo #
1450+
1451+
# Create a table with a LONGTEXT column, to ensure that filesort uses
1452+
# row IDs, and with enough rows to make a hash join look more
1453+
# attractive than a nested loop join.
1454+
CREATE TABLE t(x INT, y LONGTEXT);
1455+
INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f');
1456+
ANALYZE TABLE t;
1457+
1458+
let $query =
1459+
SELECT DISTINCT t1.x, t1.y
1460+
FROM t AS t1, t AS t2 WHERE t1.x = t2.x
1461+
ORDER BY -t1.x;
1462+
1463+
# To reproduce the bug, the plan should have two SORT nodes (one for
1464+
# ORDER BY and one for DISTINCT) on top of a HASH_JOIN node.
1465+
--eval EXPLAIN FORMAT=JSON INTO @explain $query
1466+
query_vertical
1467+
SELECT
1468+
JSON_EXTRACT(@explain, '$.access_type') AS sort_for_order_by,
1469+
JSON_EXTRACT(@explain, '$.inputs[0].access_type') AS sort_for_distinct,
1470+
JSON_EXTRACT(@explain, '$.inputs[0].inputs[0].join_algorithm') AS hash_join;
1471+
1472+
--eval $query
1473+
1474+
DROP TABLE t;
1475+
14471476
--source include/disable_hypergraph.inc

mysql-test/t/information_schema_cs.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ sql security definer view v2 as select 1;
901901
connect (con16681,localhost,mysqltest_1,,test);
902902
connection con16681;
903903

904+
--sorted_result
904905
select * from information_schema.views
905906
where table_name='v1' or table_name='v2';
906907
connection default;
@@ -1046,7 +1047,6 @@ select 1 as f1 from information_schema.tables where "COLUMN_PRIVILEGES"=
10461047
(select cast(table_name as char) from information_schema.tables
10471048
where table_schema != 'performance_schema' order by table_name limit 1) limit 1;
10481049

1049-
--skip_if_hypergraph # Flaky, see Bug#36579239
10501050
select t.table_name, group_concat(t.table_schema, '.', t.table_name),
10511051
count(*) as num1
10521052
from information_schema.tables t

sql/join_optimizer/access_path.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,12 @@ unique_ptr_destroy_only<RowIterator> CreateIteratorFromAccessPath(
13391339
}
13401340

13411341
void FindTablesToGetRowidFor(AccessPath *path) {
1342+
// A map of the tables for which other paths further down in the tree will
1343+
// take care of copying the correct row ID into table->file->ref. The hash
1344+
// join iterators and the BKA join iterators do that, so iterators higher up
1345+
// should not call handler::position(), as that would overwrite the copied row
1346+
// ID with the row ID of the last row that was read by the join. Sorting
1347+
// iterators, on the other hand, do not
13421348
table_map handled_by_others = 0;
13431349

13441350
auto add_tables_handled_by_others = [path, &handled_by_others](
@@ -1367,6 +1373,13 @@ void FindTablesToGetRowidFor(AccessPath *path) {
13671373
// Doesn't really matter, we don't cross query blocks anyway.
13681374
return true;
13691375
}
1376+
case AccessPath::SORT:
1377+
// The sorting iterators do not populate handler::ref with the row ID
1378+
// while returning rows, so row IDs in any tables handled by paths below
1379+
// it have to be fetched again from the handler by the paths above the
1380+
// sort. Therefore, we don't add any of the tables in the subtree below
1381+
// SORT to handled_by_others.
1382+
return true; // Skip the rest of the subtree.
13701383
default:
13711384
return false;
13721385
}

0 commit comments

Comments
 (0)