mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-28 04:06:59 +00:00
When we append an entry to a list with the same user-defined timestamp, the behaviour is actually undefined. If the append is processed by the same coordinator as the one that accepted the existing entry, then it gets the same timeuuid as the list key, and replaces (potentially) the existing list valiue. Then it gets a timeuuid which maybe both larger and smaller than the existing key's timeuuid, and then turns either to an append or a prepend. The part of the timestamp responsible for the result is the shard id's spoof node address implemented in scope of fixing Scylla's timeuuid uniqueness. When the test was implemented all spoof node ids where 0 on all shards and all coordinators. Later the difference in behaviour was dormant because cql_repl would always execute the append on the same shard. We could fix Scylla to use a zero spoof node address in case a user timestamp is supplied, but the purpose of this is unclear, it may actually be to the contrary of the user's intent.
92 lines
3.7 KiB
SQL
92 lines
3.7 KiB
SQL
CREATE TABLE t (pk INT PRIMARY KEY, l LIST<INT>);
|
|
UPDATE t SET l = [-1] + l WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = [-3,-2] + l WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = [-4] + l WHERE pk = 0 IF EXISTS;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = [-6, -5] + l WHERE pk = 0 IF EXISTS;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = l + [1] WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = l + [2,3] WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = l + [4] WHERE pk = 0 IF EXISTS;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t SET l = l + [5,6] WHERE pk = 0 IF EXISTS;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
BEGIN BATCH
|
|
UPDATE t SET l = l + [7] WHERE pk = 0
|
|
UPDATE t SET l = [-7] + l WHERE pk = 0
|
|
UPDATE t SET l = l + [8, 9] WHERE pk = 0
|
|
UPDATE t SET l = l + [10] WHERE pk = 0
|
|
UPDATE t SET l = [-9, -8] + l WHERE pk = 0
|
|
UPDATE t SET l = [-10] + l WHERE pk = 0
|
|
APPLY BATCH;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
-- LWT batch
|
|
BEGIN BATCH
|
|
UPDATE t SET l = [-11] + l WHERE pk = 0 IF EXISTS
|
|
UPDATE t SET l = [-13, -12] + l WHERE pk = 0 IF EXISTS
|
|
UPDATE t SET l = [-14] + l WHERE pk = 0 IF EXISTS
|
|
UPDATE t SET l = l + [11] WHERE pk = 0 IF EXISTS
|
|
UPDATE t SET l = l + [12, 13] WHERE pk = 0 IF EXISTS
|
|
UPDATE t SET l = l + [14] WHERE pk = 0 IF EXISTS
|
|
APPLY BATCH;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
|
|
DROP TABLE t;
|
|
-- test custom timestamps
|
|
-- Scylla, unlike Cassandra, takes custom timestamps into account
|
|
-- in list append/prepend operations
|
|
CREATE TABLE t (pk INT PRIMARY KEY, l LIST<INT>);
|
|
|
|
-- Even though it's an append, since the timestamp is in the past,
|
|
-- the result is going to be a prepend
|
|
UPDATE t USING TIMESTAMP 1607100000000000 SET l = l + [-3] WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
-- append with the same timestamp has an undefined behavior:
|
|
-- the list key, which is a TIMEUUID, is generated by the coordinator,
|
|
-- so depends on the coordinator spoof node address. If the coordinator
|
|
-- happens to be the same, then it generated an identical timestamp, and
|
|
-- then the the value is reset or skipped, depending on whether it's
|
|
-- larger or not lexicographically. But if the coordinator is different,
|
|
-- the value will be appended.
|
|
-- UPDATE t USING TIMESTAMP 1607100000000000 SET l = l + [-5] WHERE pk = 0;
|
|
-- SELECT l FROM t WHERE pk = 0;
|
|
UPDATE t USING TIMESTAMP 1607100000000001 SET l = l + [-2] WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
-- if a timestamp grows, the new value is after the previous one in the list
|
|
UPDATE t USING TIMESTAMP 1607100000000002 SET l = l + [-1] WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
-- And if it goes back, it's prepended
|
|
UPDATE t USING TIMESTAMP 1607099999999999 SET l = l + [-4] WHERE pk = 0;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
-- The batch has both list append and prepend.
|
|
-- The relative order of appends and prepends in the batch
|
|
-- is correct, but since batch timestamp is lower
|
|
-- than anything that is already in the list cell
|
|
-- all appends and prepends of the batch end up
|
|
-- preceding all previous values of the list.
|
|
BEGIN BATCH USING TIMESTAMP 1607099999999998
|
|
UPDATE t SET l = [-5] + l WHERE pk = 0
|
|
UPDATE t SET l = [-7, -6] + l WHERE pk = 0
|
|
UPDATE t SET l = [-8] + l WHERE pk = 0
|
|
UPDATE t SET l = l + [0] WHERE pk = 0
|
|
UPDATE t SET l = l + [1, 2] WHERE pk = 0
|
|
UPDATE t SET l = l + [3] WHERE pk = 0
|
|
APPLY BATCH;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
-- try a very low timestamp
|
|
BEGIN BATCH USING TIMESTAMP 1000
|
|
UPDATE t SET l = [-8] + l WHERE pk = 0
|
|
UPDATE t SET l = [-10, -9] + l WHERE pk = 0
|
|
UPDATE t SET l = [-11] + l WHERE pk = 0
|
|
UPDATE t SET l = l + [4] WHERE pk = 0
|
|
UPDATE t SET l = l + [5, 6] WHERE pk = 0
|
|
UPDATE t SET l = l + [7] WHERE pk = 0
|
|
APPLY BATCH;
|
|
SELECT l FROM t WHERE pk = 0;
|
|
|
|
DROP TABLE t;
|