Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions mysql-test/suite/heap/blob_vers_full.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Probe: versioned UPDATE on a HEAP blob table at capacity, with one
# base slot freed first so that heap_update() itself succeeds and the
# history-row write is what needs the space.
#
SET @@max_heap_table_size = 1048576;
CREATE TABLE t (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t VALUES (0, 't');
# Fill to capacity
# Reached capacity
# Free one base record slot
DELETE FROM t WHERE pk = 0;
# Shrinking versioned UPDATE: heap_update() succeeds and parks the old
# chain; the history row then needs a full 2000-byte chain, which the
# parked one supplies. Asserted as plain success -- tolerating
# ER_RECORD_FILE_FULL here would let the regression this pins be
# absorbed by an mtr --record.
UPDATE t SET f = 'x' WHERE pk = 1;
# Base row state and whether its previous version survived
SELECT LENGTH(f) AS cur_len FROM t WHERE pk = 1;
cur_len
1
SELECT COUNT(*) AS all_versions FROM t FOR SYSTEM_TIME ALL WHERE pk = 1;
all_versions
2
SELECT COUNT(*) AS history_ok
FROM t FOR SYSTEM_TIME ALL WHERE pk = 1 AND f = REPEAT('a', 2000);
history_ok
1
DROP TABLE t;
SET @@max_heap_table_size = DEFAULT;
47 changes: 47 additions & 0 deletions mysql-test/suite/heap/blob_vers_full.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
--echo #
--echo # Probe: versioned UPDATE on a HEAP blob table at capacity, with one
--echo # base slot freed first so that heap_update() itself succeeds and the
--echo # history-row write is what needs the space.
--echo #

SET @@max_heap_table_size = 1048576;

CREATE TABLE t (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;

INSERT INTO t VALUES (0, 't');

--echo # Fill to capacity
--disable_query_log
--let $i= 1
while ($i < 3000)
{
--error 0,ER_RECORD_FILE_FULL
eval INSERT INTO t VALUES ($i, REPEAT('a', 2000));
if ($mysql_errno)
{
--let $i= 3000
}
--inc $i
}
--enable_query_log
--echo # Reached capacity

--echo # Free one base record slot
DELETE FROM t WHERE pk = 0;

--echo # Shrinking versioned UPDATE: heap_update() succeeds and parks the old
--echo # chain; the history row then needs a full 2000-byte chain, which the
--echo # parked one supplies. Asserted as plain success -- tolerating
--echo # ER_RECORD_FILE_FULL here would let the regression this pins be
--echo # absorbed by an mtr --record.
UPDATE t SET f = 'x' WHERE pk = 1;

--echo # Base row state and whether its previous version survived
SELECT LENGTH(f) AS cur_len FROM t WHERE pk = 1;
SELECT COUNT(*) AS all_versions FROM t FOR SYSTEM_TIME ALL WHERE pk = 1;
SELECT COUNT(*) AS history_ok
FROM t FOR SYSTEM_TIME ALL WHERE pk = 1 AND f = REPEAT('a', 2000);

DROP TABLE t;
SET @@max_heap_table_size = DEFAULT;
85 changes: 85 additions & 0 deletions mysql-test/suite/heap/blob_vers_multi.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#
# The remaining vers_insert_history_row() callers on a HEAP table with
# blobs: multi-table UPDATE (both the on-the-fly and the deferred
# do_updates() path) and REPLACE.
#
# Each of them writes the history row from a record buffer that a read
# filled with zero-copy blob pointers into HP_BLOCK, so each can hand
# heap_write() a blob source living in the chain ha_update_row() just
# parked for deferred free.
#
#
# Multi-table UPDATE: the first table is updated while scanning, the
# second goes through the deferred do_updates() path
#
CREATE TABLE t1 (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
CREATE TABLE t2 (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t1 VALUES (1, REPEAT('abcdefgh',8)), (2, REPEAT('ijklmnop',60));
INSERT INTO t2 VALUES (1, REPEAT('12345678',40)), (2, REPEAT('!@#$%^&*',300));
UPDATE t1, t2 SET t1.f = CONCAT('n1_', t1.pk), t2.f = CONCAT('n2_', t2.pk)
WHERE t1.pk = t2.pk;
SELECT pk, f FROM t1 ORDER BY pk;
pk f
1 n1_1
2 n1_2
SELECT pk, f FROM t2 ORDER BY pk;
pk f
1 n2_1
2 n2_2
SELECT pk, LENGTH(f),
f = REPEAT('abcdefgh',8) OR f = REPEAT('ijklmnop',60) AS hist_ok
FROM t1 FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'n1\_%' ORDER BY pk;
pk LENGTH(f) hist_ok
1 64 1
2 480 1
SELECT pk, LENGTH(f),
f = REPEAT('12345678',40) OR f = REPEAT('!@#$%^&*',300) AS hist_ok
FROM t2 FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'n2\_%' ORDER BY pk;
pk LENGTH(f) hist_ok
1 320 1
2 2400 1
DROP TABLE t1, t2;
#
# Multi-table UPDATE touching only the table that is not first in the
# join order
#
CREATE TABLE t1 (pk INT PRIMARY KEY, c INT) ENGINE=HEAP;
CREATE TABLE t2 (pk INT PRIMARY KEY, b1 TEXT, b2 MEDIUMTEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t1 VALUES (1, 10), (2, 20);
INSERT INTO t2 VALUES (1, REPEAT('abcdefgh',50), REPEAT('ABCDEFGH',150)),
(2, REPEAT('qrstuvwx',25), REPEAT('ijklmnop',400));
# STRAIGHT_JOIN pins t2 second, so it goes through do_updates() rather
# than being updated on the fly like the case above
UPDATE t1 STRAIGHT_JOIN t2 ON t1.pk = t2.pk
SET t2.b1 = REPEAT('z', 900), t2.b2 = 'y';
SELECT pk,
b1 = CASE pk WHEN 1 THEN REPEAT('abcdefgh',50)
ELSE REPEAT('qrstuvwx',25) END AS b1_ok,
b2 = CASE pk WHEN 1 THEN REPEAT('ABCDEFGH',150)
ELSE REPEAT('ijklmnop',400) END AS b2_ok
FROM t2 FOR SYSTEM_TIME ALL WHERE b2 <> 'y' ORDER BY pk;
pk b1_ok b2_ok
1 1 1
2 1 1
DROP TABLE t1, t2;
#
# REPLACE reaching the optimized ha_update_row() path
#
CREATE TABLE t (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t VALUES (1, REPEAT('abcdefgh',8)), (2, REPEAT('ijklmnop',60));
REPLACE INTO t VALUES (1, 'r1'), (2, 'r2');
SELECT pk, f FROM t ORDER BY pk;
pk f
1 r1
2 r2
SELECT pk, LENGTH(f),
f = REPEAT('abcdefgh',8) OR f = REPEAT('ijklmnop',60) AS hist_ok
FROM t FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'r%' ORDER BY pk;
pk LENGTH(f) hist_ok
1 64 1
2 480 1
DROP TABLE t;
79 changes: 79 additions & 0 deletions mysql-test/suite/heap/blob_vers_multi.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
--echo #
--echo # The remaining vers_insert_history_row() callers on a HEAP table with
--echo # blobs: multi-table UPDATE (both the on-the-fly and the deferred
--echo # do_updates() path) and REPLACE.
--echo #
--echo # Each of them writes the history row from a record buffer that a read
--echo # filled with zero-copy blob pointers into HP_BLOCK, so each can hand
--echo # heap_write() a blob source living in the chain ha_update_row() just
--echo # parked for deferred free.
--echo #

--echo #
--echo # Multi-table UPDATE: the first table is updated while scanning, the
--echo # second goes through the deferred do_updates() path
--echo #
CREATE TABLE t1 (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
CREATE TABLE t2 (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;

INSERT INTO t1 VALUES (1, REPEAT('abcdefgh',8)), (2, REPEAT('ijklmnop',60));
INSERT INTO t2 VALUES (1, REPEAT('12345678',40)), (2, REPEAT('!@#$%^&*',300));

UPDATE t1, t2 SET t1.f = CONCAT('n1_', t1.pk), t2.f = CONCAT('n2_', t2.pk)
WHERE t1.pk = t2.pk;

SELECT pk, f FROM t1 ORDER BY pk;
SELECT pk, f FROM t2 ORDER BY pk;

SELECT pk, LENGTH(f),
f = REPEAT('abcdefgh',8) OR f = REPEAT('ijklmnop',60) AS hist_ok
FROM t1 FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'n1\_%' ORDER BY pk;
SELECT pk, LENGTH(f),
f = REPEAT('12345678',40) OR f = REPEAT('!@#$%^&*',300) AS hist_ok
FROM t2 FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'n2\_%' ORDER BY pk;

DROP TABLE t1, t2;

--echo #
--echo # Multi-table UPDATE touching only the table that is not first in the
--echo # join order
--echo #
CREATE TABLE t1 (pk INT PRIMARY KEY, c INT) ENGINE=HEAP;
CREATE TABLE t2 (pk INT PRIMARY KEY, b1 TEXT, b2 MEDIUMTEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;

INSERT INTO t1 VALUES (1, 10), (2, 20);
INSERT INTO t2 VALUES (1, REPEAT('abcdefgh',50), REPEAT('ABCDEFGH',150)),
(2, REPEAT('qrstuvwx',25), REPEAT('ijklmnop',400));

--echo # STRAIGHT_JOIN pins t2 second, so it goes through do_updates() rather
--echo # than being updated on the fly like the case above
UPDATE t1 STRAIGHT_JOIN t2 ON t1.pk = t2.pk
SET t2.b1 = REPEAT('z', 900), t2.b2 = 'y';

SELECT pk,
b1 = CASE pk WHEN 1 THEN REPEAT('abcdefgh',50)
ELSE REPEAT('qrstuvwx',25) END AS b1_ok,
b2 = CASE pk WHEN 1 THEN REPEAT('ABCDEFGH',150)
ELSE REPEAT('ijklmnop',400) END AS b2_ok
FROM t2 FOR SYSTEM_TIME ALL WHERE b2 <> 'y' ORDER BY pk;

DROP TABLE t1, t2;

--echo #
--echo # REPLACE reaching the optimized ha_update_row() path
--echo #
CREATE TABLE t (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t VALUES (1, REPEAT('abcdefgh',8)), (2, REPEAT('ijklmnop',60));

REPLACE INTO t VALUES (1, 'r1'), (2, 'r2');

SELECT pk, f FROM t ORDER BY pk;
SELECT pk, LENGTH(f),
f = REPEAT('abcdefgh',8) OR f = REPEAT('ijklmnop',60) AS hist_ok
FROM t FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'r%' ORDER BY pk;

DROP TABLE t;
95 changes: 95 additions & 0 deletions mysql-test/suite/heap/blob_vers_odku.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#
# INSERT ... ON DUPLICATE KEY UPDATE on a HEAP table with blobs.
#
# The duplicate branch reads the conflicting row into record[1] (blob
# pointers are zero-copy pointers into HP_BLOCK), copies it into
# record[0] with restore_record(table, record[1]), applies the update
# fields and calls ha_update_row(). On a system-versioned table it then
# calls vers_insert_history_row(), which does the same restore_record()
# and writes the history row -- with a blob source still pointing at the
# chain the update just parked for deferred free.
#
#
# Versioned: history row must keep the pre-update blob
#
CREATE TABLE t (pk INT PRIMARY KEY, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t VALUES (1, REPEAT('abcdefgh',8)), (2, REPEAT('ijklmnop',60));
INSERT INTO t VALUES (1, 'ignored'), (2, 'ignored')
ON DUPLICATE KEY UPDATE f = CONCAT('new', pk);
SELECT pk, f, LENGTH(f) FROM t ORDER BY pk;
pk f LENGTH(f)
1 new1 4
2 new2 4
SELECT pk, LENGTH(f),
f = REPEAT('abcdefgh',8) OR f = REPEAT('ijklmnop',60) AS hist_ok
FROM t FOR SYSTEM_TIME ALL WHERE f NOT LIKE 'new%' ORDER BY pk;
pk LENGTH(f) hist_ok
1 64 1
2 480 1
DROP TABLE t;
#
# Versioned, blob column NOT in the update list: the history row carries
# the blob forward unchanged
#
CREATE TABLE t (pk INT PRIMARY KEY, c INT, f TEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t VALUES (1, 10, REPEAT('abcdefgh',40)),
(2, 20, REPEAT('12345678',200));
INSERT INTO t (pk, c, f) VALUES (1, 0, 'ignored'), (2, 0, 'ignored')
ON DUPLICATE KEY UPDATE c = c + 1;
SELECT pk, c, LENGTH(f),
f = REPEAT('abcdefgh',40) OR f = REPEAT('12345678',200) AS cur_ok
FROM t ORDER BY pk;
pk c LENGTH(f) cur_ok
1 11 320 1
2 21 1600 1
SELECT pk, c, LENGTH(f),
f = REPEAT('abcdefgh',40) OR f = REPEAT('12345678',200) AS hist_ok
FROM t FOR SYSTEM_TIME ALL WHERE c IN (10, 20) ORDER BY pk;
pk c LENGTH(f) hist_ok
1 10 320 1
2 20 1600 1
DROP TABLE t;
#
# Versioned, multiple blob columns, mixed growth and shrink
#
CREATE TABLE t (pk INT PRIMARY KEY, b1 TEXT, b2 MEDIUMTEXT)
ENGINE=HEAP WITH SYSTEM VERSIONING CHARACTER SET latin1;
INSERT INTO t VALUES (1, REPEAT('abcdefgh',50), REPEAT('ABCDEFGH',150)),
(2, REPEAT('12345678',25), REPEAT('!@#$%^&*',400));
INSERT INTO t VALUES (1, 'ignored', 'ignored'), (2, 'ignored', 'ignored')
ON DUPLICATE KEY UPDATE b1 = REPEAT('z', 900), b2 = 'y';
SELECT pk,
b1 = CASE pk WHEN 1 THEN REPEAT('abcdefgh',50)
ELSE REPEAT('12345678',25) END AS b1_ok,
b2 = CASE pk WHEN 1 THEN REPEAT('ABCDEFGH',150)
ELSE REPEAT('!@#$%^&*',400) END AS b2_ok
FROM t FOR SYSTEM_TIME ALL WHERE b2 <> 'y' ORDER BY pk;
pk b1_ok b2_ok
1 1 1
2 1 1
DROP TABLE t;
#
# Non-versioned control: the same statement shape must leave the stored
# rows intact
#
CREATE TABLE t (pk INT PRIMARY KEY, c INT, f TEXT)
ENGINE=HEAP CHARACTER SET latin1;
INSERT INTO t VALUES (1, 10, REPEAT('abcdefgh',40)),
(2, 20, REPEAT('12345678',200));
INSERT INTO t (pk, c, f) VALUES (1, 0, 'ignored'), (2, 0, 'ignored')
ON DUPLICATE KEY UPDATE c = c + 1;
SELECT pk, c, LENGTH(f),
f = REPEAT('abcdefgh',40) OR f = REPEAT('12345678',200) AS f_ok
FROM t ORDER BY pk;
pk c LENGTH(f) f_ok
1 11 320 1
2 21 1600 1
INSERT INTO t (pk, c, f) VALUES (1, 0, 'ignored'), (2, 0, 'ignored')
ON DUPLICATE KEY UPDATE f = CONCAT('new', pk);
SELECT pk, c, f FROM t ORDER BY pk;
pk c f
1 11 new1
2 21 new2
DROP TABLE t;
Loading
Loading