#######################################################################################
#
# Executes REPLACE statements (effectively INSERT, or DELETE then INSERT if
# a duplicate value for a unique index or primary key is specified.
#
# Transaction 1: REPLACE INTO
# Transaction 2: REPLACE INTO SELECT
#
# NOTE: We should not delete rows where pk MOD 5 = 0 AND pk < 1001
#       (consistency check, see rr_c_count_not_zero).
#       So, make sure to insert/replace rows with pk > 1000, etc.
#
# Note that one REPLACE insert may replace more than one row, if we have
# multiple columns with unique indexes.
# Vary the values for unique columns so that we don't replace the same row every time.
######################################################################################

SET autocommit = 0;


###########################
# Transaction 1
###########################

START TRANSACTION;

# In order to avoid replacing a "reserved" row (pk mod 5 = 0 AND pk <= 1000), we need
# to pick a row to replace which fulfills this requirement (we cannot replace an arbitrary row).
# We also should not replace internally inconsistent rows, as this would not be a zero-sum transaction.
# We select a pk between 200 and 1200 depending on conn_id, not including those where pk MOD 5 = 0.
# This will cost an extra roundtrip and reduce concurency, but there is not much else to do apart
# from not having unique indexes in the table.
# Using FOR UPDATE to avoid letting other treads change the uniques values or the row's consistency
# properties in the mean time.

--echo *** Disabling result log
--disable_result_log
--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
SELECT @pk:=`pk`, @unique:=`int1_unique`
    FROM t1
    WHERE `pk` MOD 5 <> 0
      AND `pk` > 200 + (CONNECTION_ID() MOD 1000)
      AND `int1_unique` NOT IN (SELECT `int1_unique` FROM t1 WHERE (`pk` < 1000 AND `pk` MOD 5 = 0) OR `is_consistent` = 0)
      AND -`int1_unique` NOT IN (SELECT `int2_unique` FROM t1 WHERE (`pk` < 1000 AND `pk` MOD 5 = 0) OR `is_consistent` = 0)
      AND `is_consistent`= 1
    LIMIT 1 FOR UPDATE;
--echo *** Enabling result log
--enable_result_log

--source suite/engines/rr_trx/include/check_for_error_rollback_skip.inc

--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
REPLACE INTO t1 SET `pk` = @pk,
                    `id` = 7,
                    `int1` = 7,
                    `int1_key` = -7,
                    `int1_unique` = @unique,
                    `int2` = -7,
                    `int2_key` = 7,
                    `int2_unique` = -@unique,
                    `connection_id` = CONNECTION_ID(),
                    `is_consistent` = 1;

COMMIT;

###########################
# Transaction 2
###########################

START TRANSACTION;

# Same rules apply as in previous transaction. Do not replace a "reserved" or inconsistent row.

# We get Warning "1592: Statement is not safe to log in statement mode" with server 5.1
# due to LIMIT (see Bug#42415 and Bug#42851).
--disable_warnings

--error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
REPLACE INTO t1
    SELECT * FROM t1
    WHERE `pk` > 1000 + CONNECTION_ID() MOD 777
      AND `int1_unique` NOT IN (SELECT `int1_unique` FROM t1 WHERE `pk` < 1000 OR `is_consistent` = 0)
      AND `int2_unique` NOT IN (SELECT `int2_unique` FROM t1 WHERE `pk` < 1000 OR `is_consistent` = 0)
      AND `pk` MOD 5 <> 0
      AND `is_consistent` = 1
    ORDER BY `pk` LIMIT 1;
--enable_warnings

# Conditional, so skip query log:
--disable_query_log
--echo *** Updating replaced row (if applicable)
# Update id, conn_id if we successfully replaced a row.
if (`SELECT IF(ROW_COUNT() > 0, 1, 0)`)
{
    --error 0, ER_LOCK_DEADLOCK, ER_LOCK_WAIT_TIMEOUT, ER_CHECKREAD
    UPDATE t1 SET `id` = 8, `connection_id` = CONNECTION_ID() WHERE `pk` = @@last_insert_id;
    --source suite/engines/rr_trx/include/check_for_error_rollback.inc
}
--enable_query_log

COMMIT;
