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

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


The following commit(s) were added to refs/heads/trunk by this push:
     new 5e06a1f5 CONTAINS and CONTAINS KEY support for Lightweight Transactions
5e06a1f5 is described below

commit 5e06a1f5c192670b586abf8d1a68e4f884ba4e42
Author: ROCHETEAU Antoine <arochet...@jouve.com>
AuthorDate: Tue Mar 22 09:26:17 2022 +0100

    CONTAINS and CONTAINS KEY support for Lightweight Transactions
    
    patch by ROCHETEAU Antoine; reviewed by Benjamin Lerer, Berenguer Blasi for 
CASSANDRA-10537
---
 upgrade_tests/cql_tests.py | 164 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 128 insertions(+), 36 deletions(-)

diff --git a/upgrade_tests/cql_tests.py b/upgrade_tests/cql_tests.py
index cb4d5667..59e37cb1 100644
--- a/upgrade_tests/cql_tests.py
+++ b/upgrade_tests/cql_tests.py
@@ -29,7 +29,7 @@ from tools.assertions import (assert_all, assert_invalid, 
assert_length_equal,
 from tools.data import rows_to_list
 from tools.misc import add_skip
 from .upgrade_base import UpgradeTester
-from .upgrade_manifest import build_upgrade_pairs, CASSANDRA_4_0
+from .upgrade_manifest import build_upgrade_pairs, CASSANDRA_4_0, CASSANDRA_4_1
 
 since = pytest.mark.since
 logger = logging.getLogger(__name__)
@@ -4351,8 +4351,13 @@ class TestCQL(UpgradeTester):
                 cursor.execute("INSERT INTO {}(k, l) VALUES (0, ['foo', 'bar', 
'foobar'])".format(table))
 
                 def check_applies(condition):
+                    # UPDATE statement
                     assert_one(cursor, "UPDATE {} SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF {}".format(table, condition), [True], cl=self.CL)
                     assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])  # read back at default cl.one
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [True], cl=self.CL)
+                    assert_none(cursor, "SELECT * FROM {}".format(table))  # 
read back at default cl.one
+                    cursor.execute("INSERT INTO {}(k, l) VALUES (0, ['foo', 
'bar', 'foobar'])".format(table))
 
                 check_applies("l = ['foo', 'bar', 'foobar']")
                 check_applies("l != ['baz']")
@@ -4367,9 +4372,14 @@ class TestCQL(UpgradeTester):
                 check_applies("l != null AND l IN (['foo', 'bar', 'foobar'])")
 
                 def check_does_not_apply(condition):
+                    # UPDATE statement
                     assert_one(cursor, "UPDATE {} SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF {}".format(table, condition),
                                [False, ['foo', 'bar', 'foobar']], cl=self.CL)
-                    assert_one(cursor, "SELECT * FROM {}".format((table)), [0, 
['foo', 'bar', 'foobar']])  # read back at default cl.one
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])  # read back at default cl.one
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition),
+                               [False, ['foo', 'bar', 'foobar']], cl=self.CL)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])  # read back at default cl.one
 
                 # should not apply
                 check_does_not_apply("l = ['baz']")
@@ -4386,8 +4396,12 @@ class TestCQL(UpgradeTester):
                 check_does_not_apply("l > ['zzz'] AND l < ['zzz']")
 
                 def check_invalid(condition, expected=InvalidRequest):
+                    # UPDATE statement
                     assert_invalid(cursor, "UPDATE {} SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF {}".format(table, condition), expected=expected)
                     assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']], cl=self.CL)
+                    # DELETE statement
+                    assert_invalid(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']], cl=self.CL)
 
                 check_invalid("l = [null]")
                 check_invalid("l < null")
@@ -4396,10 +4410,18 @@ class TestCQL(UpgradeTester):
                 check_invalid("l >= null")
                 check_invalid("l IN null", expected=SyntaxException)
                 check_invalid("l IN 367", expected=SyntaxException)
-                check_invalid("l CONTAINS KEY 123", expected=SyntaxException)
 
-                # not supported yet
-                check_invalid("m CONTAINS 'bar'", expected=SyntaxException)
+                # @jira_ticket CASSANDRA-10537
+                if self.get_node_version(is_upgraded) >= 
LooseVersion(CASSANDRA_4_1):
+                    check_applies("l CONTAINS 'bar'")
+                    check_applies("l CONTAINS 'foo' AND l CONTAINS 'foobar'")
+                    check_does_not_apply("l CONTAINS 'baz'")
+                    check_does_not_apply("l CONTAINS 'bar' AND l CONTAINS 
'baz'")
+                    check_invalid("m CONTAINS 'bar'")
+                    check_invalid("l CONTAINS KEY 123")
+                else:
+                    check_invalid("m CONTAINS 'bar'", expected=SyntaxException)
+                    check_invalid("l CONTAINS KEY 123", 
expected=SyntaxException)
 
     @since('2.1')
     def test_list_item_conditional(self):
@@ -4467,11 +4489,17 @@ class TestCQL(UpgradeTester):
 
                 table = "frozentlist" if frozen else "tlist"
 
-                cursor.execute("INSERT INTO %s(k, l) VALUES (0, ['foo', 'bar', 
'foobar'])" % (table,))
+                cursor.execute("INSERT INTO {}(k, l) VALUES (0, ['foo', 'bar', 
'foobar'])".format(table,))
 
                 def check_applies(condition):
