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
This commit is contained in:
Pranav Shenoy 2025-06-26 09:32:25 +08:00 committed by Maxwell Guo
parent 15ded6a68d
commit 4437fa4fd4
2 changed files with 53 additions and 0 deletions

View File

@ -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);

View File

@ -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);