From 4fa5ba0c2d0f157257eef5dbd18f4691d7b95e9f Mon Sep 17 00:00:00 2001 From: Alan Wang Date: Thu, 2 Jul 2026 15:20:34 -0700 Subject: [PATCH] initial tests --- .../test/accord/AccordCQLTestBase.java | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) diff --git a/test/distributed/org/apache/cassandra/distributed/test/accord/AccordCQLTestBase.java b/test/distributed/org/apache/cassandra/distributed/test/accord/AccordCQLTestBase.java index f38b84ede2..7898d44f40 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/accord/AccordCQLTestBase.java +++ b/test/distributed/org/apache/cassandra/distributed/test/accord/AccordCQLTestBase.java @@ -301,6 +301,34 @@ public abstract class AccordCQLTestBase extends AccordTestBase }); } + @Test + public void testRejectTransactionWithUpdatesToSamePrimaryKeyInTrailingUpdate() throws Throwable + { + test(cluster -> { + try + { + cluster.coordinator(1).execute(wrapInTxn("INSERT INTO " + qualifiedAccordTableName + " (k, c, v) VALUES (?, ?, ?)"), ConsistencyLevel.ALL, 1, 1, 2); + String txn = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1 AND c = 1);\n" + + " IF k1.v > 5 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1 AND c = 2;\n" + + " ELSE \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 2 WHERE k = 1 AND c = 1;\n" + + " END IF \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 5 WHERE k = 1 AND c = 1;\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(txn, ConsistencyLevel.SERIAL); + fail("Expected exception"); + } + catch (Throwable t) + { + assertEquals(InvalidRequestException.class.getName(), t.getClass().getName()); + assertEquals(TransactionStatement.DUPLICATE_KEYS_IN_SAME_TRANSACTION_MESSAGE, t.getMessage()); + } + }); + } + @Test public void testCounterCreateTableTransactionalModeFails() throws Exception { @@ -3604,4 +3632,220 @@ public abstract class AccordCQLTestBase extends AccordTestBase .hasMessage("Attempted to set an element on a list which is null"); }); } + + @Test + public void testElseIf() throws Throwable + { + test("CREATE TABLE " + qualifiedAccordTableName + " (k int PRIMARY KEY, v int) WITH " + transactionalMode.asCqlParam(), cluster -> { + String insert = "BEGIN TRANSACTION\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (1, 2);\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (2, 3);\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(insert, ConsistencyLevel.SERIAL); + + String query = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1);\n" + + " LET k2 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 2);\n" + + " IF k1.v > 5 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1;\n" + + " ELSE IF k2.v = 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 127 WHERE k = 1;\n" + + " ELSE IF k2.v = 3 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 129 WHERE k = 1;\n" + + " ELSE \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 15 WHERE k = 1;\n" + + " END IF\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(query, ConsistencyLevel.SERIAL); + + String read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1;\n" + + "COMMIT TRANSACTION"; + + SimpleQueryResult result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(1, 129); + }); + } + + @Test + public void testNoConditionsMatch() throws Throwable + { + test("CREATE TABLE " + qualifiedAccordTableName + " (k int PRIMARY KEY, v int) WITH " + transactionalMode.asCqlParam(), cluster -> { + String insert = "BEGIN TRANSACTION\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (1, 2);\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(insert, ConsistencyLevel.SERIAL); + + String query = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1);\n" + + " IF k1.v > 5 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1;\n" + + " ELSE IF k1.v != 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 127 WHERE k = 1;\n" + + " END IF\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(query, ConsistencyLevel.SERIAL); + + String read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1;\n" + + "COMMIT TRANSACTION"; + + SimpleQueryResult result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(1, 2); + }); + } + + @Test + public void testRepeatedConditionChoosesFirstOneThatMatches() throws Throwable + { + test("CREATE TABLE " + qualifiedAccordTableName + " (k int PRIMARY KEY, v int) WITH " + transactionalMode.asCqlParam(), cluster -> { + String insert = "BEGIN TRANSACTION\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (1, 2);\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(insert, ConsistencyLevel.SERIAL); + + String query = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1);\n" + + " IF k1.v = 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1;\n" + + " ELSE IF k1.v = 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 127 WHERE k = 1;\n" + + " END IF\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(query, ConsistencyLevel.SERIAL); + + String read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1;\n" + + "COMMIT TRANSACTION"; + + SimpleQueryResult result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(1, 10); + }); + } + + @Test + public void testChooseFirstConditionThatMatches() throws Throwable + { + test("CREATE TABLE " + qualifiedAccordTableName + " (k int PRIMARY KEY, v int) WITH " + transactionalMode.asCqlParam(), cluster -> { + String insert = "BEGIN TRANSACTION\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (1, 2);\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(insert, ConsistencyLevel.SERIAL); + + String query = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1);\n" + + " IF k1.v > 5 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1;\n" + + " ELSE IF k1.v = 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 127 WHERE k = 1;\n" + + " ELSE \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 15 WHERE k = 1;\n" + + " END IF\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(query, ConsistencyLevel.SERIAL); + + String read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1;\n" + + "COMMIT TRANSACTION"; + + SimpleQueryResult result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(1, 127); + }); + } + + @Test + public void testElseIFWithTrailingUpdate() throws Throwable + { + test("CREATE TABLE " + qualifiedAccordTableName + " (k int PRIMARY KEY, v int) WITH " + transactionalMode.asCqlParam(), cluster -> { + String insert = "BEGIN TRANSACTION\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (1, 2);\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (2, 3);\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(insert, ConsistencyLevel.SERIAL); + + String query = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1);\n" + + " LET k2 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 2);\n" + + " IF k1.v > 5 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1;\n" + + " ELSE IF k2.v = 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 127 WHERE k = 1;\n" + + " ELSE IF k2.v = 3 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 129 WHERE k = 1;\n" + + " ELSE \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 15 WHERE k = 1;\n" + + " END IF\n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 78 WHERE k = 2;\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(query, ConsistencyLevel.SERIAL); + + String read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1;\n" + + "COMMIT TRANSACTION"; + + SimpleQueryResult result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(1, 129); + + read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 2;\n" + + "COMMIT TRANSACTION"; + + result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(2, 78); + }); + } + + @Test + public void testIfBlockWIthMultipleUpdateStatements() throws Throwable + { + test("CREATE TABLE " + qualifiedAccordTableName + " (k int PRIMARY KEY, v int) WITH " + transactionalMode.asCqlParam(), cluster -> { + String insert = "BEGIN TRANSACTION\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (1, 2);\n" + + " INSERT INTO " + qualifiedAccordTableName + " (k, v) VALUES (2, 3);\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(insert, ConsistencyLevel.SERIAL); + + String query = "BEGIN TRANSACTION\n" + + " LET k1 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1);\n" + + " LET k2 = (SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 2);\n" + + " IF k1.v > 5 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 10 WHERE k = 1;\n" + + " ELSE IF k2.v = 2 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 127 WHERE k = 1;\n" + + " ELSE IF k2.v = 3 THEN \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 129 WHERE k = 1;\n" + + " ELSE \n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 15 WHERE k = 1;\n" + + " END IF\n" + + " UPDATE " + qualifiedAccordTableName + " SET v = 78 WHERE k = 2;\n" + + "COMMIT TRANSACTION"; + + cluster.coordinator(1).executeWithResult(query, ConsistencyLevel.SERIAL); + + String read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 1;\n" + + "COMMIT TRANSACTION"; + + SimpleQueryResult result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(1, 129); + + read = "BEGIN TRANSACTION\n" + + " SELECT * FROM " + qualifiedAccordTableName + " WHERE k = 2;\n" + + "COMMIT TRANSACTION"; + + result = cluster.coordinator(1).executeWithResult(read, ConsistencyLevel.SERIAL); + assertThat(result).hasSize(1).contains(2, 78); + }); + } }