-                    assert_one(cursor, "UPDATE %s SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF %s" % (table, condition), [True])
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
['foo', 'bar', 'foobar']])
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF {}".format(table, condition), [True])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [True])
+                    assert_none(cursor, "SELECT * FROM {}".format(table), 
cl=ConsistencyLevel.SERIAL)
+                    cursor.execute("INSERT INTO {}(k, l) VALUES (0, ['foo', 
'bar', 'foobar'])".format(table,))
+
 
                 check_applies("l[1] < 'zzz'")
                 check_applies("l[1] <= 'bar'")
@@ -4487,8 +4515,12 @@ class TestCQL(UpgradeTester):
                 check_applies("l[3] IN (null, 'xxx', 'bar')")
 
                 def check_does_not_apply(condition):
-                    assert_one(cursor, "UPDATE %s SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF %s" % (table, condition), [False, ['foo', 'bar', 
'foobar']])
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
['foo', 'bar', 'foobar']])
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF {}".format(table, condition), [False, ['foo', 'bar', 
'foobar']])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [False, ['foo', 'bar', 'foobar']])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])
 
                 check_does_not_apply("l[1] < 'aaa'")
                 check_does_not_apply("l[1] <= 'aaa'")
@@ -4504,8 +4536,12 @@ class TestCQL(UpgradeTester):
                 check_does_not_apply("l[3] = 'xxx'")
 
                 def check_invalid(condition, expected=InvalidRequest):
-                    assert_invalid(cursor, "UPDATE %s SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF %s" % (table, condition), expected=expected)
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
['foo', 'bar', 'foobar']])
+                    # UPDATE statement
+                    assert_invalid(cursor, "UPDATE {} SET l = ['foo', 'bar', 
'foobar'] WHERE k=0 IF {}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])
+                    # DELETE statement
+                    assert_invalid(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
['foo', 'bar', 'foobar']])
 
                 check_invalid("l[1] < null")
                 check_invalid("l[1] <= null")
@@ -4542,11 +4578,16 @@ class TestCQL(UpgradeTester):
             for frozen in (False, True):
 
                 table = "frozentset" if frozen else "tset"
-                assert_one(cursor, "INSERT INTO %s(k, s) VALUES (0, {'bar', 
'foo'}) IF NOT EXISTS" % (table,), [True])
+                assert_one(cursor, "INSERT INTO {}(k, s) VALUES (0, {{'bar', 
'foo'}}) IF NOT EXISTS".format(table), [True])
 
                 def check_applies(condition):
-                    assert_one(cursor, "UPDATE %s SET s = {'bar', 'foo'} WHERE 
k=0 IF %s" % (table, condition), [True])
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
set(['bar', 'foo'])], cl=ConsistencyLevel.SERIAL)
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET s = {{'bar', 'foo'}} 
WHERE k=0 IF {}".format(table, condition), [True])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [True])
+                    assert_none(cursor, "SELECT * FROM {}".format(table), 
cl=ConsistencyLevel.SERIAL)
+                    assert_one(cursor, "INSERT INTO {}(k, s) VALUES (0, 
{{'bar', 'foo'}}) IF NOT EXISTS".format(table), [True])
 
                 check_applies("s = {'bar', 'foo'}")
                 check_applies("s = {'foo', 'bar'}")
