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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]