Skip to content

Commit e82dacd

Browse files
committed
Bug#22077611: UPDATE .. WHERE JSON_EXTRACT(..) = '..' NOT USING VIRTUAL COL INDEX
Expressions that match an indexed generated column may be replaced with the generated column in JOIN::optimize(), which enables use of the associated index. Single-table update and delete statements don't have a JOIN data structure, so this optimization is not performed for such statements. This patch changes JOIN::substitute_gc() into a free function, which is used from single-table update and delete statements as well as from JOIN::optimize(). With this change, single-table update and delete statements can use indexes on generated columns for filtering and ordering, even if the statements use the generated column expression instead of an explicit reference to the column.
1 parent d3fe9b0 commit e82dacd

14 files changed

+560
-32
lines changed

mysql-test/suite/gcol/inc/gcol_keys.inc

+27
Original file line numberDiff line numberDiff line change
@@ -762,5 +762,32 @@ ANALYZE TABLE employees;
762762
--eval EXPLAIN $query
763763
--eval $query
764764
DROP TABLE employees;
765+
--echo #
766+
--echo # Bug#22077611 UPDATE .. WHERE JSON_EXTRACT(..) = '..' NOT USING
767+
--echo # VIRTUAL COL INDEX
768+
--echo #
769+
CREATE TABLE t(a INT, b INT, gc INT GENERATED ALWAYS AS (a+1) STORED, KEY(gc));
770+
INSERT INTO t(a) VALUES (1), (2), (3), (4), (5), (1), (2), (3), (4), (5);
771+
ANALYZE TABLE t;
772+
--let $query= UPDATE t SET b = 10 WHERE (a+1) = 3
773+
--eval EXPLAIN $query
774+
--eval $query
775+
SELECT * FROM t ORDER BY a, b;
776+
ANALYZE TABLE t;
777+
--let $query= UPDATE t SET b = 9 ORDER BY (a+1) LIMIT 1
778+
--eval EXPLAIN $query
779+
--eval $query
780+
SELECT * FROM t ORDER BY a, b;
781+
ANALYZE TABLE t;
782+
--let $query= DELETE FROM t WHERE (a+1) = 2
783+
--eval EXPLAIN $query
784+
--eval $query
785+
SELECT * FROM t ORDER BY a, b;
786+
ANALYZE TABLE t;
787+
--let $query= DELETE FROM t ORDER BY (a+1) LIMIT 1
788+
--eval EXPLAIN $query
789+
--eval $query
790+
SELECT * FROM t ORDER BY a, b;
791+
DROP TABLE t;
765792

766793
--echo #

mysql-test/suite/gcol/r/gcol_keys_innodb.result

+78
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,84 @@ data name1 name2
13641364
{"id": 1, "name": "Jane"} "Jane" Jane
13651365
DROP TABLE employees;
13661366
#
1367+
# Bug#22077611 UPDATE .. WHERE JSON_EXTRACT(..) = '..' NOT USING
1368+
# VIRTUAL COL INDEX
1369+
#
1370+
CREATE TABLE t(a INT, b INT, gc INT GENERATED ALWAYS AS (a+1) STORED, KEY(gc));
1371+
INSERT INTO t(a) VALUES (1), (2), (3), (4), (5), (1), (2), (3), (4), (5);
1372+
ANALYZE TABLE t;
1373+
Table Op Msg_type Msg_text
1374+
test.t analyze status OK
1375+
EXPLAIN UPDATE t SET b = 10 WHERE (a+1) = 3;
1376+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1377+
1 UPDATE t NULL range gc gc 5 const 2 100.00 Using where
1378+
UPDATE t SET b = 10 WHERE (a+1) = 3;
1379+
SELECT * FROM t ORDER BY a, b;
1380+
a b gc
1381+
1 NULL 2
1382+
1 NULL 2
1383+
2 10 3
1384+
2 10 3
1385+
3 NULL 4
1386+
3 NULL 4
1387+
4 NULL 5
1388+
4 NULL 5
1389+
5 NULL 6
1390+
5 NULL 6
1391+
ANALYZE TABLE t;
1392+
Table Op Msg_type Msg_text
1393+
test.t analyze status OK
1394+
EXPLAIN UPDATE t SET b = 9 ORDER BY (a+1) LIMIT 1;
1395+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1396+
1 UPDATE t NULL index NULL gc 5 NULL 1 100.00 Using temporary
1397+
UPDATE t SET b = 9 ORDER BY (a+1) LIMIT 1;
1398+
SELECT * FROM t ORDER BY a, b;
1399+
a b gc
1400+
1 NULL 2
1401+
1 9 2
1402+
2 10 3
1403+
2 10 3
1404+
3 NULL 4
1405+
3 NULL 4
1406+
4 NULL 5
1407+
4 NULL 5
1408+
5 NULL 6
1409+
5 NULL 6
1410+
ANALYZE TABLE t;
1411+
Table Op Msg_type Msg_text
1412+
test.t analyze status OK
1413+
EXPLAIN DELETE FROM t WHERE (a+1) = 2;
1414+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1415+
1 DELETE t NULL range gc gc 5 const 2 100.00 Using where
1416+
DELETE FROM t WHERE (a+1) = 2;
1417+
SELECT * FROM t ORDER BY a, b;
1418+
a b gc
1419+
2 10 3
1420+
2 10 3
1421+
3 NULL 4
1422+
3 NULL 4
1423+
4 NULL 5
1424+
4 NULL 5
1425+
5 NULL 6
1426+
5 NULL 6
1427+
ANALYZE TABLE t;
1428+
Table Op Msg_type Msg_text
1429+
test.t analyze status OK
1430+
EXPLAIN DELETE FROM t ORDER BY (a+1) LIMIT 1;
1431+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1432+
1 DELETE t NULL index NULL gc 5 NULL 1 100.00 NULL
1433+
DELETE FROM t ORDER BY (a+1) LIMIT 1;
1434+
SELECT * FROM t ORDER BY a, b;
1435+
a b gc
1436+
2 10 3
1437+
3 NULL 4
1438+
3 NULL 4
1439+
4 NULL 5
1440+
4 NULL 5
1441+
5 NULL 6
1442+
5 NULL 6
1443+
DROP TABLE t;
1444+
#
13671445
#
13681446
# BUG#21365158 WL8149:ASSERTION `!TABLE || (!TABLE->WRITE_SET
13691447
#