@@ -4562,9 +4603,14 @@ class TestCQL(UpgradeTester):
                 check_applies("s IN (null, {'bar', 'foo'}, {'a'}) AND s IN 
({'a'}, {'bar', 'foo'}, null)")
 
                 def check_does_not_apply(condition):
-                    assert_one(cursor, "UPDATE %s SET s = {'bar', 'foo'} WHERE 
k=0 IF %s" % (table, condition),
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET s = {{'bar', 'foo'}} 
WHERE k=0 IF {}".format(table, condition),
                                [False, {'bar', 'foo'}])
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition),
+                               [False, {'bar', 'foo'}])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
 
                 # should not apply
                 check_does_not_apply("s = {'baz'}")
@@ -4578,8 +4624,12 @@ class TestCQL(UpgradeTester):
                 check_does_not_apply("s != null AND s IN ()")
 
                 def check_invalid(condition, expected=InvalidRequest):
-                    assert_invalid(cursor, "UPDATE %s SET s = {'bar', 'foo'} 
WHERE k=0 IF %s" % (table, condition), expected=expected)
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
+                    # UPDATE statement
+                    assert_invalid(cursor, "UPDATE {} SET s = {{'bar', 'foo'}} 
WHERE k=0 IF {}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_invalid(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'bar', 'foo'}], cl=ConsistencyLevel.SERIAL)
 
                 check_invalid("s = {null}")
                 check_invalid("s < null")
@@ -4588,13 +4638,20 @@ class TestCQL(UpgradeTester):
                 check_invalid("s >= null")
                 check_invalid("s IN null", expected=SyntaxException)
                 check_invalid("s IN 367", expected=SyntaxException)
-                check_invalid("s CONTAINS KEY 123", expected=SyntaxException)
 
                 # element access is not allow for sets
                 check_invalid("s['foo'] = 'foobar'")
 
-                # not supported yet
-                check_invalid("m CONTAINS 'bar'", expected=SyntaxException)
+                # @jira_ticket CASSANDRA-10537
+                if self.get_node_version(is_upgraded) >= 
LooseVersion(CASSANDRA_4_1):
+                    check_applies("s CONTAINS 'foo'")
+                    check_applies("s CONTAINS 'foo' AND s CONTAINS 'bar'")
+                    check_does_not_apply("s CONTAINS 'baz'")
+                    check_invalid("s CONTAINS null")
+                    check_invalid("s CONTAINS KEY 123")
+                else:
+                    check_invalid("s CONTAINS null", expected=SyntaxException)
+                    check_invalid("s CONTAINS KEY 123", 
expected=SyntaxException)
 
     @since('2.1.1')
     def test_whole_map_conditional(self):
@@ -4624,8 +4681,13 @@ class TestCQL(UpgradeTester):
                 cursor.execute("INSERT INTO %s(k, m) VALUES (0, {'foo' : 
'bar'})" % (table,))
 
                 def check_applies(condition):
-                    assert_one(cursor, "UPDATE %s SET m = {'foo': 'bar'} WHERE 
k=0 IF %s" % (table, condition), [True])
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET m = {{'foo': 'bar'}} 
WHERE k=0 IF {}".format(table, condition), [True])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [True])
+                    assert_none(cursor, "SELECT * FROM {}".format(table), 
cl=ConsistencyLevel.SERIAL)
+                    cursor.execute("INSERT INTO {}(k, m) VALUES (0, {{'foo' : 
'bar'}})".format(table))
 
                 check_applies("m = {'foo': 'bar'}")
                 check_applies("m > {'a': 'a'}")
@@ -4640,8 +4702,12 @@ class TestCQL(UpgradeTester):
                 check_applies("m != null AND m IN (null, {'a': 'a'}, {'foo': 
'bar'})")
 
                 def check_does_not_apply(condition):
