You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ma...@apache.org on 2025/06/26 01:44:57 UTC

(cassandra) branch trunk updated: Ensuring Row reference is only used for IS Null/IS Not Null expressions

This is an automated email from the ASF dual-hosted git repository.

maxwellguo pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 4437fa4fd4 Ensuring Row reference is only used for IS Null/IS Not Null expressions
4437fa4fd4 is described below

commit 4437fa4fd42f76106493965e400cc5b79510c00a
Author: Pranav Shenoy <pr...@gmail.com>
AuthorDate: Thu Jun 26 09:32:25 2025 +0800

    Ensuring Row reference is only used for IS Null/IS Not Null expressions
    
    patch by Pranav Shenoy; reviewed by David Capwell and Maxwell Guo for CASSANDRA-20596
---
 .../cql3/transactions/ConditionStatement.java      |  4 ++
 .../cql3/statements/TransactionStatementTest.java  | 49 ++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/src/java/org/apache/cassandra/cql3/transactions/ConditionStatement.java b/src/java/org/apache/cassandra/cql3/transactions/ConditionStatement.java
index 25715b34e1..2acf247724 100644
--- a/src/java/org/apache/cassandra/cql3/transactions/ConditionStatement.java
+++ b/src/java/org/apache/cassandra/cql3/transactions/ConditionStatement.java
@@ -103,12 +103,16 @@ public class ConditionStatement
             
             if (lhs instanceof RowDataReference.Raw)
             {
+                if (((RowDataReference.Raw) lhs).column() == null)
+                    throw new IllegalStateException(String.format("Row reference (%s) can only be used with IS NULL/IS NOT NULL conditions", lhs.getText()));
                 reference = ((RowDataReference.Raw) lhs).prepareAsReceiver();
                 ColumnSpecification receiver = reference.getValueReceiver();
                 value = rhs.prepare(keyspace, receiver);
             }
             else if (rhs instanceof RowDataReference.Raw)
             {
+                if (((RowDataReference.Raw) rhs).column() == null)
+                    throw new IllegalStateException(String.format("Row reference (%s) can only be used with IS NULL/IS NOT NULL conditions", rhs.getText()));
                 reference = ((RowDataReference.Raw) rhs).prepareAsReceiver();
                 ColumnSpecification receiver = reference.getValueReceiver();
                 value = lhs.prepare(keyspace, receiver);
diff --git a/test/unit/org/apache/cassandra/cql3/statements/TransactionStatementTest.java b/test/unit/org/apache/cassandra/cql3/statements/TransactionStatementTest.java
index dd4c816e84..3395dadb1d 100644
--- a/test/unit/org/apache/cassandra/cql3/statements/TransactionStatementTest.java
+++ b/test/unit/org/apache/cassandra/cql3/statements/TransactionStatementTest.java
@@ -561,6 +561,55 @@ public class TransactionStatementTest
                 .hasMessageContaining(String.format(TRANSACTIONS_DISABLED_ON_TABLE_MESSAGE, "INSERT", "at [2:3]"));
     }
 
+    @Test
+    public void shouldRejectRowReferenceOnLHSExceptIsNullAndIsNotNull()
+    {
+        String query = "BEGIN TRANSACTION\n" +
+                       "  LET row1 = (SELECT * FROM ks.tbl1 WHERE k=1 AND c=1);\n" +
+                       "  IF row1 = 1 THEN\n" +
+                       "    UPDATE ks.tbl1 SET v=1 WHERE k=1 AND c=1;\n" +
+                       "  END IF\n" +
+                       "COMMIT TRANSACTION";
+
+        Assertions.assertThatThrownBy(() -> prepare(query))
+                  .isInstanceOf(IllegalStateException.class)
+                  .hasMessageContaining("Row reference (row1) can only be used with IS NULL/IS NOT NULL conditions");
+    }
+
+    @Test
+    public void shouldRejectRowReferenceOnRHSExceptIsNullAndIsNotNull()
+    {
+        String query = "BEGIN TRANSACTION\n" +
+                       "  LET row1 = (SELECT * FROM ks.tbl1 WHERE k=1 AND c=1);\n" +
+                       "  IF 100 = row1 THEN\n" +
+                       "    UPDATE ks.tbl1 SET v=1 WHERE k=1 AND c=1;\n" +
+                       "  END IF\n" +
+                       "COMMIT TRANSACTION";
+
+        Assertions.assertThatThrownBy(() -> prepare(query))
+                  .isInstanceOf(IllegalStateException.class)
+                  .hasMessageContaining("Row reference (row1) can only be used with IS NULL/IS NOT NULL conditions");
+    }
+
+    @Test
+    public void shouldAcceptRowReferenceWithIsNullAndIsNotNull()
+    {
+        String query = "BEGIN TRANSACTION\n" +
+                       "  LET row1 = (SELECT * FROM ks.tbl1 WHERE k=1 AND c=1);\n" +
+                       "  IF row1 IS NULL THEN\n" +
+                       "    UPDATE ks.tbl1 SET v=1 WHERE k=1 AND c=1;\n" +
+                       "  END IF\n" +
+                       "COMMIT TRANSACTION";
+        Assertions.assertThat(prepare(query)).isNotNull();
+        query = "BEGIN TRANSACTION\n" +
+                       "  LET row1 = (SELECT * FROM ks.tbl1 WHERE k=1 AND c=1);\n" +
+                       "  IF row1 IS NOT NULL THEN\n" +
+                       "    UPDATE ks.tbl1 SET v=1 WHERE k=1 AND c=1;\n" +
+                       "  END IF\n" +
+                       "COMMIT TRANSACTION";
+        Assertions.assertThat(prepare(query)).isNotNull();
+    }
+
     private static CQLStatement prepare(String query)
     {
         TransactionStatement.Parsed parsed = (TransactionStatement.Parsed) QueryProcessor.parseStatement(query);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org