Bug #106090 query through *prefix index defined on virutal column* may see unexpected result
Submitted: 7 Jan 2022 4:45 Modified: 7 Jan 2022 6:39
Reporter: henry liang Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S2 (Serious)
Version:8.0, 5.7.36, 8.0.27 OS:Any
Assigned to: CPU Architecture:Any

[7 Jan 2022 4:45] henry liang
Description:
During btree search on secondary index, when access primary index is necessary, row_sel_get_clust_rec_for_mysql() will be called. In this function, in some cases(old version/sec index entry has del mark) clust_rec and sec_rec will be compared to see if the index entry exists in the snapshot.

For virtual column, innobase_get_computed_value() will be called to construct the real row and compare with secondary record entry, but when the latter is on column's prefix, the compare(through cmp_data_data) will failed even if it should return success, hence the record can not be seen by the query.

How to repeat:
--connect(con1, localhost, root,,)
--connect(con2, localhost, root,,)

--connection con1
## Prepare data
CREATE TABLE t1 (
  pk INT PRIMARY KEY AUTO_INCREMENT,
  i INT,
  vc VARCHAR(7),
  gc1 VARCHAR(14) GENERATED ALWAYS AS (concat(vc, vc)) VIRTUAL NOT NULL,
  gc2 VARCHAR(14) GENERATED ALWAYS AS (concat(gc1, 'x')) VIRTUAL NOT NULL,
  KEY gc2_key (gc2),
  KEY gc2_key_prefix (gc2(5))
);

INSERT INTO t1 (i, vc) VALUES
(7, 'xcek'), (3, 'ceksat'), (3, 'eksate'), (3, 'ksatef'), (6, 's');

--connection con1
--echo [connectionn con1]
BEGIN;
SELECT i FROM t1 FORCE INDEX (gc2_key_prefix) WHERE gc2 <= 'ksatefksatefx';

--connection con2
--echo [connectionn con2]
BEGIN;
SELECT i FROM t1 FORCE INDEX (gc2_key_prefix) WHERE gc2 <= 'ksatefksatefx';

--connection con1
--echo [connectionn con1]
## Delete records but not commit yet.
DELETE FROM t1;

--connection con2
--echo [connectionn con2]
## Query through virutal index return no result, but should see 3 records
SELECT i FROM t1 FORCE INDEX (gc2_key_prefix) WHERE gc2 <= 'ksatefksatefx';

## Query through PK see 3 records as expected
SELECT i FROM t1 FORCE INDEX (primary) WHERE gc2 <= 'ksatefksatefx';
[7 Jan 2022 6:39] MySQL Verification Team
Hello henry liang,

Thank you for the report and test case.
Verified as described.

regards,
Umesh