mysql-test/suite/gcol/r/gcol_keys_myisam.result

+78
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,84 @@ data name1 name2
936936
{"id": 1, "name": "Jane"} "Jane" Jane
937937
DROP TABLE employees;
938938
#
939+
# Bug#22077611 UPDATE .. WHERE JSON_EXTRACT(..) = '..' NOT USING
940+
# VIRTUAL COL INDEX
941+
#
942+
CREATE TABLE t(a INT, b INT, gc INT GENERATED ALWAYS AS (a+1) STORED, KEY(gc));
943+
INSERT INTO t(a) VALUES (1), (2), (3), (4), (5), (1), (2), (3), (4), (5);
944+
ANALYZE TABLE t;
945+
Table Op Msg_type Msg_text
946+
test.t analyze status OK
947+
EXPLAIN UPDATE t SET b = 10 WHERE (a+1) = 3;
948+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
949+
1 UPDATE t NULL range gc gc 5 const 2 100.00 Using where
950+
UPDATE t SET b = 10 WHERE (a+1) = 3;
951+
SELECT * FROM t ORDER BY a, b;
952+
a b gc
953+
1 NULL 2
954+
1 NULL 2
955+
2 10 3
956+
2 10 3
957+
3 NULL 4
958+
3 NULL 4
959+
4 NULL 5
960+
4 NULL 5
961+
5 NULL 6
962+
5 NULL 6
963+
ANALYZE TABLE t;
964+
Table Op Msg_type Msg_text
965+
test.t analyze status OK
966+
EXPLAIN UPDATE t SET b = 9 ORDER BY (a+1) LIMIT 1;
967+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
968+
1 UPDATE t NULL index NULL gc 5 NULL 1 100.00 Using temporary
969+
UPDATE t SET b = 9 ORDER BY (a+1) LIMIT 1;
970+
SELECT * FROM t ORDER BY a, b;
971+
a b gc
972+
1 NULL 2
973+
1 9 2
974+
2 10 3
975+
2 10 3
976+
3 NULL 4
977+
3 NULL 4
978+
4 NULL 5
979+
4 NULL 5
980+
5 NULL 6
981+
5 NULL 6
982+
ANALYZE TABLE t;
983+
Table Op Msg_type Msg_text
984+
test.t analyze status OK
985+
EXPLAIN DELETE FROM t WHERE (a+1) = 2;
986+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
987+
1 DELETE t NULL range gc gc 5 const 2 100.00 Using where
988+
DELETE FROM t WHERE (a+1) = 2;
989+
SELECT * FROM t ORDER BY a, b;
990+
a b gc
991+
2 10 3
992+
2 10 3
993+
3 NULL 4
994+
3 NULL 4
995+
4 NULL 5
996+
4 NULL 5
997+
5 NULL 6
998+
5 NULL 6
999+
ANALYZE TABLE t;
1000+
Table Op Msg_type Msg_text
1001+
test.t analyze status OK
1002+
EXPLAIN DELETE FROM t ORDER BY (a+1) LIMIT 1;
1003+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1004+
1 DELETE t NULL index NULL gc 5 NULL 1 100.00 NULL
1005+
DELETE FROM t ORDER BY (a+1) LIMIT 1;
1006+
SELECT * FROM t ORDER BY a, b;
1007+
a b gc
1008+
2 10 3
1009+
3 NULL 4
1010+
3 NULL 4
1011+
4 NULL 5
1012+
4 NULL 5
1013+
5 NULL 6
1014+
5 NULL 6
1015+
DROP TABLE t;
1016+
#
9391017
DROP VIEW IF EXISTS v1,v2;
9401018
DROP TABLE IF EXISTS t1,t2,t3;
9411019
DROP PROCEDURE IF EXISTS p1;

0 commit comments

Comments
 (0)