-                    assert_one(cursor, "UPDATE %s SET m = {'foo': 'bar'} WHERE 
k=0 IF %s" % (table, condition), [False, {'foo': 'bar'}])
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET m = {{'foo': 'bar'}} 
WHERE k=0 IF {}".format(table, condition), [False, {'foo': 'bar'}])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [False, {'foo': 'bar'}])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
 
                 # should not apply
                 check_does_not_apply("m = {'a': 'a'}")
@@ -4655,8 +4721,12 @@ class TestCQL(UpgradeTester):
                 check_does_not_apply("m = null AND m != null")
 
                 def check_invalid(condition, expected=InvalidRequest):
-                    assert_invalid(cursor, "UPDATE %s SET m = {'foo': 'bar'} 
WHERE k=0 IF %s" % (table, condition), expected=expected)
-                    assert_one(cursor, "SELECT * FROM %s" % (table,), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # UPDATE statement
+                    assert_invalid(cursor, "UPDATE {} SET m = {{'foo': 'bar'}} 
WHERE k=0 IF {}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_invalid(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
 
                 check_invalid("m = {null: null}")
                 check_invalid("m = {'a': null}")
@@ -4664,11 +4734,20 @@ class TestCQL(UpgradeTester):
                 check_invalid("m < null")
                 check_invalid("m IN null", expected=SyntaxException)
 
-                # not supported yet
-                check_invalid("m CONTAINS 'bar'", expected=SyntaxException)
-                check_invalid("m CONTAINS KEY 'foo'", expected=SyntaxException)
-                check_invalid("m CONTAINS null", expected=SyntaxException)
-                check_invalid("m CONTAINS KEY null", expected=SyntaxException)
+                # @jira_ticket CASSANDRA-10537
+                if self.get_node_version(is_upgraded) >= 
LooseVersion(CASSANDRA_4_1):
+                    check_applies("m CONTAINS 'bar'")
+                    check_applies("m CONTAINS KEY 'foo'")
+                    check_applies("m CONTAINS 'bar' AND m CONTAINS KEY 'foo'")
+                    check_does_not_apply("m CONTAINS 'foo'")
+                    check_does_not_apply("m CONTAINS KEY 'bar'")
+                    check_invalid("m CONTAINS null")
+                    check_invalid("m CONTAINS KEY null")
+                else:
+                    check_invalid("m CONTAINS 'bar'", expected=SyntaxException)
+                    check_invalid("m CONTAINS KEY 'foo'", 
expected=SyntaxException)
+                    check_invalid("m CONTAINS null", expected=SyntaxException)
+                    check_invalid("m CONTAINS KEY null", 
expected=SyntaxException)
 
     @since('2.1')
     def test_map_item_conditional(self):
@@ -4742,8 +4821,13 @@ class TestCQL(UpgradeTester):
                 cursor.execute("INSERT INTO %s (k, m) VALUES (0, {'foo' : 
'bar'})" % table)
 
                 def check_applies(condition):
-                    assert_one(cursor, "UPDATE %s SET m = {'foo': 'bar'} WHERE 
k=0 IF %s" % (table, condition), [True])
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET m = {{'foo': 'bar'}} 
WHERE k=0 IF {}".format(table, condition), [True])
                     assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [True])
+                    assert_none(cursor, "SELECT * FROM {}".format(table), 
cl=ConsistencyLevel.SERIAL)
+                    cursor.execute("INSERT INTO {} (k, m) VALUES (0, {{'foo' : 
'bar'}})".format(table))
 
                 check_applies("m['xxx'] = null")
                 check_applies("m['foo'] < 'zzz'")
@@ -4759,7 +4843,11 @@ class TestCQL(UpgradeTester):
                 check_applies("m['foo'] < 'zzz' AND m['foo'] > 'aaa'")
 
                 def check_does_not_apply(condition):
-                    assert_one(cursor, "UPDATE %s SET m = {'foo': 'bar'} WHERE 
k=0 IF %s" % (table, condition), [False, {'foo': 'bar'}])
+                    # UPDATE statement
+                    assert_one(cursor, "UPDATE {} SET m = {{'foo': 'bar'}} 
WHERE k=0 IF {}".format(table, condition), [False, {'foo': 'bar'}])
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
+                    # DELETE statement
+                    assert_one(cursor, "DELETE FROM {} WHERE k=0 IF 
{}".format(table, condition), [False, {'foo': 'bar'}])
                     assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}], cl=ConsistencyLevel.SERIAL)
 
                 check_does_not_apply("m['foo'] < 'aaa'")
@@ -4773,7 +4861,11 @@ class TestCQL(UpgradeTester):
                 check_does_not_apply("m['foo'] != null AND m['foo'] = null")
 
                 def check_invalid(condition, expected=InvalidRequest):
-                    assert_invalid(cursor, "UPDATE %s SET m = {'foo': 'bar'} 
WHERE k=0 IF %s" % (table, condition), expected=expected)
+                    # UPDATE statement
+                    assert_invalid(cursor, "UPDATE {} SET m = {{'foo': 'bar'}} 
WHERE k=0 IF {}".format(table, condition), expected=expected)
+                    assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}])
+                    # DELETE statement
+                    assert_invalid(cursor, "DELETE FROM {} WHERE k=0 IF  
{}".format(table, condition), expected=expected)
                     assert_one(cursor, "SELECT * FROM {}".format(table), [0, 
{'foo': 'bar'}])
 
                 check_invalid("m['foo'] < null")


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

Reply via email to